/ Check-in [6994826c]
Login

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

Overview
Comment:Merge the latest trunk changes into the sessions branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: 6994826c0784280f2e9728dfa4185848846d03df
User & Date: drh 2013-04-22 23:59:06
Context
2013-05-03
18:29
Merge all recent trunk changes into the sessions branch. check-in: 3879ab1b user: drh tags: sessions
2013-04-22
23:59
Merge the latest trunk changes into the sessions branch. check-in: 6994826c user: drh tags: sessions
23:38
Fix harmless compiler warnings. check-in: 1a1cf5aa user: drh tags: trunk
2013-04-12
13:53
Fix the xCheckReservedLock() method on the windows VFS so that it cannot return a false positive when two or more processes use it at the same time on the same file. Ticket [7ff3120e4fa54abb55]. Update to version 3.7.16.2. check-in: 67b3c0ef user: drh tags: sessions
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

165
166
167
168
169
170
171

172
173
174
175
176
177
178
...
315
316
317
318
319
320
321

322
323
324
325
326
327
328
...
506
507
508
509
510
511
512





513
514
515
516
517
518
519
...
859
860
861
862
863
864
865



866
867
868
869
870
871
872
...
955
956
957
958
959
960
961


962
963

964
965
966
967
968
969
970
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
         backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
         callback.lo complete.lo ctime.lo date.lo delete.lo \
         expr.lo fault.lo fkey.lo \
         fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
         fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \

         fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
         func.lo global.lo hash.lo \
         icu.lo insert.lo journal.lo legacy.lo loadext.lo \
         main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
         memjournal.lo \
         mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
         notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
................................................................................
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_icu.c \
  $(TOP)/ext/fts3/fts3_porter.c \
  $(TOP)/ext/fts3/fts3_snippet.c \
  $(TOP)/ext/fts3/fts3_tokenizer.h \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_tokenizer1.c \

  $(TOP)/ext/fts3/fts3_unicode.c \
  $(TOP)/ext/fts3/fts3_unicode2.c \
  $(TOP)/ext/fts3/fts3_write.c
SRC += \
  $(TOP)/ext/icu/sqliteicu.h \
  $(TOP)/ext/icu/icu.c
SRC += \
................................................................................
		-version-info "8:6:8" \
		-avoid-version

sqlite3$(TEXE):	$(TOP)/src/shell.c libsqlite3.la sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) \
		-o $@ $(TOP)/src/shell.c libsqlite3.la \
		$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"






# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
#
................................................................................

fts3_tokenizer.lo:	$(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c

fts3_tokenizer1.lo:	$(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c




fts3_unicode.lo:	$(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c

fts3_unicode2.lo:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c

fts3_write.lo:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
................................................................................
	rm -f *.da *.bb *.bbg gmon.out
	rm -rf quota2a quota2b quota2c
	rm -rf tsrc .target_source
	rm -f tclsqlite3$(TEXE)
	rm -f testfixture$(TEXE) test.db
	rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
	rm -f sqlite3.c


	rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
	rm -f sqlite-*-output.vsix


distclean:	clean
	rm -f config.log config.status libtool Makefile sqlite3.pc

#
# Windows section
#







>







 







>







 







>
>
>
>
>







 







>
>
>







 







>
>


>







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
...
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
         backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
         callback.lo complete.lo ctime.lo date.lo delete.lo \
         expr.lo fault.lo fkey.lo \
         fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
         fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
         fts3_tokenize_vtab.lo \
         fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
         func.lo global.lo hash.lo \
         icu.lo insert.lo journal.lo legacy.lo loadext.lo \
         main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
         memjournal.lo \
         mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
         notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
................................................................................
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_icu.c \
  $(TOP)/ext/fts3/fts3_porter.c \
  $(TOP)/ext/fts3/fts3_snippet.c \
  $(TOP)/ext/fts3/fts3_tokenizer.h \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_tokenizer1.c \
  $(TOP)/ext/fts3/fts3_tokenize_vtab.c \
  $(TOP)/ext/fts3/fts3_unicode.c \
  $(TOP)/ext/fts3/fts3_unicode2.c \
  $(TOP)/ext/fts3/fts3_write.c
SRC += \
  $(TOP)/ext/icu/sqliteicu.h \
  $(TOP)/ext/icu/icu.c
SRC += \
................................................................................
		-version-info "8:6:8" \
		-avoid-version

sqlite3$(TEXE):	$(TOP)/src/shell.c libsqlite3.la sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) \
		-o $@ $(TOP)/src/shell.c libsqlite3.la \
		$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"

mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
	$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
		$(TLIBS) -rpath "$(libdir)"


# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
#
................................................................................

fts3_tokenizer.lo:	$(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c

fts3_tokenizer1.lo:	$(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c

fts3_tokenizer_vtab.lo:	$(TOP)/ext/fts3/fts3_tokenizer_vtab.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer_vtab.c

fts3_unicode.lo:	$(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c

fts3_unicode2.lo:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c

fts3_write.lo:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
................................................................................
	rm -f *.da *.bb *.bbg gmon.out
	rm -rf quota2a quota2b quota2c
	rm -rf tsrc .target_source
	rm -f tclsqlite3$(TEXE)
	rm -f testfixture$(TEXE) test.db
	rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
	rm -f sqlite3.c
	rm -f sqlite3rc.h
	rm -f shell.c sqlite3ext.h
	rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
	rm -f sqlite-*-output.vsix
	rm -f mptester mptester.exe

distclean:	clean
	rm -f config.log config.status libtool Makefile sqlite3.pc

#
# Windows section
#

Changes to Makefile.msc.

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
...
639
640
641
642
643
644
645

646
647
648
649
650
651
652
...
754
755
756
757
758
759
760

761
762
763
764
765
766
767
...
828
829
830
831
832
833
834




835
836
837
838
839
840
841
....
1188
1189
1190
1191
1192
1193
1194



1195
1196
1197
1198
1199
1200
1201
....
1269
1270
1271
1272
1273
1274
1275

1276
1277

1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
         backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
         callback.lo complete.lo ctime.lo date.lo delete.lo \
         expr.lo fault.lo fkey.lo \
         fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
         fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
         fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
         func.lo global.lo hash.lo \
         icu.lo insert.lo journal.lo legacy.lo loadext.lo \
         main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
         memjournal.lo \
         mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
         notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
         pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
................................................................................
  $(TOP)\ext\fts3\fts3_hash.h \
  $(TOP)\ext\fts3\fts3_icu.c \
  $(TOP)\ext\fts3\fts3_porter.c \
  $(TOP)\ext\fts3\fts3_snippet.c \
  $(TOP)\ext\fts3\fts3_tokenizer.h \
  $(TOP)\ext\fts3\fts3_tokenizer.c \
  $(TOP)\ext\fts3\fts3_tokenizer1.c \

  $(TOP)\ext\fts3\fts3_unicode.c \
  $(TOP)\ext\fts3\fts3_unicode2.c \
  $(TOP)\ext\fts3\fts3_write.c
SRC = $(SRC) \
  $(TOP)\ext\icu\sqliteicu.h \
  $(TOP)\ext\icu\icu.c
SRC = $(SRC) \
................................................................................
  $(TOP)\src\vdbetrace.c \
  $(TOP)\src\where.c \
  parse.c \
  $(TOP)\ext\fts3\fts3.c \
  $(TOP)\ext\fts3\fts3_aux.c \
  $(TOP)\ext\fts3\fts3_expr.c \
  $(TOP)\ext\fts3\fts3_tokenizer.c \

  $(TOP)\ext\fts3\fts3_unicode.c \
  $(TOP)\ext\fts3\fts3_unicode2.c \
  $(TOP)\ext\fts3\fts3_write.c \
  $(TOP)\ext\async\sqlite3async.c \
  $(TOP)\ext\session\sqlite3session.c

# Source code to the library files needed by the test fixture
................................................................................
	$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)

sqlite3.exe:	$(TOP)\src\shell.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) \
		$(TOP)\src\shell.c \
		/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)





# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
#
.target_source:	$(SRC) $(TOP)\tool\vdbe-compress.tcl
................................................................................

fts3_tokenizer.lo:	$(TOP)\ext\fts3\fts3_tokenizer.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c

fts3_tokenizer1.lo:	$(TOP)\ext\fts3\fts3_tokenizer1.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c




fts3_unicode.lo:	$(TOP)\ext\fts3\fts3_unicode.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c

fts3_unicode2.lo:	$(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c

fts3_write.lo:	$(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
................................................................................
	-rmdir /Q/S tsrc
	del /Q .target_source
	del /Q tclsqlite3.exe tclsqlite3.exp
	del /Q testfixture.exe testfixture.exp test.db
	del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
	del /Q sqlite3.c
	del /Q sqlite3rc.h

	del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c
	del /Q sqlite-*-output.vsix


# Dynamic link library section.
#
dll: sqlite3.dll

sqlite3.def: libsqlite3.lib
	echo EXPORTS > sqlite3.def
	dumpbin /all libsqlite3.lib \
		| $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
		| sort >> sqlite3.def

sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) sqlite3.def
	$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)







|







 







>







 







>







 







>
>
>
>







 







>
>
>







 







>


>













478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
...
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
....
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
....
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
         backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
         callback.lo complete.lo ctime.lo date.lo delete.lo \
         expr.lo fault.lo fkey.lo \
         fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
         fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
         fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
         func.lo global.lo hash.lo \
         icu.lo insert.lo journal.lo legacy.lo loadext.lo \
         main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
         memjournal.lo \
         mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
         notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
         pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
................................................................................
  $(TOP)\ext\fts3\fts3_hash.h \
  $(TOP)\ext\fts3\fts3_icu.c \
  $(TOP)\ext\fts3\fts3_porter.c \
  $(TOP)\ext\fts3\fts3_snippet.c \
  $(TOP)\ext\fts3\fts3_tokenizer.h \
  $(TOP)\ext\fts3\fts3_tokenizer.c \
  $(TOP)\ext\fts3\fts3_tokenizer1.c \
  $(TOP)\ext\fts3\fts3_tokenize_vtab.c \
  $(TOP)\ext\fts3\fts3_unicode.c \
  $(TOP)\ext\fts3\fts3_unicode2.c \
  $(TOP)\ext\fts3\fts3_write.c
SRC = $(SRC) \
  $(TOP)\ext\icu\sqliteicu.h \
  $(TOP)\ext\icu\icu.c
SRC = $(SRC) \
................................................................................
  $(TOP)\src\vdbetrace.c \
  $(TOP)\src\where.c \
  parse.c \
  $(TOP)\ext\fts3\fts3.c \
  $(TOP)\ext\fts3\fts3_aux.c \
  $(TOP)\ext\fts3\fts3_expr.c \
  $(TOP)\ext\fts3\fts3_tokenizer.c \
  $(TOP)\ext\fts3\fts3_tokenize_vtab.c \
  $(TOP)\ext\fts3\fts3_unicode.c \
  $(TOP)\ext\fts3\fts3_unicode2.c \
  $(TOP)\ext\fts3\fts3_write.c \
  $(TOP)\ext\async\sqlite3async.c \
  $(TOP)\ext\session\sqlite3session.c

# Source code to the library files needed by the test fixture
................................................................................
	$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)

sqlite3.exe:	$(TOP)\src\shell.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) \
		$(TOP)\src\shell.c \
		/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)

mptester.exe:	$(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
	$(LTLINK) $(TOP)\mptest\mptest.c \
		/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)

# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
#
.target_source:	$(SRC) $(TOP)\tool\vdbe-compress.tcl
................................................................................

fts3_tokenizer.lo:	$(TOP)\ext\fts3\fts3_tokenizer.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c

fts3_tokenizer1.lo:	$(TOP)\ext\fts3\fts3_tokenizer1.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c

fts3_tokenize_vtab.lo:	$(TOP)\ext\fts3\fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenize_vtab.c

fts3_unicode.lo:	$(TOP)\ext\fts3\fts3_unicode.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c

fts3_unicode2.lo:	$(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c

fts3_write.lo:	$(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
................................................................................
	-rmdir /Q/S tsrc
	del /Q .target_source
	del /Q tclsqlite3.exe tclsqlite3.exp
	del /Q testfixture.exe testfixture.exp test.db
	del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
	del /Q sqlite3.c
	del /Q sqlite3rc.h
	del /Q shell.c sqlite3ext.h
	del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c
	del /Q sqlite-*-output.vsix
	del /Q mptester.exe

# Dynamic link library section.
#
dll: sqlite3.dll

sqlite3.def: libsqlite3.lib
	echo EXPORTS > sqlite3.def
	dumpbin /all libsqlite3.lib \
		| $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
		| sort >> sqlite3.def

sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) sqlite3.def
	$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)

Changes to Makefile.vxworks.

658
659
660
661
662
663
664


665
	rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h
	rm -f $(PUBLISH)
	rm -f *.da *.bb *.bbg gmon.out
	rm -rf quota2a quota2b quota2c
	rm -rf tsrc target_source
	rm -f testloadext.dll libtestloadext.so
	rm -f sqlite3.c fts?amal.c tclsqlite3.c


	rm -f $(SHPREFIX)sqlite3.$(SO)







>
>

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

Changes to ext/fts3/fts3.c.

3589
3590
3591
3592
3593
3594
3595



3596
3597
3598
3599
3600
3601
3602
  rc = sqlite3Fts3InitTerm(db);
  if( rc!=SQLITE_OK ) return rc;
#endif

  rc = sqlite3Fts3InitAux(db);
  if( rc!=SQLITE_OK ) return rc;




  sqlite3Fts3SimpleTokenizerModule(&pSimple);
  sqlite3Fts3PorterTokenizerModule(&pPorter);

  /* Allocate and initialize the hash-table used to store tokenizers. */
  pHash = sqlite3_malloc(sizeof(Fts3Hash));
  if( !pHash ){
    rc = SQLITE_NOMEM;







>
>
>







3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
  rc = sqlite3Fts3InitTerm(db);
  if( rc!=SQLITE_OK ) return rc;
#endif

  rc = sqlite3Fts3InitAux(db);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3Fts3InitTok(db);
  if( rc!=SQLITE_OK ) return rc;

  sqlite3Fts3SimpleTokenizerModule(&pSimple);
  sqlite3Fts3PorterTokenizerModule(&pPorter);

  /* Allocate and initialize the hash-table used to store tokenizers. */
  pHash = sqlite3_malloc(sizeof(Fts3Hash));
  if( !pHash ){
    rc = SQLITE_NOMEM;

Changes to ext/fts3/fts3Int.h.

545
546
547
548
549
550
551



552
553
554
555
556
557
558
559
560
    Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
int sqlite3Fts3MsrIncrNext(
    Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); 
int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);




/* fts3_unicode2.c (functions generated by parsing unicode text files) */
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
int sqlite3FtsUnicodeFold(int, int);
int sqlite3FtsUnicodeIsalnum(int);
int sqlite3FtsUnicodeIsdiacritic(int);
#endif

#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */







>
>
>









545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
    Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
int sqlite3Fts3MsrIncrNext(
    Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); 
int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);

/* fts3_tokenize_vtab.c */
int sqlite3Fts3InitTok(sqlite3*);

/* fts3_unicode2.c (functions generated by parsing unicode text files) */
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
int sqlite3FtsUnicodeFold(int, int);
int sqlite3FtsUnicodeIsalnum(int);
int sqlite3FtsUnicodeIsdiacritic(int);
#endif

#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

Changes to ext/fts3/fts3_aux.c.

66
67
68
69
70
71
72
73




74
75
76
77
78
79
80
81
82









83

84
85
86
87
88
89
90
..
99
100
101
102
103
104
105




106
107
108
109
110
111
112
  int nFts3;                      /* Result of strlen(zFts3) */
  int nByte;                      /* Bytes of space to allocate here */
  int rc;                         /* value returned by declare_vtab() */
  Fts3auxTable *p;                /* Virtual table object to return */

  UNUSED_PARAMETER(pUnused);

  /* The user should specify a single argument - the name of an fts3 table. */




  if( argc!=4 ){
    *pzErr = sqlite3_mprintf(
        "wrong number of arguments to fts4aux constructor"
    );
    return SQLITE_ERROR;
  }

  zDb = argv[1]; 
  nDb = (int)strlen(zDb);









  zFts3 = argv[3];

  nFts3 = (int)strlen(zFts3);

  rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
  if( rc!=SQLITE_OK ) return rc;

  nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
  p = (Fts3auxTable *)sqlite3_malloc(nByte);
................................................................................

  memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
  memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
  sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);

  *ppVtab = (sqlite3_vtab *)p;
  return SQLITE_OK;




}

/*
** This function does the work for both the xDisconnect and xDestroy methods.
** These tables have no persistent representation of their own, so xDisconnect
** and xDestroy are identical operations.
*/







|
>
>
>
>
|
<
<
<
<
|
<


>
>
>
>
>
>
>
>
>
|
>







 







>
>
>
>







66
67
68
69
70
71
72
73
74
75
76
77
78




79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  int nFts3;                      /* Result of strlen(zFts3) */
  int nByte;                      /* Bytes of space to allocate here */
  int rc;                         /* value returned by declare_vtab() */
  Fts3auxTable *p;                /* Virtual table object to return */

  UNUSED_PARAMETER(pUnused);

  /* The user should invoke this in one of two forms:
  **
  **     CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table);
  **     CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table);
  */
  if( argc!=4 && argc!=5 ) goto bad_args;






  zDb = argv[1]; 
  nDb = (int)strlen(zDb);
  if( argc==5 ){
    if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){
      zDb = argv[3]; 
      nDb = (int)strlen(zDb);
      zFts3 = argv[4];
    }else{
      goto bad_args;
    }
  }else{
    zFts3 = argv[3];
  }
  nFts3 = (int)strlen(zFts3);

  rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
  if( rc!=SQLITE_OK ) return rc;

  nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
  p = (Fts3auxTable *)sqlite3_malloc(nByte);
................................................................................

  memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
  memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
  sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);

  *ppVtab = (sqlite3_vtab *)p;
  return SQLITE_OK;

 bad_args:
  *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor");
  return SQLITE_ERROR;
}

/*
** This function does the work for both the xDisconnect and xDestroy methods.
** These tables have no persistent representation of their own, so xDisconnect
** and xDestroy are identical operations.
*/

Added ext/fts3/fts3_tokenize_vtab.c.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
/*
** 2013 Apr 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code for the "fts3tokenize" virtual table module.
** An fts3tokenize virtual table is created as follows:
**
**   CREATE VIRTUAL TABLE <tbl> USING fts3tokenize(
**       <tokenizer-name>, <arg-1>, ...
**   );
**
** The table created has the following schema:
**
**   CREATE TABLE <tbl>(input, token, start, end, position)
**
** When queried, the query must include a WHERE clause of type:
**
**   input = <string>
**
** The virtual table module tokenizes this <string>, using the FTS3 
** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE 
** statement and returns one row for each token in the result. With
** fields set as follows:
**
**   input:   Always set to a copy of <string>
**   token:   A token from the input.
**   start:   Byte offset of the token within the input <string>.
**   end:     Byte offset of the byte immediately following the end of the
**            token within the input string.
**   pos:     Token offset of token within input.
**
*/
#include "fts3Int.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

#include <string.h>
#include <assert.h>

typedef struct Fts3tokTable Fts3tokTable;
typedef struct Fts3tokCursor Fts3tokCursor;

/*
** Virtual table structure.
*/
struct Fts3tokTable {
  sqlite3_vtab base;              /* Base class used by SQLite core */
  const sqlite3_tokenizer_module *pMod;
  sqlite3_tokenizer *pTok;
};

/*
** Virtual table cursor structure.
*/
struct Fts3tokCursor {
  sqlite3_vtab_cursor base;       /* Base class used by SQLite core */
  char *zInput;                   /* Input string */
  sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */
  int iRowid;                     /* Current 'rowid' value */
  const char *zToken;             /* Current 'token' value */
  int nToken;                     /* Size of zToken in bytes */
  int iStart;                     /* Current 'start' value */
  int iEnd;                       /* Current 'end' value */
  int iPos;                       /* Current 'pos' value */
};

/*
** Query FTS for the tokenizer implementation named zName.
*/
static int fts3tokQueryTokenizer(
  sqlite3 *db,
  const char *zName,
  const sqlite3_tokenizer_module **pp
){
  int rc;
  sqlite3_stmt *pStmt;
  const char *zSql = "SELECT fts3_tokenizer(?)";

  *pp = 0;
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
    if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
      memcpy((void*)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
    }
  }

  return sqlite3_finalize(pStmt);
}

/*
** The second argument, argv[], is an array of pointers to nul-terminated
** strings. This function makes a copy of the array and strings into a 
** single block of memory. It then dequotes any of the strings that appear
** to be quoted.
**
** If successful, output parameter *pazDequote is set to point at the
** array of dequoted strings and SQLITE_OK is returned. The caller is
** responsible for eventually calling sqlite3_free() to free the array
** in this case. Or, if an error occurs, an SQLite error code is returned.
** The final value of *pazDequote is undefined in this case.
*/
static int fts3tokDequoteArray(
  int argc,                       /* Number of elements in argv[] */
  const char * const *argv,       /* Input array */
  char ***pazDequote              /* Output array */
){
  int rc = SQLITE_OK;             /* Return code */
  if( argc==0 ){
    *pazDequote = 0;
  }else{
    int i;
    int nByte = 0;
    char **azDequote;

    for(i=0; i<argc; i++){
      nByte += (int)(strlen(argv[i]) + 1);
    }

    *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
    if( azDequote==0 ){
      rc = SQLITE_NOMEM;
    }else{
      char *pSpace = (char *)&azDequote[argc];
      for(i=0; i<argc; i++){
        int n = (int)strlen(argv[i]);
        azDequote[i] = pSpace;
        memcpy(pSpace, argv[i], n+1);
        sqlite3Fts3Dequote(pSpace);
        pSpace += (n+1);
      }
    }
  }

  return rc;
}

/*
** Schema of the tokenizer table.
*/
#define FTS3_TOK_SCHEMA "CREATE TABLE x(input, token, start, end, position)"

/*
** This function does all the work for both the xConnect and xCreate methods.
** These tables have no persistent representation of their own, so xConnect
** and xCreate are identical operations.
**
**   argv[0]: module name
**   argv[1]: database name 
**   argv[2]: table name
**   argv[3]: first argument (tokenizer name)
*/
static int fts3tokConnectMethod(
  sqlite3 *db,                    /* Database connection */
  void *pUnused,                  /* Unused */
  int argc,                       /* Number of elements in argv array */
  const char * const *argv,       /* xCreate/xConnect argument array */
  sqlite3_vtab **ppVtab,          /* OUT: New sqlite3_vtab object */
  char **pzErr                    /* OUT: sqlite3_malloc'd error message */
){
  Fts3tokTable *pTab;
  const sqlite3_tokenizer_module *pMod = 0;
  sqlite3_tokenizer *pTok = 0;
  int rc;
  char **azDequote = 0;
  int nDequote;
  UNUSED_PARAMETER(pUnused);

  rc = sqlite3_declare_vtab(db, FTS3_TOK_SCHEMA);
  if( rc!=SQLITE_OK ) return rc;

  nDequote = argc-3;
  rc = fts3tokDequoteArray(nDequote, &argv[3], &azDequote);

  if( rc==SQLITE_OK ){
    const char *zModule;
    if( nDequote<1 ){
      zModule = "simple";
    }else{
      zModule = azDequote[0];
    }
    rc = fts3tokQueryTokenizer(db, zModule, &pMod);
  }

  if( rc!=SQLITE_OK ){
    *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
  }else if( pMod==0 ){
    rc = SQLITE_ERROR;
  }else{
    const char * const *azArg = (const char * const *)&azDequote[1];
    rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok);
  }

  if( rc==SQLITE_OK ){
    pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable));
    if( pTab==0 ){
      rc = SQLITE_NOMEM;
    }
  }

  if( rc==SQLITE_OK ){
    memset(pTab, 0, sizeof(Fts3tokTable));
    pTab->pMod = pMod;
    pTab->pTok = pTok;
    *ppVtab = &pTab->base;
  }else{
    if( pTok ){
      pMod->xDestroy(pTok);
    }
  }

  sqlite3_free(azDequote);
  return rc;
}

/*
** This function does the work for both the xDisconnect and xDestroy methods.
** These tables have no persistent representation of their own, so xDisconnect
** and xDestroy are identical operations.
*/
static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){
  Fts3tokTable *pTab = (Fts3tokTable *)pVtab;

  pTab->pMod->xDestroy(pTab->pTok);
  sqlite3_free(pTab);
  return SQLITE_OK;
}

/*
** xBestIndex - Analyze a WHERE and ORDER BY clause.
*/
static int fts3tokBestIndexMethod(
  sqlite3_vtab *pVTab, 
  sqlite3_index_info *pInfo
){
  int i;
  UNUSED_PARAMETER(pVTab);

  for(i=0; i<pInfo->nConstraint; i++){
    if( pInfo->aConstraint[i].usable 
     && pInfo->aConstraint[i].iColumn==0 
     && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ 
    ){
      pInfo->idxNum = 1;
      pInfo->aConstraintUsage[i].argvIndex = 1;
      pInfo->aConstraintUsage[i].omit = 1;
      pInfo->estimatedCost = 1;
      return SQLITE_OK;
    }
  }

  pInfo->idxNum = 0;
  assert( pInfo->estimatedCost>1000000.0 );

  return SQLITE_OK;
}

/*
** xOpen - Open a cursor.
*/
static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
  Fts3tokCursor *pCsr;
  UNUSED_PARAMETER(pVTab);

  pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor));
  if( pCsr==0 ){
    return SQLITE_NOMEM;
  }
  memset(pCsr, 0, sizeof(Fts3tokCursor));

  *ppCsr = (sqlite3_vtab_cursor *)pCsr;
  return SQLITE_OK;
}

/*
** Reset the tokenizer cursor passed as the only argument. As if it had
** just been returned by fts3tokOpenMethod().
*/
static void fts3tokResetCursor(Fts3tokCursor *pCsr){
  if( pCsr->pCsr ){
    Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab);
    pTab->pMod->xClose(pCsr->pCsr);
    pCsr->pCsr = 0;
  }
  sqlite3_free(pCsr->zInput);
  pCsr->zInput = 0;
  pCsr->zToken = 0;
  pCsr->nToken = 0;
  pCsr->iStart = 0;
  pCsr->iEnd = 0;
  pCsr->iPos = 0;
  pCsr->iRowid = 0;
}

/*
** xClose - Close a cursor.
*/
static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){
  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;

  fts3tokResetCursor(pCsr);
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/*
** xNext - Advance the cursor to the next row, if any.
*/
static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){
  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
  Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
  int rc;                         /* Return code */

  pCsr->iRowid++;
  rc = pTab->pMod->xNext(pCsr->pCsr,
      &pCsr->zToken, &pCsr->nToken,
      &pCsr->iStart, &pCsr->iEnd, &pCsr->iPos
  );

  if( rc!=SQLITE_OK ){
    fts3tokResetCursor(pCsr);
    if( rc==SQLITE_DONE ) rc = SQLITE_OK;
  }

  return rc;
}

/*
** xFilter - Initialize a cursor to point at the start of its data.
*/
static int fts3tokFilterMethod(
  sqlite3_vtab_cursor *pCursor,   /* The cursor used for this query */
  int idxNum,                     /* Strategy index */
  const char *idxStr,             /* Unused */
  int nVal,                       /* Number of elements in apVal */
  sqlite3_value **apVal           /* Arguments for the indexing scheme */
){
  int rc = SQLITE_ERROR;
  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
  Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
  UNUSED_PARAMETER(idxStr);
  UNUSED_PARAMETER(nVal);

  fts3tokResetCursor(pCsr);
  if( idxNum==1 ){
    const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
    int nByte = sqlite3_value_bytes(apVal[0]);
    pCsr->zInput = sqlite3_malloc(nByte+1);
    if( pCsr->zInput==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memcpy(pCsr->zInput, zByte, nByte);
      pCsr->zInput[nByte] = 0;
      rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
      if( rc==SQLITE_OK ){
        pCsr->pCsr->pTokenizer = pTab->pTok;
      }
    }
  }

  if( rc!=SQLITE_OK ) return rc;
  return fts3tokNextMethod(pCursor);
}

/*
** xEof - Return true if the cursor is at EOF, or false otherwise.
*/
static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){
  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
  return (pCsr->zToken==0);
}

/*
** xColumn - Return a column value.
*/
static int fts3tokColumnMethod(
  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
  int iCol                        /* Index of column to read value from */
){
  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;

  /* CREATE TABLE x(input, token, start, end, position) */
  switch( iCol ){
    case 0:
      sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT);
      break;
    case 1:
      sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT);
      break;
    case 2:
      sqlite3_result_int(pCtx, pCsr->iStart);
      break;
    case 3:
      sqlite3_result_int(pCtx, pCsr->iEnd);
      break;
    default:
      assert( iCol==4 );
      sqlite3_result_int(pCtx, pCsr->iPos);
      break;
  }
  return SQLITE_OK;
}

/*
** xRowid - Return the current rowid for the cursor.
*/
static int fts3tokRowidMethod(
  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  sqlite_int64 *pRowid            /* OUT: Rowid value */
){
  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
  *pRowid = (sqlite3_int64)pCsr->iRowid;
  return SQLITE_OK;
}

/*
** Register the fts3tok module with database connection db. Return SQLITE_OK
** if successful or an error code if sqlite3_create_module() fails.
*/
int sqlite3Fts3InitTok(sqlite3 *db){
  static const sqlite3_module fts3tok_module = {
     0,                           /* iVersion      */
     fts3tokConnectMethod,        /* xCreate       */
     fts3tokConnectMethod,        /* xConnect      */
     fts3tokBestIndexMethod,      /* xBestIndex    */
     fts3tokDisconnectMethod,     /* xDisconnect   */
     fts3tokDisconnectMethod,     /* xDestroy      */
     fts3tokOpenMethod,           /* xOpen         */
     fts3tokCloseMethod,          /* xClose        */
     fts3tokFilterMethod,         /* xFilter       */
     fts3tokNextMethod,           /* xNext         */
     fts3tokEofMethod,            /* xEof          */
     fts3tokColumnMethod,         /* xColumn       */
     fts3tokRowidMethod,          /* xRowid        */
     0,                           /* xUpdate       */
     0,                           /* xBegin        */
     0,                           /* xSync         */
     0,                           /* xCommit       */
     0,                           /* xRollback     */
     0,                           /* xFindFunction */
     0,                           /* xRename       */
     0,                           /* xSavepoint    */
     0,                           /* xRelease      */
     0                            /* xRollbackTo   */
  };
  int rc;                         /* Return code */

  rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, 0);
  return rc;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */

Changes to ext/rtree/rtree1.test.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl


# Test plan:
#
#   rtree-1.*: Creating/destroying r-tree tables.
#   rtree-2.*: Test the implicit constraints - unique rowid and
#              (coord[N]<=coord[N+1]) for even values of N. Also
#              automatic assigning of rowid values.







>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl
set testprefix rtree1

# Test plan:
#
#   rtree-1.*: Creating/destroying r-tree tables.
#   rtree-2.*: Test the implicit constraints - unique rowid and
#              (coord[N]<=coord[N+1]) for even values of N. Also
#              automatic assigning of rowid values.

Changes to ext/rtree/rtree5.test.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
do_test rtree5-1.9 { 
  execsql { SELECT count(*) FROM t1 WHERE x1==5.0 }
} {1}

do_test rtree5-1.10 { 
  execsql { SELECT (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5 }
} {2147483643 2147483647 -2147483648 -2147483643}
do_test rtree5-1.10 { 
  execsql { 
    INSERT INTO t1 VALUES(2, (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5) 
  }
} {}
do_test rtree5-1.12 { 
  execsql { SELECT * FROM t1 WHERE id=2 }
} {2 2147483643 2147483647 -2147483648 -2147483643}







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
do_test rtree5-1.9 { 
  execsql { SELECT count(*) FROM t1 WHERE x1==5.0 }
} {1}

do_test rtree5-1.10 { 
  execsql { SELECT (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5 }
} {2147483643 2147483647 -2147483648 -2147483643}
do_test rtree5-1.11 { 
  execsql { 
    INSERT INTO t1 VALUES(2, (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5) 
  }
} {}
do_test rtree5-1.12 { 
  execsql { SELECT * FROM t1 WHERE id=2 }
} {2 2147483643 2147483647 -2147483648 -2147483643}

Changes to main.mk.

52
53
54
55
56
57
58

59
60
61
62
63
64
65
...
194
195
196
197
198
199
200

201
202
203
204
205
206
207
...
367
368
369
370
371
372
373




374
375
376
377
378
379
380
...
514
515
516
517
518
519
520



521
522
523
524
525
526
527
...
629
630
631
632
633
634
635


636
637

# Object files for the SQLite library.
#
LIBOBJ+= alter.o analyze.o attach.o auth.o \
         backup.o bitvec.o btmutex.o btree.o build.o \
         callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
         fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
         fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \

	 fts3_unicode.o fts3_unicode2.o \
         fts3_write.o func.o global.o hash.o \
         icu.o insert.o journal.o legacy.o loadext.o \
         main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         memjournal.o \
         mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
         notify.o opcodes.o os.o os_unix.o os_win.o \
................................................................................
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_icu.c \
  $(TOP)/ext/fts3/fts3_porter.c \
  $(TOP)/ext/fts3/fts3_snippet.c \
  $(TOP)/ext/fts3/fts3_tokenizer.h \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_tokenizer1.c \

  $(TOP)/ext/fts3/fts3_unicode.c \
  $(TOP)/ext/fts3/fts3_unicode2.c \
  $(TOP)/ext/fts3/fts3_write.c
SRC += \
  $(TOP)/ext/icu/sqliteicu.h \
  $(TOP)/ext/icu/icu.c
SRC += \
................................................................................
	$(RANLIB) libsqlite3.a

sqlite3$(EXE):	$(TOP)/src/shell.c libsqlite3.a sqlite3.h
	$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE)                  \
		$(TOP)/src/shell.c                                  \
		libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)





sqlite3.o:	sqlite3.c
	$(TCCX) -c sqlite3.c

# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
................................................................................
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c

fts3_tokenizer.o:	$(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c

fts3_tokenizer1.o:	$(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c




fts3_unicode.o:	$(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c

fts3_unicode2.o:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c

................................................................................
	rm -rf tsrc target_source
	rm -f testloadext.dll libtestloadext.so
	rm -f amalgamation-testfixture amalgamation-testfixture.exe
	rm -f fts3-testfixture fts3-testfixture.exe
	rm -f testfixture testfixture.exe
	rm -f threadtest3 threadtest3.exe
	rm -f sqlite3.c fts?amal.c tclsqlite3.c


	rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
	rm -f sqlite-*-output.vsix








>







 







>







 







>
>
>
>







 







>
>
>







 







>
>


>
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
...
638
639
640
641
642
643
644
645
646
647
648
649
# Object files for the SQLite library.
#
LIBOBJ+= alter.o analyze.o attach.o auth.o \
         backup.o bitvec.o btmutex.o btree.o build.o \
         callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
         fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
         fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
         fts3_tokenize_vtab.o \
	 fts3_unicode.o fts3_unicode2.o \
         fts3_write.o func.o global.o hash.o \
         icu.o insert.o journal.o legacy.o loadext.o \
         main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         memjournal.o \
         mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
         notify.o opcodes.o os.o os_unix.o os_win.o \
................................................................................
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_icu.c \
  $(TOP)/ext/fts3/fts3_porter.c \
  $(TOP)/ext/fts3/fts3_snippet.c \
  $(TOP)/ext/fts3/fts3_tokenizer.h \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_tokenizer1.c \
  $(TOP)/ext/fts3/fts3_tokenize_vtab.c \
  $(TOP)/ext/fts3/fts3_unicode.c \
  $(TOP)/ext/fts3/fts3_unicode2.c \
  $(TOP)/ext/fts3/fts3_write.c
SRC += \
  $(TOP)/ext/icu/sqliteicu.h \
  $(TOP)/ext/icu/icu.c
SRC += \
................................................................................
	$(RANLIB) libsqlite3.a

sqlite3$(EXE):	$(TOP)/src/shell.c libsqlite3.a sqlite3.h
	$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE)                  \
		$(TOP)/src/shell.c                                  \
		libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)

mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
	$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
		$(TLIBS) $(THREADLIB)

sqlite3.o:	sqlite3.c
	$(TCCX) -c sqlite3.c

# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
................................................................................
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c

fts3_tokenizer.o:	$(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c

fts3_tokenizer1.o:	$(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c

fts3_tokenize_vtab.o:	$(TOP)/ext/fts3/fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenize_vtab.c

fts3_unicode.o:	$(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c

fts3_unicode2.o:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c

................................................................................
	rm -rf tsrc target_source
	rm -f testloadext.dll libtestloadext.so
	rm -f amalgamation-testfixture amalgamation-testfixture.exe
	rm -f fts3-testfixture fts3-testfixture.exe
	rm -f testfixture testfixture.exe
	rm -f threadtest3 threadtest3.exe
	rm -f sqlite3.c fts?amal.c tclsqlite3.c
	rm -f sqlite3rc.h
	rm -f shell.c sqlite3ext.h
	rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
	rm -f sqlite-*-output.vsix
	rm -f mptester mptester.exe

Added mptest/config01.test.





























































































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

Added mptest/config02.test.























































































































































































































































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

Added mptest/crash01.test.













































































































































































































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

--wait all
/* After the database file has been set up, run the crash2 subscript
** multiple times. */
--source crash02.subtest
--source crash02.subtest
--source crash02.subtest
--source crash02.subtest
--source crash02.subtest
--source crash02.subtest
--source crash02.subtest
--source crash02.subtest
--source crash02.subtest

Added mptest/crash02.subtest.











































































































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

Added mptest/mptest.c.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
/*
** 2013-04-05
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 
** This is a program used for testing SQLite, and specifically for testing
** the ability of independent processes to access the same SQLite database
** concurrently.
**
** Compile this program as follows:
**
**    gcc -g -c -Wall sqlite3.c $(OPTS)
**    gcc -g -o mptest mptest.c sqlite3.o $(LIBS)
**
** Recommended options:
**
**    -DHAVE_USLEEP
**    -DSQLITE_NO_SYNC
**    -DSQLITE_THREADSAFE=0
**    -DSQLITE_OMIT_LOAD_EXTENSION
**
** Run like this:
**
**     ./mptest $database $script
**
** where $database is the database to use for testing and $script is a
** test script.
*/
#include "sqlite3.h"
#include <stdio.h>
#if defined(_WIN32)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#else
# include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>

/* The suffix to append to the child command lines, if any */
#if defined(_WIN32)
# define GETPID (int)GetCurrentProcessId
#else
# define GETPID getpid
#endif

/* Mark a parameter as unused to suppress compiler warnings */
#define UNUSED_PARAMETER(x)  (void)x

/* Global data
*/
static struct Global {
  char *argv0;           /* Name of the executable */
  const char *zVfs;      /* Name of VFS to use. Often NULL meaning "default" */
  char *zDbFile;         /* Name of the database */
  sqlite3 *db;           /* Open connection to database */
  char *zErrLog;         /* Filename for error log */
  FILE *pErrLog;         /* Where to write errors */
  char *zLog;            /* Name of output log file */
  FILE *pLog;            /* Where to write log messages */
  char zName[32];        /* Symbolic name of this process */
  int taskId;            /* Task ID.  0 means supervisor. */
  int iTrace;            /* Tracing level */
  int bSqlTrace;         /* True to trace SQL commands */
  int bIgnoreSqlErrors;  /* Ignore errors in SQL statements */
  int nError;            /* Number of errors */
  int nTest;             /* Number of --match operators */
  int iTimeout;          /* Milliseconds until a busy timeout */
  int bSync;             /* Call fsync() */
} g;

/* Default timeout */
#define DEFAULT_TIMEOUT 10000

/*
** Print a message adding zPrefix[] to the beginning of every line.
*/
static void printWithPrefix(FILE *pOut, const char *zPrefix, const char *zMsg){
  while( zMsg && zMsg[0] ){
    int i;
    for(i=0; zMsg[i] && zMsg[i]!='\n' && zMsg[i]!='\r'; i++){}
    fprintf(pOut, "%s%.*s\n", zPrefix, i, zMsg);
    zMsg += i;
    while( zMsg[0]=='\n' || zMsg[0]=='\r' ) zMsg++;
  }
}

/*
** Compare two pointers to strings, where the pointers might be NULL.
*/
static int safe_strcmp(const char *a, const char *b){
  if( a==b ) return 0;
  if( a==0 ) return -1;
  if( b==0 ) return 1;
  return strcmp(a,b);
}

/*
** Return TRUE if string z[] matches glob pattern zGlob[].
** Return FALSE if the pattern does not match.
**
** Globbing rules:
**
**      '*'       Matches any sequence of zero or more characters.
**
**      '?'       Matches exactly one character.
**
**     [...]      Matches one character from the enclosed list of
**                characters.
**
**     [^...]     Matches one character not in the enclosed list.
**
**      '#'       Matches any sequence of one or more digits with an
**                optional + or - sign in front
*/
int strglob(const char *zGlob, const char *z){
  int c, c2;
  int invert;
  int seen;

  while( (c = (*(zGlob++)))!=0 ){
    if( c=='*' ){
      while( (c=(*(zGlob++))) == '*' || c=='?' ){
        if( c=='?' && (*(z++))==0 ) return 0;
      }
      if( c==0 ){
        return 1;
      }else if( c=='[' ){
        while( *z && strglob(zGlob-1,z) ){
          z++;
        }
        return (*z)!=0;
      }
      while( (c2 = (*(z++)))!=0 ){
        while( c2!=c ){
          c2 = *(z++);
          if( c2==0 ) return 0;
        }
        if( strglob(zGlob,z) ) return 1;
      }
      return 0;
    }else if( c=='?' ){
      if( (*(z++))==0 ) return 0;
    }else if( c=='[' ){
      int prior_c = 0;
      seen = 0;
      invert = 0;
      c = *(z++);
      if( c==0 ) return 0;
      c2 = *(zGlob++);
      if( c2=='^' ){
        invert = 1;
        c2 = *(zGlob++);
      }
      if( c2==']' ){
        if( c==']' ) seen = 1;
        c2 = *(zGlob++);
      }
      while( c2 && c2!=']' ){
        if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
          c2 = *(zGlob++);
          if( c>=prior_c && c<=c2 ) seen = 1;
          prior_c = 0;
        }else{
          if( c==c2 ){
            seen = 1;
          }
          prior_c = c2;
        }
        c2 = *(zGlob++);
      }
      if( c2==0 || (seen ^ invert)==0 ) return 0;
    }else if( c=='#' ){
      if( (z[0]=='-' || z[0]=='+') && isdigit(z[1]) ) z++;
      if( !isdigit(z[0]) ) return 0;
      z++;
      while( isdigit(z[0]) ){ z++; }
    }else{
      if( c!=(*(z++)) ) return 0;
    }
  }
  return *z==0;
}

/*
** Close output stream pOut if it is not stdout or stderr
*/
static void maybeClose(FILE *pOut){
  if( pOut!=stdout && pOut!=stderr ) fclose(pOut);
}

/*
** Print an error message
*/
static void errorMessage(const char *zFormat, ...){
  va_list ap;
  char *zMsg;
  char zPrefix[30];
  va_start(ap, zFormat);
  zMsg = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:ERROR: ", g.zName);
  if( g.pLog ){
    printWithPrefix(g.pLog, zPrefix, zMsg);
    fflush(g.pLog);
  }
  if( g.pErrLog && safe_strcmp(g.zErrLog,g.zLog) ){
    printWithPrefix(g.pErrLog, zPrefix, zMsg);
    fflush(g.pErrLog);
  }
  sqlite3_free(zMsg);
  g.nError++;
}

/* Forward declaration */
static int trySql(const char*, ...);

/*
** Print an error message and then quit.
*/
static void fatalError(const char *zFormat, ...){
  va_list ap;
  char *zMsg;
  char zPrefix[30];
  va_start(ap, zFormat);
  zMsg = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:FATAL: ", g.zName);
  if( g.pLog ){
    printWithPrefix(g.pLog, zPrefix, zMsg);
    fflush(g.pLog);
    maybeClose(g.pLog);
  }
  if( g.pErrLog && safe_strcmp(g.zErrLog,g.zLog) ){
    printWithPrefix(g.pErrLog, zPrefix, zMsg);
    fflush(g.pErrLog);
    maybeClose(g.pErrLog);
  }
  sqlite3_free(zMsg);
  if( g.db ){
    int nTry = 0;
    g.iTimeout = 0;
    while( trySql("UPDATE client SET wantHalt=1;")==SQLITE_BUSY
           && (nTry++)<100 ){
      sqlite3_sleep(10);
    }
  }
  sqlite3_close(g.db);
  exit(1);  
}


/*
** Print a log message
*/
static void logMessage(const char *zFormat, ...){
  va_list ap;
  char *zMsg;
  char zPrefix[30];
  va_start(ap, zFormat);
  zMsg = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s: ", g.zName);
  if( g.pLog ){
    printWithPrefix(g.pLog, zPrefix, zMsg);
    fflush(g.pLog);
  }
  sqlite3_free(zMsg);
}

/*
** Return the length of a string omitting trailing whitespace
*/
static int clipLength(const char *z){
  int n = (int)strlen(z);
  while( n>0 && isspace(z[n-1]) ){ n--; }
  return n;
}

/*
** Auxiliary SQL function to return the name of the VFS
*/
static void vfsNameFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  char *zVfs = 0;
  UNUSED_PARAMETER(argc);
  UNUSED_PARAMETER(argv);
  sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zVfs);
  if( zVfs ){
    sqlite3_result_text(context, zVfs, -1, sqlite3_free);
  }
}

/*
** Busy handler with a g.iTimeout-millisecond timeout
*/
static int busyHandler(void *pCD, int count){
  UNUSED_PARAMETER(pCD);
  if( count*10>g.iTimeout ){
    if( g.iTimeout>0 ) errorMessage("timeout after %dms", g.iTimeout);
    return 0;
  }
  sqlite3_sleep(10);
  return 1;
}

/*
** SQL Trace callback
*/
static void sqlTraceCallback(void *NotUsed1, const char *zSql){
  UNUSED_PARAMETER(NotUsed1);
  logMessage("[%.*s]", clipLength(zSql), zSql);
}

/*
** SQL error log callback
*/
static void sqlErrorCallback(void *pArg, int iErrCode, const char *zMsg){
  UNUSED_PARAMETER(pArg);
  if( iErrCode==SQLITE_ERROR && g.bIgnoreSqlErrors ) return;
  if( (iErrCode&0xff)==SQLITE_SCHEMA && g.iTrace<3 ) return;
  if( g.iTimeout==0 && (iErrCode&0xff)==SQLITE_BUSY && g.iTrace<3 ) return;
  if( (iErrCode&0xff)==SQLITE_NOTICE ){
    logMessage("(info) %s", zMsg);
  }else{
    errorMessage("(errcode=%d) %s", iErrCode, zMsg);
  }
}

/*
** Prepare an SQL statement.  Issue a fatal error if unable.
*/
static sqlite3_stmt *prepareSql(const char *zFormat, ...){
  va_list ap;
  char *zSql;
  int rc;
  sqlite3_stmt *pStmt = 0;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
  if( rc!=SQLITE_OK ){
    sqlite3_finalize(pStmt);
    fatalError("%s\n%s\n", sqlite3_errmsg(g.db), zSql);
  }
  sqlite3_free(zSql);
  return pStmt;
}

/*
** Run arbitrary SQL.  Issue a fatal error on failure.
*/
static void runSql(const char *zFormat, ...){
  va_list ap;
  char *zSql;
  int rc;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
  if( rc!=SQLITE_OK ){
    fatalError("%s\n%s\n", sqlite3_errmsg(g.db), zSql);
  }
  sqlite3_free(zSql);
}

/*
** Try to run arbitrary SQL.  Return success code.
*/
static int trySql(const char *zFormat, ...){
  va_list ap;
  char *zSql;
  int rc;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
  sqlite3_free(zSql);
  return rc;
}

/* Structure for holding an arbitrary length string
*/
typedef struct String String;
struct String {
  char *z;         /* the string */
  int n;           /* Slots of z[] used */
  int nAlloc;      /* Slots of z[] allocated */
};

/* Free a string */
static void stringFree(String *p){
  if( p->z ) sqlite3_free(p->z);
  memset(p, 0, sizeof(*p));
}

/* Append n bytes of text to a string.  If n<0 append the entire string. */
static void stringAppend(String *p, const char *z, int n){
  if( n<0 ) n = (int)strlen(z);
  if( p->n+n>=p->nAlloc ){
    int nAlloc = p->nAlloc*2 + n + 100;
    char *z = sqlite3_realloc(p->z, nAlloc);
    if( z==0 ) fatalError("out of memory");
    p->z = z;
    p->nAlloc = nAlloc;
  }
  memcpy(p->z+p->n, z, n);
  p->n += n;
  p->z[p->n] = 0;
}

/* Reset a string to an empty string */
static void stringReset(String *p){
  if( p->z==0 ) stringAppend(p, " ", 1);
  p->n = 0;
  p->z[0] = 0;
}

/* Append a new token onto the end of the string */
static void stringAppendTerm(String *p, const char *z){
  int i;
  if( p->n ) stringAppend(p, " ", 1);
  if( z==0 ){
    stringAppend(p, "nil", 3);
    return;
  }
  for(i=0; z[i] && !isspace(z[i]); i++){}
  if( i>0 && z[i]==0 ){
    stringAppend(p, z, i);
    return;
  }
  stringAppend(p, "'", 1);
  while( z[0] ){
    for(i=0; z[i] && z[i]!='\''; i++){}
    if( z[i] ){
      stringAppend(p, z, i+1);
      stringAppend(p, "'", 1);
      z += i+1;
    }else{
      stringAppend(p, z, i);
      break;
    }
  }
  stringAppend(p, "'", 1);
}

/*
** Callback function for evalSql()
*/
static int evalCallback(void *pCData, int argc, char **argv, char **azCol){
  String *p = (String*)pCData;
  int i;
  UNUSED_PARAMETER(azCol);
  for(i=0; i<argc; i++) stringAppendTerm(p, argv[i]);
  return 0;
}

/*
** Run arbitrary SQL and record the results in an output string
** given by the first parameter.
*/
static int evalSql(String *p, const char *zFormat, ...){
  va_list ap;
  char *zSql;
  int rc;
  char *zErrMsg = 0;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  assert( g.iTimeout>0 );
  rc = sqlite3_exec(g.db, zSql, evalCallback, p, &zErrMsg);
  sqlite3_free(zSql);
  if( rc ){
    char zErr[30];
    sqlite3_snprintf(sizeof(zErr), zErr, "error(%d)", rc);
    stringAppendTerm(p, zErr);
    if( zErrMsg ){
      stringAppendTerm(p, zErrMsg);
      sqlite3_free(zErrMsg);
    }
  }
  return rc;
}

/*
** Auxiliary SQL function to recursively evaluate SQL.
*/
static void evalFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  String res;
  char *zErrMsg = 0;
  int rc;
  UNUSED_PARAMETER(argc);
  memset(&res, 0, sizeof(res));
  rc = sqlite3_exec(db, zSql, evalCallback, &res, &zErrMsg);
  if( zErrMsg ){
    sqlite3_result_error(context, zErrMsg, -1);
    sqlite3_free(zErrMsg);
  }else if( rc ){
    sqlite3_result_error_code(context, rc);
  }else{
    sqlite3_result_text(context, res.z, -1, SQLITE_TRANSIENT);
  }
  stringFree(&res);
}

/*
** Look up the next task for client iClient in the database.
** Return the task script and the task number and mark that
** task as being under way.
*/
static int startScript(
  int iClient,              /* The client number */
  char **pzScript,          /* Write task script here */
  int *pTaskId,             /* Write task number here */
  char **pzTaskName         /* Name of the task */
){
  sqlite3_stmt *pStmt = 0;
  int taskId;
  int rc;
  int totalTime = 0;

  *pzScript = 0;
  g.iTimeout = 0;
  while(1){
    rc = trySql("BEGIN IMMEDIATE");
    if( rc==SQLITE_BUSY ){
      sqlite3_sleep(10);
      totalTime += 10;
      continue;
    }
    if( rc!=SQLITE_OK ){
      fatalError("in startScript: %s", sqlite3_errmsg(g.db));
    }
    if( g.nError || g.nTest ){
      runSql("UPDATE counters SET nError=nError+%d, nTest=nTest+%d",
             g.nError, g.nTest);
      g.nError = 0;
      g.nTest = 0;
    }
    pStmt = prepareSql("SELECT 1 FROM client WHERE id=%d AND wantHalt",iClient);
    rc = sqlite3_step(pStmt);
    sqlite3_finalize(pStmt);
    if( rc==SQLITE_ROW ){
      runSql("DELETE FROM client WHERE id=%d", iClient);
      g.iTimeout = DEFAULT_TIMEOUT;
      runSql("COMMIT TRANSACTION;");
      return SQLITE_DONE;
    }
    pStmt = prepareSql(
              "SELECT script, id, name FROM task"
              " WHERE client=%d AND starttime IS NULL"
              " ORDER BY id LIMIT 1", iClient);
    rc = sqlite3_step(pStmt);
    if( rc==SQLITE_ROW ){
      int n = sqlite3_column_bytes(pStmt, 0);
      *pzScript = sqlite3_malloc(n+1);
      strcpy(*pzScript, (const char*)sqlite3_column_text(pStmt, 0));
      *pTaskId = taskId = sqlite3_column_int(pStmt, 1);
      *pzTaskName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 2));
      sqlite3_finalize(pStmt);
      runSql("UPDATE task"
             "   SET starttime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')"
             " WHERE id=%d;", taskId);
      g.iTimeout = DEFAULT_TIMEOUT;
      runSql("COMMIT TRANSACTION;");
      return SQLITE_OK;
    }
    sqlite3_finalize(pStmt);
    if( rc==SQLITE_DONE ){
      if( totalTime>30000 ){
        errorMessage("Waited over 30 seconds with no work.  Giving up.");
        runSql("DELETE FROM client WHERE id=%d; COMMIT;", iClient);
        sqlite3_close(g.db);
        exit(1);
      }
      while( trySql("COMMIT")==SQLITE_BUSY ){
        sqlite3_sleep(10);
        totalTime += 10;
      }
      sqlite3_sleep(100);
      totalTime += 100;
      continue;
    }
    fatalError("%s", sqlite3_errmsg(g.db));
  }
  g.iTimeout = DEFAULT_TIMEOUT;
}

/*
** Mark a script as having finished.   Remove the CLIENT table entry
** if bShutdown is true.
*/
static int finishScript(int iClient, int taskId, int bShutdown){
  runSql("UPDATE task"
         "   SET endtime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')"
         " WHERE id=%d;", taskId);
  if( bShutdown ){
    runSql("DELETE FROM client WHERE id=%d", iClient);
  }
  return SQLITE_OK;
}

/*
** Start up a client process for iClient, if it is not already
** running.  If the client is already running, then this routine
** is a no-op.
*/
static void startClient(int iClient){
  runSql("INSERT OR IGNORE INTO client VALUES(%d,0)", iClient);
  if( sqlite3_changes(g.db) ){
    char *zSys;
    int rc;
    zSys = sqlite3_mprintf("%s \"%s\" --client %d --trace %d",
                 g.argv0, g.zDbFile, iClient, g.iTrace);
    if( g.bSqlTrace ){
      zSys = sqlite3_mprintf("%z --sqltrace", zSys);
    }
    if( g.bSync ){
      zSys = sqlite3_mprintf("%z --sync", zSys);
    }
    if( g.zVfs ){
      zSys = sqlite3_mprintf("%z --vfs \"%s\"", zSys, g.zVfs);
    }
    if( g.iTrace>=2 ) logMessage("system('%q')", zSys);
#if !defined(_WIN32)
    zSys = sqlite3_mprintf("%z &", zSys);
    rc = system(zSys);
    if( rc ) errorMessage("system() fails with error code %d", rc);
#else
    {
      STARTUPINFOA startupInfo;
      PROCESS_INFORMATION processInfo;
      memset(&startupInfo, 0, sizeof(startupInfo));
      startupInfo.cb = sizeof(startupInfo);
      memset(&processInfo, 0, sizeof(processInfo));
      rc = CreateProcessA(NULL, zSys, NULL, NULL, FALSE, 0, NULL, NULL,
                        &startupInfo, &processInfo);
      if( rc ){
        CloseHandle(processInfo.hThread);
        CloseHandle(processInfo.hProcess);
      }else{
        errorMessage("CreateProcessA() fails with error code %lu",
                     GetLastError());
      }
    }
#endif
    sqlite3_free(zSys);
  }
}

/*
** Read the entire content of a file into memory
*/
static char *readFile(const char *zFilename){
  FILE *in = fopen(zFilename, "rb");
  long sz;
  char *z;
  if( in==0 ){
    fatalError("cannot open \"%s\" for reading", zFilename);
  }
  fseek(in, 0, SEEK_END);
  sz = ftell(in);
  rewind(in);
  z = sqlite3_malloc( sz+1 );
  sz = (long)fread(z, 1, sz, in);
  z[sz] = 0;
  fclose(in);
  return z;
}

/*
** Return the length of the next token.
*/
static int tokenLength(const char *z, int *pnLine){
  int n = 0;
  if( isspace(z[0]) || (z[0]=='/' && z[1]=='*') ){
    int inC = 0;
    int c;
    if( z[0]=='/' ){
      inC = 1;
      n = 2;
    }
    while( (c = z[n++])!=0 ){
      if( c=='\n' ) (*pnLine)++;
      if( isspace(c) ) continue;
      if( inC && c=='*' && z[n]=='/' ){
        n++;
        inC = 0;
      }else if( !inC && c=='/' && z[n]=='*' ){
        n++;
        inC = 1;
      }else if( !inC ){
        break;
      }
    }
    n--;
  }else if( z[0]=='-' && z[1]=='-' ){
    for(n=2; z[n] && z[n]!='\n'; n++){}
    if( z[n] ){ (*pnLine)++; n++; }
  }else if( z[0]=='"' || z[0]=='\'' ){
    int delim = z[0];
    for(n=1; z[n]; n++){
      if( z[n]=='\n' ) (*pnLine)++;
      if( z[n]==delim ){
        n++;
        if( z[n+1]!=delim ) break;
      }
    }
  }else{
    int c;
    for(n=1; (c = z[n])!=0 && !isspace(c) && c!='"' && c!='\'' && c!=';'; n++){}
  }
  return n;
}

/*
** Copy a single token into a string buffer.
*/
static int extractToken(const char *zIn, int nIn, char *zOut, int nOut){
  int i;
  if( nIn<=0 ){
    zOut[0] = 0;
    return 0;
  }
  for(i=0; i<nIn && i<nOut-1 && !isspace(zIn[i]); i++){ zOut[i] = zIn[i]; }
  zOut[i] = 0;
  return i;
}

/*
** Find the number of characters up to the start of the next "--end" token.
*/
static int findEnd(const char *z, int *pnLine){
  int n = 0;
  while( z[n] && (strncmp(z+n,"--end",5) || !isspace(z[n+5])) ){
    n += tokenLength(z+n, pnLine);
  }
  return n;
}

/*
** Find the number of characters up to the first character past the
** of the next "--endif"  or "--else" token. Nested --if commands are
** also skipped.
*/
static int findEndif(const char *z, int stopAtElse, int *pnLine){
  int n = 0;
  while( z[n] ){
    int len = tokenLength(z+n, pnLine);
    if( (strncmp(z+n,"--endif",7)==0 && isspace(z[n+7]))
     || (stopAtElse && strncmp(z+n,"--else",6)==0 && isspace(z[n+6]))
    ){
      return n+len;
    }
    if( strncmp(z+n,"--if",4)==0 && isspace(z[n+4]) ){
      int skip = findEndif(z+n+len, 0, pnLine);
      n += skip + len;
    }else{
      n += len;
    }
  }
  return n;
}

/*
** Wait for a client process to complete all its tasks
*/
static void waitForClient(int iClient, int iTimeout, char *zErrPrefix){
  sqlite3_stmt *pStmt;
  int rc;
  if( iClient>0 ){
    pStmt = prepareSql(
               "SELECT 1 FROM task"
               " WHERE client=%d"
               "   AND client IN (SELECT id FROM client)"
               "  AND endtime IS NULL",
               iClient);
  }else{
    pStmt = prepareSql(
               "SELECT 1 FROM task"
               " WHERE client IN (SELECT id FROM client)"
               "   AND endtime IS NULL");
  }
  g.iTimeout = 0;
  while( ((rc = sqlite3_step(pStmt))==SQLITE_BUSY || rc==SQLITE_ROW)
    && iTimeout>0
  ){
    sqlite3_reset(pStmt);
    sqlite3_sleep(50);
    iTimeout -= 50;
  }
  sqlite3_finalize(pStmt);
  g.iTimeout = DEFAULT_TIMEOUT;
  if( rc!=SQLITE_DONE ){
    if( zErrPrefix==0 ) zErrPrefix = "";
    if( iClient>0 ){
      errorMessage("%stimeout waiting for client %d", zErrPrefix, iClient);
    }else{
      errorMessage("%stimeout waiting for all clients", zErrPrefix);
    }
  }
}

/* Return a pointer to the tail of a filename
*/
static char *filenameTail(char *z){
  int i, j;
  for(i=j=0; z[i]; i++) if( z[i]=='/' ) j = i+1;
  return z+j;
}

/*
** Interpret zArg as a boolean value.  Return either 0 or 1.
*/
static int booleanValue(char *zArg){
  int i;
  if( zArg==0 ) return 0;
  for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
  if( i>0 && zArg[i]==0 ) return atoi(zArg);
  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
    return 1;
  }
  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
    return 0;
  }
  errorMessage("unknown boolean: [%s]", zArg);
  return 0;
}


/* This routine exists as a convenient place to set a debugger
** breakpoint.
*/
static void test_breakpoint(void){ static volatile int cnt = 0; cnt++; }

/* Maximum number of arguments to a --command */
#define MX_ARG 2

/*
** Run a script.
*/
static void runScript(
  int iClient,       /* The client number, or 0 for the master */
  int taskId,        /* The task ID for clients.  0 for master */
  char *zScript,     /* Text of the script */
  char *zFilename    /* File from which script was read. */
){
  int lineno = 1;
  int prevLine = 1;
  int ii = 0;
  int iBegin = 0;
  int n, c, j;
  int len;
  int nArg;
  String sResult;
  char zCmd[30];
  char zError[1000];
  char azArg[MX_ARG][100];

  memset(&sResult, 0, sizeof(sResult));
  stringReset(&sResult);
  while( (c = zScript[ii])!=0 ){
    prevLine = lineno;
    len = tokenLength(zScript+ii, &lineno);
    if( isspace(c) || (c=='/' && zScript[ii+1]=='*') ){
      ii += len;
      continue;
    }
    if( c!='-' || zScript[ii+1]!='-' || !isalpha(zScript[ii+2]) ){
      ii += len;
      continue;
    }

    /* Run any prior SQL before processing the new --command */
    if( ii>iBegin ){
      char *zSql = sqlite3_mprintf("%.*s", ii-iBegin, zScript+iBegin);
      evalSql(&sResult, zSql);
      sqlite3_free(zSql);
      iBegin = ii + len;
    }

    /* Parse the --command */
    if( g.iTrace>=2 ) logMessage("%.*s", len, zScript+ii);
    n = extractToken(zScript+ii+2, len-2, zCmd, sizeof(zCmd));
    for(nArg=0; n<len-2 && nArg<MX_ARG; nArg++){
      while( n<len-2 && isspace(zScript[ii+2+n]) ){ n++; }
      if( n>=len-2 ) break;
      n += extractToken(zScript+ii+2+n, len-2-n,
                        azArg[nArg], sizeof(azArg[nArg]));
    }
    for(j=nArg; j<MX_ARG; j++) azArg[j++][0] = 0;

    /*
    **  --sleep N
    **
    ** Pause for N milliseconds
    */
    if( strcmp(zCmd, "sleep")==0 ){
      sqlite3_sleep(atoi(azArg[0]));
    }else 

    /*
    **   --exit N
    **
    ** Exit this process.  If N>0 then exit without shutting down
    ** SQLite.  (In other words, simulate a crash.)
    */
    if( strcmp(zCmd, "exit")==0 ){
      int rc = atoi(azArg[0]);
      finishScript(iClient, taskId, 1);
      if( rc==0 ) sqlite3_close(g.db);
      exit(rc);
    }else

    /*
    **   --testcase NAME
    **
    ** Begin a new test case.  Announce in the log that the test case
    ** has begun.
    */
    if( strcmp(zCmd, "testcase")==0 ){
      if( g.iTrace==1 ) logMessage("%.*s", len - 1, zScript+ii);
      stringReset(&sResult);
    }else

    /*
    **   --finish
    **
    ** Mark the current task as having finished, even if it is not.
    ** This can be used in conjunction with --exit to simulate a crash.
    */
    if( strcmp(zCmd, "finish")==0 && iClient>0 ){
      finishScript(iClient, taskId, 1);
    }else

    /*
    **  --reset
    **
    ** Reset accumulated results back to an empty string
    */
    if( strcmp(zCmd, "reset")==0 ){
      stringReset(&sResult);
    }else

    /*
    **  --match ANSWER...
    **
    ** Check to see if output matches ANSWER.  Report an error if not.
    */
    if( strcmp(zCmd, "match")==0 ){
      int jj;
      char *zAns = zScript+ii;
      for(jj=7; jj<len-1 && isspace(zAns[jj]); jj++){}
      zAns += jj;
      if( len-jj-1!=sResult.n || strncmp(sResult.z, zAns, len-jj-1) ){
        errorMessage("line %d of %s:\nExpected [%.*s]\n     Got [%s]",
          prevLine, zFilename, len-jj-1, zAns, sResult.z);
      }
      g.nTest++;
      stringReset(&sResult);
    }else

    /*
    **  --glob ANSWER...
    **  --notglob ANSWER....
    **
    ** Check to see if output does or does not match the glob pattern
    ** ANSWER.
    */
    if( strcmp(zCmd, "glob")==0 || strcmp(zCmd, "notglob")==0 ){
      int jj;
      char *zAns = zScript+ii;
      char *zCopy;
      int isGlob = (zCmd[0]=='g');
      for(jj=9-3*isGlob; jj<len-1 && isspace(zAns[jj]); jj++){}
      zAns += jj;
      zCopy = sqlite3_mprintf("%.*s", len-jj-1, zAns);
      if( (sqlite3_strglob(zCopy, sResult.z)==0)^isGlob ){
        errorMessage("line %d of %s:\nExpected [%s]\n     Got [%s]",
          prevLine, zFilename, zCopy, sResult.z);
      }
      sqlite3_free(zCopy);
      g.nTest++;
      stringReset(&sResult);
    }else

    /*
    **  --output
    **
    ** Output the result of the previous SQL.
    */
    if( strcmp(zCmd, "output")==0 ){
      logMessage("%s", sResult.z);
    }else

    /*
    **  --source FILENAME
    **
    ** Run a subscript from a separate file.
    */
    if( strcmp(zCmd, "source")==0 ){
      char *zNewFile, *zNewScript;
      char *zToDel = 0;
      zNewFile = azArg[0];
      if( zNewFile[0]!='/' ){
        int k;
        for(k=(int)strlen(zFilename)-1; k>=0 && zFilename[k]!='/'; k--){}
        if( k>0 ){
          zNewFile = zToDel = sqlite3_mprintf("%.*s/%s", k,zFilename,zNewFile);
        }
      }
      zNewScript = readFile(zNewFile);
      if( g.iTrace ) logMessage("begin script [%s]\n", zNewFile);
      runScript(0, 0, zNewScript, zNewFile);
      sqlite3_free(zNewScript);
      if( g.iTrace ) logMessage("end script [%s]\n", zNewFile);
      sqlite3_free(zToDel);
    }else

    /*
    **  --print MESSAGE....
    **
    ** Output the remainder of the line to the log file
    */
    if( strcmp(zCmd, "print")==0 ){
      int jj;
      for(jj=7; jj<len && isspace(zScript[ii+jj]); jj++){}
      logMessage("%.*s", len-jj, zScript+ii+jj);
    }else

    /*
    **  --if EXPR
    **
    ** Skip forward to the next matching --endif or --else if EXPR is false.
    */
    if( strcmp(zCmd, "if")==0 ){
      int jj, rc;
      sqlite3_stmt *pStmt;
      for(jj=4; jj<len && isspace(zScript[ii+jj]); jj++){}
      pStmt = prepareSql("SELECT %.*s", len-jj, zScript+ii+jj);
      rc = sqlite3_step(pStmt);
      if( rc!=SQLITE_ROW || sqlite3_column_int(pStmt, 0)==0 ){
        ii += findEndif(zScript+ii+len, 1, &lineno);
      }
      sqlite3_finalize(pStmt);
    }else

    /*
    **  --else
    **
    ** This command can only be encountered if currently inside an --if that
    ** is true.  Skip forward to the next matching --endif.
    */
    if( strcmp(zCmd, "else")==0 ){
      ii += findEndif(zScript+ii+len, 0, &lineno);
    }else

    /*
    **  --endif
    **
    ** This command can only be encountered if currently inside an --if that
    ** is true or an --else of a false if.  This is a no-op.
    */
    if( strcmp(zCmd, "endif")==0 ){
      /* no-op */
    }else

    /*
    **  --start CLIENT
    **
    ** Start up the given client.
    */
    if( strcmp(zCmd, "start")==0 && iClient==0 ){
      int iNewClient = atoi(azArg[0]);
      if( iNewClient>0 ){
        startClient(iNewClient);
      }
    }else

    /*
    **  --wait CLIENT TIMEOUT
    **
    ** Wait until all tasks complete for the given client.  If CLIENT is
    ** "all" then wait for all clients to complete.  Wait no longer than
    ** TIMEOUT milliseconds (default 10,000)
    */
    if( strcmp(zCmd, "wait")==0 && iClient==0 ){
      int iTimeout = nArg>=2 ? atoi(azArg[1]) : 10000;
      sqlite3_snprintf(sizeof(zError),zError,"line %d of %s\n",
                       prevLine, zFilename);
      waitForClient(atoi(azArg[0]), iTimeout, zError);
    }else

    /*
    **  --task CLIENT
    **     <task-content-here>
    **  --end
    **
    ** Assign work to a client.  Start the client if it is not running
    ** already.
    */
    if( strcmp(zCmd, "task")==0 && iClient==0 ){
      int iTarget = atoi(azArg[0]);
      int iEnd;
      char *zTask;
      char *zTName;
      iEnd = findEnd(zScript+ii+len, &lineno);
      if( iTarget<0 ){
        errorMessage("line %d of %s: bad client number: %d",
                     prevLine, zFilename, iTarget);
      }else{
        zTask = sqlite3_mprintf("%.*s", iEnd, zScript+ii+len);
        if( nArg>1 ){
          zTName = sqlite3_mprintf("%s", azArg[1]);
        }else{
          zTName = sqlite3_mprintf("%s:%d", filenameTail(zFilename), prevLine);
        }
        startClient(iTarget);
        runSql("INSERT INTO task(client,script,name)"
               " VALUES(%d,'%q',%Q)", iTarget, zTask, zTName);
        sqlite3_free(zTask);
        sqlite3_free(zTName);
      }
      iEnd += tokenLength(zScript+ii+len+iEnd, &lineno);
      len += iEnd;
      iBegin = ii+len;
    }else

    /*
    **  --breakpoint
    **
    ** This command calls "test_breakpoint()" which is a routine provided
    ** as a convenient place to set a debugger breakpoint.
    */
    if( strcmp(zCmd, "breakpoint")==0 ){
      test_breakpoint();
    }else

    /*
    **  --show-sql-errors BOOLEAN
    **
    ** Turn display of SQL errors on and off.
    */
    if( strcmp(zCmd, "show-sql-errors")==0 ){
      g.bIgnoreSqlErrors = nArg>=1 ? !booleanValue(azArg[0]) : 1;
    }else


    /* error */{
      errorMessage("line %d of %s: unknown command --%s",
                   prevLine, zFilename, zCmd);
    }
    ii += len;
  }
  if( iBegin<ii ){
    char *zSql = sqlite3_mprintf("%.*s", ii-iBegin, zScript+iBegin);
    runSql(zSql);
    sqlite3_free(zSql);
  }
  stringFree(&sResult);
}

/*
** Look for a command-line option.  If present, return a pointer.
** Return NULL if missing.
**
** hasArg==0 means the option is a flag.  It is either present or not.
** hasArg==1 means the option has an argument.  Return a pointer to the
** argument.
*/
static char *findOption(
  char **azArg,
  int *pnArg,
  const char *zOption,
  int hasArg
){
  int i, j;
  char *zReturn = 0;
  int nArg = *pnArg;

  assert( hasArg==0 || hasArg==1 );
  for(i=0; i<nArg; i++){
    const char *z;
    if( i+hasArg >= nArg ) break;
    z = azArg[i];
    if( z[0]!='-' ) continue;
    z++;
    if( z[0]=='-' ){
      if( z[1]==0 ) break;
      z++;
    }
    if( strcmp(z,zOption)==0 ){
      if( hasArg && i==nArg-1 ){
        fatalError("command-line option \"--%s\" requires an argument", z);
      }
      if( hasArg ){
        zReturn = azArg[i+1];
      }else{
        zReturn = azArg[i];
      }
      j = i+1+(hasArg!=0);
      while( j<nArg ) azArg[i++] = azArg[j++];
      *pnArg = i;
      return zReturn;
    }
  }
  return zReturn;
}

/* Print a usage message for the program and exit */
static void usage(const char *argv0){
  int i;
  const char *zTail = argv0;
  for(i=0; argv0[i]; i++){
    if( argv0[i]=='/' ) zTail = argv0+i+1;
  }
  fprintf(stderr,"Usage: %s DATABASE ?OPTIONS? ?SCRIPT?\n", zTail);
  exit(1);
}

/* Report on unrecognized arguments */
static void unrecognizedArguments(
  const char *argv0,
  int nArg,
  char **azArg
){
  int i;
  fprintf(stderr,"%s: unrecognized arguments:", argv0);
  for(i=0; i<nArg; i++){
    fprintf(stderr," %s", azArg[i]);
  }
  fprintf(stderr,"\n");
  exit(1);
}

int main(int argc, char **argv){
  const char *zClient;
  int iClient;
  int n, i;
  int openFlags = SQLITE_OPEN_READWRITE;
  int rc;
  char *zScript;
  int taskId;
  const char *zTrace;
  const char *zCOption;

  g.argv0 = argv[0];
  g.iTrace = 1;
  if( argc<2 ) usage(argv[0]);
  g.zDbFile = argv[1];
  if( strglob("*.test", g.zDbFile) ) usage(argv[0]);
  if( strcmp(sqlite3_sourceid(), SQLITE_SOURCE_ID)!=0 ){
    fprintf(stderr, "SQLite library and header mismatch\n"
                    "Library: %s\n"
                    "Header:  %s\n",
                    sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
  }
  n = argc-2;
  sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.mptest", GETPID());
  g.zVfs = findOption(argv+2, &n, "vfs", 1);
  zClient = findOption(argv+2, &n, "client", 1);
  g.zErrLog = findOption(argv+2, &n, "errlog", 1);
  g.zLog = findOption(argv+2, &n, "log", 1);
  zTrace = findOption(argv+2, &n, "trace", 1);
  if( zTrace ) g.iTrace = atoi(zTrace);
  if( findOption(argv+2, &n, "quiet", 0)!=0 ) g.iTrace = 0;
  g.bSqlTrace = findOption(argv+2, &n, "sqltrace", 0)!=0;
  g.bSync = findOption(argv+2, &n, "sync", 0)!=0;
  if( g.zErrLog ){
    g.pErrLog = fopen(g.zErrLog, "a");
  }else{
    g.pErrLog = stderr;
  }
  if( g.zLog ){
    g.pLog = fopen(g.zLog, "a");
  }else{
    g.pLog = stdout;
  }
  
  sqlite3_config(SQLITE_CONFIG_LOG, sqlErrorCallback, 0);
  if( zClient ){
    iClient = atoi(zClient);
    if( iClient<1 ) fatalError("illegal client number: %d\n", iClient);
    sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.client%02d",
                     GETPID(), iClient);
  }else{
    if( g.iTrace>0 ){
      printf("With SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\n" );
      for(i=0; (zCOption = sqlite3_compileoption_get(i))!=0; i++){
        printf("-DSQLITE_%s\n", zCOption);
      }
      fflush(stdout);
    }
    iClient =  0;
    unlink(g.zDbFile);
    openFlags |= SQLITE_OPEN_CREATE;
  }
  rc = sqlite3_open_v2(g.zDbFile, &g.db, openFlags, g.zVfs);
  if( rc ) fatalError("cannot open [%s]", g.zDbFile);
  sqlite3_enable_load_extension(g.db, 1);
  sqlite3_busy_handler(g.db, busyHandler, 0);
  sqlite3_create_function(g.db, "vfsname", 0, SQLITE_UTF8, 0,
                          vfsNameFunc, 0, 0);
  sqlite3_create_function(g.db, "eval", 1, SQLITE_UTF8, 0,
                          evalFunc, 0, 0);
  g.iTimeout = DEFAULT_TIMEOUT;
  if( g.bSqlTrace ) sqlite3_trace(g.db, sqlTraceCallback, 0);
  if( !g.bSync ) trySql("PRAGMA synchronous=OFF");
  if( iClient>0 ){
    if( n>0 ) unrecognizedArguments(argv[0], n, argv+2);
    if( g.iTrace ) logMessage("start-client");
    while(1){
      char *zTaskName = 0;
      rc = startScript(iClient, &zScript, &taskId, &zTaskName);
      if( rc==SQLITE_DONE ) break;
      if( g.iTrace ) logMessage("begin %s (%d)", zTaskName, taskId);
      runScript(iClient, taskId, zScript, zTaskName);
      if( g.iTrace ) logMessage("end %s (%d)", zTaskName, taskId);
      finishScript(iClient, taskId, 0);
      sqlite3_free(zTaskName);
      sqlite3_sleep(10);
    }
    if( g.iTrace ) logMessage("end-client");
  }else{
    sqlite3_stmt *pStmt;
    int iTimeout;
    if( n==0 ){
      fatalError("missing script filename");
    }
    if( n>1 ) unrecognizedArguments(argv[0], n, argv+2);
    runSql(
      "CREATE TABLE task(\n"
      "  id INTEGER PRIMARY KEY,\n"
      "  name TEXT,\n"
      "  client INTEGER,\n"
      "  starttime DATE,\n"
      "  endtime DATE,\n"
      "  script TEXT\n"
      ");"
      "CREATE INDEX task_i1 ON task(client, starttime);\n"
      "CREATE INDEX task_i2 ON task(client, endtime);\n"
      "CREATE TABLE counters(nError,nTest);\n"
      "INSERT INTO counters VALUES(0,0);\n"
      "CREATE TABLE client(id INTEGER PRIMARY KEY, wantHalt);\n"
    );
    zScript = readFile(argv[2]);
    if( g.iTrace ) logMessage("begin script [%s]\n", argv[2]);
    runScript(0, 0, zScript, argv[2]);
    sqlite3_free(zScript);
    if( g.iTrace ) logMessage("end script [%s]\n", argv[2]);
    waitForClient(0, 2000, "during shutdown...\n");
    trySql("UPDATE client SET wantHalt=1");
    sqlite3_sleep(10);
    g.iTimeout = 0;
    iTimeout = 1000;
    while( ((rc = trySql("SELECT 1 FROM client"))==SQLITE_BUSY
        || rc==SQLITE_ROW) && iTimeout>0 ){
      sqlite3_sleep(10);
      iTimeout -= 10;
    }
    sqlite3_sleep(100);
    pStmt = prepareSql("SELECT nError, nTest FROM counters");
    iTimeout = 1000;
    while( (rc = sqlite3_step(pStmt))==SQLITE_BUSY && iTimeout>0 ){
      sqlite3_sleep(10);
      iTimeout -= 10;
    }
    if( rc==SQLITE_ROW ){
      g.nError += sqlite3_column_int(pStmt, 0);
      g.nTest += sqlite3_column_int(pStmt, 1);
    }
    sqlite3_finalize(pStmt);
  }
  sqlite3_close(g.db);  
  maybeClose(g.pLog);
  maybeClose(g.pErrLog);
  if( iClient==0 ){
    printf("Summary: %d errors in %d tests\n", g.nError, g.nTest);
  }
  return g.nError>0;
}

Added mptest/multiwrite01.test.











































































































































































































































































































































































































































































































































































































































































































































































































































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


--task 2 build-t2
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
  --sleep 1
  INSERT INTO t2 VALUES(1, randomblob(2000));
  INSERT INTO t2 VALUES(2, randomblob(1000));
  --sleep 1
  INSERT INTO t2 SELECT a+2, randomblob(1500) FROM t2;
  INSERT INTO t2 SELECT a+4, randomblob(1500) FROM t2;
  INSERT INTO t2 SELECT a+8, randomblob(1500) FROM t2;
  --sleep 1
  INSERT INTO t2 SELECT a+16, randomblob(1500) FROM t2;
  --sleep 1
  INSERT INTO t2 SELECT a+32, randomblob(1500) FROM t2;
  SELECT count(*) FROM t2;
  --match 64
  SELECT avg(length(b)) FROM t2;
  --match 1500.0
  --sleep 2
  UPDATE t2 SET b='x'||a||'y';
  SELECT total(length(b)) FROM t2;
  --match 247
  SELECT a FROM t2 WHERE b='x17y';
  --match 17
  CREATE INDEX t2b ON t2(b);
  SELECT a FROM t2 WHERE b='x17y';
  --match 17
  SELECT a FROM t2 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
  --match 29 28 27 26 25
--end

--task 3 build-t3
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
  --sleep 1
  INSERT INTO t3 VALUES(1, randomblob(2000));
  INSERT INTO t3 VALUES(2, randomblob(1000));
  --sleep 1
  INSERT INTO t3 SELECT a+2, randomblob(1500) FROM t3;
  INSERT INTO t3 SELECT a+4, randomblob(1500) FROM t3;
  INSERT INTO t3 SELECT a+8, randomblob(1500) FROM t3;
  --sleep 1
  INSERT INTO t3 SELECT a+16, randomblob(1500) FROM t3;
  --sleep 1
  INSERT INTO t3 SELECT a+32, randomblob(1500) FROM t3;
  SELECT count(*) FROM t3;
  --match 64
  SELECT avg(length(b)) FROM t3;
  --match 1500.0
  --sleep 2
  UPDATE t3 SET b='x'||a||'y';
  SELECT total(length(b)) FROM t3;
  --match 247
  SELECT a FROM t3 WHERE b='x17y';
  --match 17
  CREATE INDEX t3b ON t3(b);
  SELECT a FROM t3 WHERE b='x17y';
  --match 17
  SELECT a FROM t3 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
  --match 29 28 27 26 25
--end

--task 4 build-t4
  DROP TABLE IF EXISTS t4;
  CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
  --sleep 1
  INSERT INTO t4 VALUES(1, randomblob(2000));
  INSERT INTO t4 VALUES(2, randomblob(1000));
  --sleep 1
  INSERT INTO t4 SELECT a+2, randomblob(1500) FROM t4;
  INSERT INTO t4 SELECT a+4, randomblob(1500) FROM t4;
  INSERT INTO t4 SELECT a+8, randomblob(1500) FROM t4;
  --sleep 1
  INSERT INTO t4 SELECT a+16, randomblob(1500) FROM t4;
  --sleep 1
  INSERT INTO t4 SELECT a+32, randomblob(1500) FROM t4;
  SELECT count(*) FROM t4;
  --match 64
  SELECT avg(length(b)) FROM t4;
  --match 1500.0
  --sleep 2
  UPDATE t4 SET b='x'||a||'y';
  SELECT total(length(b)) FROM t4;
  --match 247
  SELECT a FROM t4 WHERE b='x17y';
  --match 17
  CREATE INDEX t4b ON t4(b);
  SELECT a FROM t4 WHERE b='x17y';
  --match 17
  SELECT a FROM t4 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
  --match 29 28 27 26 25
--end

--task 5 build-t5
  DROP TABLE IF EXISTS t5;
  CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
  --sleep 1
  INSERT INTO t5 VALUES(1, randomblob(2000));
  INSERT INTO t5 VALUES(2, randomblob(1000));
  --sleep 1
  INSERT INTO t5 SELECT a+2, randomblob(1500) FROM t5;
  INSERT INTO t5 SELECT a+4, randomblob(1500) FROM t5;
  INSERT INTO t5 SELECT a+8, randomblob(1500) FROM t5;
  --sleep 1
  INSERT INTO t5 SELECT a+16, randomblob(1500) FROM t5;
  --sleep 1
  INSERT INTO t5 SELECT a+32, randomblob(1500) FROM t5;
  SELECT count(*) FROM t5;
  --match 64
  SELECT avg(length(b)) FROM t5;
  --match 1500.0
  --sleep 2
  UPDATE t5 SET b='x'||a||'y';
  SELECT total(length(b)) FROM t5;
  --match 247
  SELECT a FROM t5 WHERE b='x17y';
  --match 17
  CREATE INDEX t5b ON t5(b);
  SELECT a FROM t5 WHERE b='x17y';
  --match 17
  SELECT a FROM t5 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
  --match 29 28 27 26 25
--end

--wait all
SELECT count(*), total(length(b)) FROM t1;
--match 64 247
SELECT count(*), total(length(b)) FROM t2;
--match 64 247
SELECT count(*), total(length(b)) FROM t3;
--match 64 247
SELECT count(*), total(length(b)) FROM t4;
--match 64 247
SELECT count(*), total(length(b)) FROM t5;
--match 64 247

--task 1
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 5
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 3
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 2
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 4
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--wait all

--task 5
  DROP INDEX t5b;
  --sleep 5
  PRAGMA integrity_check(10);
  --match ok
  CREATE INDEX t5b ON t5(b DESC);
--end
--task 3
  DROP INDEX t3b;
  --sleep 5
  PRAGMA integrity_check(10);
  --match ok
  CREATE INDEX t3b ON t3(b DESC);
--end
--task 1
  DROP INDEX t1b;
  --sleep 5
  PRAGMA integrity_check(10);
  --match ok
  CREATE INDEX t1b ON t1(b DESC);
--end
--task 2
  DROP INDEX t2b;
  --sleep 5
  PRAGMA integrity_check(10);
  --match ok
  CREATE INDEX t2b ON t2(b DESC);
--end
--task 4
  DROP INDEX t4b;
  --sleep 5
  PRAGMA integrity_check(10);
  --match ok
  CREATE INDEX t4b ON t4(b DESC);
--end
--wait all

--task 1
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 5
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 3
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 2
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 4
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--wait all

VACUUM;
PRAGMA integrity_check(10);
--match ok

--task 1
  UPDATE t1 SET b=randomblob(20000);
  --sleep 5
  UPDATE t1 SET b='x'||a||'y';
  SELECT a FROM t1 WHERE b='x63y';
  --match 63
--end
--task 2
  UPDATE t2 SET b=randomblob(20000);
  --sleep 5
  UPDATE t2 SET b='x'||a||'y';
  SELECT a FROM t2 WHERE b='x63y';
  --match 63
--end
--task 3
  UPDATE t3 SET b=randomblob(20000);
  --sleep 5
  UPDATE t3 SET b='x'||a||'y';
  SELECT a FROM t3 WHERE b='x63y';
  --match 63
--end
--task 4
  UPDATE t4 SET b=randomblob(20000);
  --sleep 5
  UPDATE t4 SET b='x'||a||'y';
  SELECT a FROM t4 WHERE b='x63y';
  --match 63
--end
--task 5
  UPDATE t5 SET b=randomblob(20000);
  --sleep 5
  UPDATE t5 SET b='x'||a||'y';
  SELECT a FROM t5 WHERE b='x63y';
  --match 63
--end
--wait all

--task 1
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 5
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 3
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 2
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--task 4
  SELECT t1.a FROM t1, t2
   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
   ORDER BY t1.a LIMIT 4
  --match 33 34 35 36
  SELECT t3.a FROM t3, t4
   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
   ORDER BY t3.a LIMIT 7
  --match 45 46 47 48 49 50 51
--end
--wait all

Changes to src/backup.c.

393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
    */
    nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
    assert( nSrcPage>=0 );
    for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
      const Pgno iSrcPg = p->iNext;                 /* Source page number */
      if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
        DbPage *pSrcPg;                             /* Source page object */
        rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);

        if( rc==SQLITE_OK ){
          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
          sqlite3PagerUnref(pSrcPg);
        }
      }
      p->iNext++;
    }







|
>







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

Changes to src/btree.c.

1577
1578
1579
1580
1581
1582
1583
1584

1585
1586
1587


1588

1589
1590
1591
1592
1593
1594
1595
1596
1597
....
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635

1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
....
1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878
1879
1880
....
2132
2133
2134
2135
2136
2137
2138













2139
2140
2141
2142
2143
2144
2145
....
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
....
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
....
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
....
3093
3094
3095
3096
3097
3098
3099


3100
3101

3102
3103
3104
3105
3106
3107
3108
....
3142
3143
3144
3145
3146
3147
3148


3149
3150
3151
3152
3153
3154
3155
3156
....
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
....
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
....
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
....
4070
4071
4072
4073
4074
4075
4076
4077


4078
4079
4080
4081
4082
4083
4084
....
4249
4250
4251
4252
4253
4254
4255

4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
....
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
....
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
....
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
....
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
....
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
....
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
....
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
....
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
....
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
....
7219
7220
7221
7222
7223
7224
7225




7226


7227

7228
7229
7230
7231
7232
7233
7234
7235
7236
....
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
....
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
....
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
....
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
....
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
....
8349
8350
8351
8352
8353
8354
8355











8356
8357
8358
8359
8360
8361
8362
** means we have started to be concerned about content and the disk
** read should occur at that point.
*/
static int btreeGetPage(
  BtShared *pBt,       /* The btree */
  Pgno pgno,           /* Number of the page to fetch */
  MemPage **ppPage,    /* Return the page in this parameter */
  int noContent        /* Do not load page content if true */

){
  int rc;
  DbPage *pDbPage;




  assert( sqlite3_mutex_held(pBt->mutex) );
  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
  if( rc ) return rc;
  *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
  return SQLITE_OK;
}

/*
** Retrieve a page from the pager cache. If the requested page is not
................................................................................
** convenience wrapper around separate calls to btreeGetPage() and 
** btreeInitPage().
**
** If an error occurs, then the value *ppPage is set to is undefined. It
** may remain unchanged, or it may be set to an invalid value.
*/
static int getAndInitPage(
  BtShared *pBt,          /* The database file */
  Pgno pgno,           /* Number of the page to get */
  MemPage **ppPage     /* Write the page pointer here */

){
  int rc;
  assert( sqlite3_mutex_held(pBt->mutex) );

  if( pgno>btreePagecount(pBt) ){
    rc = SQLITE_CORRUPT_BKPT;
  }else{
    rc = btreeGetPage(pBt, pgno, ppPage, 0);
    if( rc==SQLITE_OK ){
      rc = btreeInitPage(*ppPage);
      if( rc!=SQLITE_OK ){
        releasePage(*ppPage);
      }
    }
  }
................................................................................
    if( pBt==0 ){
      rc = SQLITE_NOMEM;
      goto btree_open_out;
    }
    rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
                          EXTRA_SIZE, flags, vfsFlags, pageReinit);
    if( rc==SQLITE_OK ){

      rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
    }
    if( rc!=SQLITE_OK ){
      goto btree_open_out;
    }
    pBt->openFlags = (u8)flags;
    pBt->db = db;
................................................................................
  BtShared *pBt = p->pBt;
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetCachesize(pBt->pPager, mxPage);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}














/*
** Change the way data is synced to disk in order to increase or decrease
** how well the database resists damage due to OS crashes and power
** failures.  Level 1 is the same as asynchronous (no syncs() occur and
** there is a high probability of damage)  Level 2 is the default.  There
** is a very low but non-zero probability of damage.  Level 3 reduces the
................................................................................
  int nPageFile = 0;   /* Number of pages in the database file */
  int nPageHeader;     /* Number of pages in the database according to hdr */

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( pBt->pPage1==0 );
  rc = sqlite3PagerSharedLock(pBt->pPager);
  if( rc!=SQLITE_OK ) return rc;
  rc = btreeGetPage(pBt, 1, &pPage1, 0);
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */
  nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
  sqlite3PagerPagecount(pBt->pPager, &nPageFile);
................................................................................
  }

  /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
  ** that it points at iFreePage. Also fix the pointer map entry for
  ** iPtrPage.
  */
  if( eType!=PTRMAP_ROOTPAGE ){
    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    rc = sqlite3PagerWrite(pPtrPage->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(pPtrPage);
      return rc;
................................................................................
      }
    } else {
      Pgno iFreePg;             /* Index of free page to move pLastPg to */
      MemPage *pLastPg;
      u8 eMode = BTALLOC_ANY;   /* Mode parameter for allocateBtreePage() */
      Pgno iNear = 0;           /* nearby parameter for allocateBtreePage() */

      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }

      /* If bCommit is zero, this loop runs exactly once and page pLastPg
      ** is swapped with the first free page pulled off the free list.
      **
................................................................................
    Pgno nOrig = btreePagecount(pBt);
    Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
    Pgno nFin = finalDbSize(pBt, nOrig, nFree);

    if( nOrig<nFin ){
      rc = SQLITE_CORRUPT_BKPT;
    }else if( nFree>0 ){


      invalidateAllOverflowCache(pBt);
      rc = incrVacuumStep(pBt, nFin, nOrig, 0);

      if( rc==SQLITE_OK ){
        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
        put4byte(&pBt->pPage1->aData[28], pBt->nPage);
      }
    }else{
      rc = SQLITE_DONE;
    }
................................................................................
      */
      return SQLITE_CORRUPT_BKPT;
    }

    nFree = get4byte(&pBt->pPage1->aData[36]);
    nFin = finalDbSize(pBt, nOrig, nFree);
    if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;



    for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
      rc = incrVacuumStep(pBt, nFin, iFree, 1);
    }
    if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
      put4byte(&pBt->pPage1->aData[32], 0);
      put4byte(&pBt->pPage1->aData[36], 0);
................................................................................
      pBt->nPage = nFin;
    }
    if( rc!=SQLITE_OK ){
      sqlite3PagerRollback(pPager);
    }
  }

  assert( nRef==sqlite3PagerRefcount(pPager) );
  return rc;
}

#else /* ifndef SQLITE_OMIT_AUTOVACUUM */
# define setChildPtrmaps(x) SQLITE_OK
#endif

................................................................................
    if( rc2!=SQLITE_OK ){
      rc = rc2;
    }

    /* The rollback may have destroyed the pPage1->aData value.  So
    ** call btreeGetPage() on page 1 again to make
    ** sure pPage1->aData is set correctly. */
    if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
      int nPage = get4byte(28+(u8*)pPage1->aData);
      testcase( nPage==0 );
      if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
      testcase( pBt->nPage!=nPage );
      pBt->nPage = nPage;
      releasePage(pPage1);
    }
................................................................................
      }
    }
  }
#endif

  assert( next==0 || rc==SQLITE_DONE );
  if( rc==SQLITE_OK ){
    rc = btreeGetPage(pBt, ovfl, &pPage, 0);
    assert( rc==SQLITE_OK || pPage==0 );
    if( rc==SQLITE_OK ){
      next = get4byte(pPage->aData);
    }
  }

  *pPgnoNext = next;
................................................................................
          nextPage = get4byte(aWrite);
          memcpy(aWrite, aSave, 4);
        }else
#endif

        {
          DbPage *pDbPage;
          rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);


          if( rc==SQLITE_OK ){
            aPayload = sqlite3PagerGetData(pDbPage);
            nextPage = get4byte(aPayload);
            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
            sqlite3PagerUnref(pDbPage);
            offset = 0;
          }
................................................................................
  int i = pCur->iPage;
  MemPage *pNewPage;
  BtShared *pBt = pCur->pBt;

  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );

  if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
    return SQLITE_CORRUPT_BKPT;
  }
  rc = getAndInitPage(pBt, newPgno, &pNewPage);
  if( rc ) return rc;
  pCur->apPage[i+1] = pNewPage;
  pCur->aiIdx[i+1] = 0;
  pCur->iPage++;

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
................................................................................
      releasePage(pCur->apPage[i]);
    }
    pCur->iPage = 0;
  }else if( pCur->pgnoRoot==0 ){
    pCur->eState = CURSOR_INVALID;
    return SQLITE_OK;
  }else{
    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    pCur->iPage = 0;

    /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
................................................................................
      }else{
        iTrunk = get4byte(&pPage1->aData[32]);
      }
      testcase( iTrunk==mxPage );
      if( iTrunk>mxPage ){
        rc = SQLITE_CORRUPT_BKPT;
      }else{
        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
      }
      if( rc ){
        pTrunk = 0;
        goto end_allocate_page;
      }
      assert( pTrunk!=0 );
      assert( pTrunk->aData!=0 );
................................................................................
          MemPage *pNewTrunk;
          Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
          if( iNewTrunk>mxPage ){ 
            rc = SQLITE_CORRUPT_BKPT;
            goto end_allocate_page;
          }
          testcase( iNewTrunk==mxPage );
          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
          if( rc!=SQLITE_OK ){
            goto end_allocate_page;
          }
          rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
          if( rc!=SQLITE_OK ){
            releasePage(pNewTrunk);
            goto end_allocate_page;
................................................................................
          rc = sqlite3PagerWrite(pTrunk->pDbPage);
          if( rc ) goto end_allocate_page;
          if( closest<k-1 ){
            memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
          }
          put4byte(&aData[4], k-1);
          noContent = !btreeGetHasContent(pBt, *pPgno);
          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
          if( rc==SQLITE_OK ){
            rc = sqlite3PagerWrite((*ppPage)->pDbPage);
            if( rc!=SQLITE_OK ){
              releasePage(*ppPage);
            }
          }
          searchList = 0;
................................................................................
      /* If *pPgno refers to a pointer-map page, allocate two new pages
      ** at the end of the file instead of one. The first allocated page
      ** becomes a new pointer-map page, the second is used by the caller.
      */
      MemPage *pPg = 0;
      TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
      assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerWrite(pPg->pDbPage);
        releasePage(pPg);
      }
      if( rc ) return rc;
      pBt->nPage++;
      if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
    }
#endif
    put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
    *pPgno = pBt->nPage;

    assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
    if( rc ) return rc;
    rc = sqlite3PagerWrite((*ppPage)->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
    }
    TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  }
................................................................................
  nFree = get4byte(&pPage1->aData[36]);
  put4byte(&pPage1->aData[36], nFree+1);

  if( pBt->btsFlags & BTS_SECURE_DELETE ){
    /* If the secure_delete option is enabled, then
    ** always fully overwrite deleted information with zeros.
    */
    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
     ||            ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
    ){
      goto freepage_out;
    }
    memset(pPage->aData, 0, pPage->pBt->pageSize);
  }

................................................................................
  ** first trunk page in the current free-list. This block tests if it
  ** is possible to add the page as a new free-list leaf.
  */
  if( nFree!=0 ){
    u32 nLeaf;                /* Initial number of leaf cells on trunk page */

    iTrunk = get4byte(&pPage1->aData[32]);
    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
    if( rc!=SQLITE_OK ){
      goto freepage_out;
    }

    nLeaf = get4byte(&pTrunk->aData[4]);
    assert( pBt->usableSize>32 );
    if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
................................................................................

  /* If control flows to this point, then it was not possible to add the
  ** the page being freed as a leaf page of the first trunk in the free-list.
  ** Possibly because the free-list is empty, or possibly because the 
  ** first trunk in the free-list is full. Either way, the page being freed
  ** will become the new first trunk page in the free-list.
  */
  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
    goto freepage_out;
  }
  rc = sqlite3PagerWrite(pPage->pDbPage);
  if( rc!=SQLITE_OK ){
    goto freepage_out;
  }
  put4byte(pPage->aData, iTrunk);
................................................................................
  if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
    pRight = &pParent->aData[pParent->hdrOffset+8];
  }else{
    pRight = findCell(pParent, i+nxDiv-pParent->nOverflow);
  }
  pgno = get4byte(pRight);
  while( 1 ){
    rc = getAndInitPage(pBt, pgno, &apOld[i]);
    if( rc ){
      memset(apOld, 0, (i+1)*sizeof(MemPage*));
      goto balance_cleanup;
    }
    nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
    if( (i--)==0 ) break;

................................................................................
      ** allocated pgnoMove. If required (i.e. if it was not allocated
      ** by extending the file), the current page at position pgnoMove
      ** is already journaled.
      */
      u8 eType = 0;
      Pgno iPtrPage = 0;





      releasePage(pPageMove);




      /* Move the page currently at pgnoRoot to pgnoMove. */
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
      if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
        rc = SQLITE_CORRUPT_BKPT;
      }
................................................................................
      rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
      releasePage(pRoot);

      /* Obtain the page at pgnoRoot */
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = sqlite3PagerWrite(pRoot->pDbPage);
      if( rc!=SQLITE_OK ){
        releasePage(pRoot);
        return rc;
................................................................................
  int i;

  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pgno>btreePagecount(pBt) ){
    return SQLITE_CORRUPT_BKPT;
  }

  rc = getAndInitPage(pBt, pgno, &pPage);
  if( rc ) return rc;
  for(i=0; i<pPage->nCell; i++){
    pCell = findCell(pPage, i);
    if( !pPage->leaf ){
      rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
      if( rc ) goto cleardatabasepage_out;
    }
................................................................................
  ** This error is caught long before control reaches this point.
  */
  if( NEVER(pBt->pCursor) ){
    sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
    return SQLITE_LOCKED_SHAREDCACHE;
  }

  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
  if( rc ) return rc;
  rc = sqlite3BtreeClearTable(p, iTable, 0);
  if( rc ){
    releasePage(pPage);
    return rc;
  }

................................................................................
      }else{
        /* The table being dropped does not have the largest root-page
        ** number in the database. So move the page that does into the 
        ** gap left by the deleted root-page.
        */
        MemPage *pMove;
        releasePage(pPage);
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
        releasePage(pMove);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        pMove = 0;
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
        freePage(pMove, &rc);
        releasePage(pMove);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        *piMoved = maxRootPgno;
      }
................................................................................

  /* Check that the page exists
  */
  pBt = pCheck->pBt;
  usableSize = pBt->usableSize;
  if( iPage==0 ) return 0;
  if( checkRef(pCheck, iPage, zParentContext) ) return 0;
  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
    checkAppendMsg(pCheck, zContext,
       "unable to get the page. error code=%d", rc);
    return 0;
  }

  /* Clear MemPage.isInit to make sure the corruption detection code in
  ** btreeInitPage() is executed.  */
................................................................................
  if( rc!=SQLITE_OK ){
    return rc;
  }
  assert( pCsr->eState!=CURSOR_REQUIRESEEK );
  if( pCsr->eState!=CURSOR_VALID ){
    return SQLITE_ABORT;
  }












  /* Check some assumptions: 
  **   (a) the cursor is open for writing,
  **   (b) there is a read/write transaction open,
  **   (c) the connection holds a write-lock on the table (if required),
  **   (d) there are no conflicting read-locks, and
  **   (e) the cursor points at a valid row of an intKey table.







|
>



>
>

>

|







 







|
|
|
>







|







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







|







 







>
>
|
|
>







 







>
>
|







 







|







 







|







 







|







 







|
>
>







 







>



|







 







|







 







|







 







|







 







|







 







|













|







 







|







 







|







 







|







 







|







 







>
>
>
>

>
>
|
>

|







 







|







 







|







 







|







 







|









|







 







|







 







>
>
>
>
>
>
>
>
>
>
>







1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
....
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
....
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
....
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
....
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
....
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
....
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
....
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
....
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
....
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
....
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
....
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
....
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
....
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
....
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
....
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
....
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
....
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
....
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
....
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
....
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
....
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
....
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
....
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
....
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
....
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
....
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
....
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
....
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
....
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
** means we have started to be concerned about content and the disk
** read should occur at that point.
*/
static int btreeGetPage(
  BtShared *pBt,       /* The btree */
  Pgno pgno,           /* Number of the page to fetch */
  MemPage **ppPage,    /* Return the page in this parameter */
  int noContent,       /* Do not load page content if true */
  int bReadonly        /* True if a read-only (mmap) page is ok */
){
  int rc;
  DbPage *pDbPage;
  int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0) 
            | (bReadonly ? PAGER_ACQUIRE_READONLY : 0);

  assert( noContent==0 || bReadonly==0 );
  assert( sqlite3_mutex_held(pBt->mutex) );
  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
  if( rc ) return rc;
  *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
  return SQLITE_OK;
}

/*
** Retrieve a page from the pager cache. If the requested page is not
................................................................................
** convenience wrapper around separate calls to btreeGetPage() and 
** btreeInitPage().
**
** If an error occurs, then the value *ppPage is set to is undefined. It
** may remain unchanged, or it may be set to an invalid value.
*/
static int getAndInitPage(
  BtShared *pBt,                  /* The database file */
  Pgno pgno,                      /* Number of the page to get */
  MemPage **ppPage,               /* Write the page pointer here */
  int bReadonly                   /* True if a read-only (mmap) page is ok */
){
  int rc;
  assert( sqlite3_mutex_held(pBt->mutex) );

  if( pgno>btreePagecount(pBt) ){
    rc = SQLITE_CORRUPT_BKPT;
  }else{
    rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly);
    if( rc==SQLITE_OK ){
      rc = btreeInitPage(*ppPage);
      if( rc!=SQLITE_OK ){
        releasePage(*ppPage);
      }
    }
  }
................................................................................
    if( pBt==0 ){
      rc = SQLITE_NOMEM;
      goto btree_open_out;
    }
    rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
                          EXTRA_SIZE, flags, vfsFlags, pageReinit);
    if( rc==SQLITE_OK ){
      sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
      rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
    }
    if( rc!=SQLITE_OK ){
      goto btree_open_out;
    }
    pBt->openFlags = (u8)flags;
    pBt->db = db;
................................................................................
  BtShared *pBt = p->pBt;
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetCachesize(pBt->pPager, mxPage);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}

/*
** Change the limit on the amount of the database file that may be
** memory mapped.
*/
int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
  BtShared *pBt = p->pBt;
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}

/*
** Change the way data is synced to disk in order to increase or decrease
** how well the database resists damage due to OS crashes and power
** failures.  Level 1 is the same as asynchronous (no syncs() occur and
** there is a high probability of damage)  Level 2 is the default.  There
** is a very low but non-zero probability of damage.  Level 3 reduces the
................................................................................
  int nPageFile = 0;   /* Number of pages in the database file */
  int nPageHeader;     /* Number of pages in the database according to hdr */

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( pBt->pPage1==0 );
  rc = sqlite3PagerSharedLock(pBt->pPager);
  if( rc!=SQLITE_OK ) return rc;
  rc = btreeGetPage(pBt, 1, &pPage1, 0, 0);
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */
  nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
  sqlite3PagerPagecount(pBt->pPager, &nPageFile);
................................................................................
  }

  /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
  ** that it points at iFreePage. Also fix the pointer map entry for
  ** iPtrPage.
  */
  if( eType!=PTRMAP_ROOTPAGE ){
    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    rc = sqlite3PagerWrite(pPtrPage->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(pPtrPage);
      return rc;
................................................................................
      }
    } else {
      Pgno iFreePg;             /* Index of free page to move pLastPg to */
      MemPage *pLastPg;
      u8 eMode = BTALLOC_ANY;   /* Mode parameter for allocateBtreePage() */
      Pgno iNear = 0;           /* nearby parameter for allocateBtreePage() */

      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }

      /* If bCommit is zero, this loop runs exactly once and page pLastPg
      ** is swapped with the first free page pulled off the free list.
      **
................................................................................
    Pgno nOrig = btreePagecount(pBt);
    Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
    Pgno nFin = finalDbSize(pBt, nOrig, nFree);

    if( nOrig<nFin ){
      rc = SQLITE_CORRUPT_BKPT;
    }else if( nFree>0 ){
      rc = saveAllCursors(pBt, 0, 0);
      if( rc==SQLITE_OK ){
        invalidateAllOverflowCache(pBt);
        rc = incrVacuumStep(pBt, nFin, nOrig, 0);
      }
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
        put4byte(&pBt->pPage1->aData[28], pBt->nPage);
      }
    }else{
      rc = SQLITE_DONE;
    }
................................................................................
      */
      return SQLITE_CORRUPT_BKPT;
    }

    nFree = get4byte(&pBt->pPage1->aData[36]);
    nFin = finalDbSize(pBt, nOrig, nFree);
    if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
    if( nFin<nOrig ){
      rc = saveAllCursors(pBt, 0, 0);
    }
    for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
      rc = incrVacuumStep(pBt, nFin, iFree, 1);
    }
    if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
      put4byte(&pBt->pPage1->aData[32], 0);
      put4byte(&pBt->pPage1->aData[36], 0);
................................................................................
      pBt->nPage = nFin;
    }
    if( rc!=SQLITE_OK ){
      sqlite3PagerRollback(pPager);
    }
  }

  assert( nRef>=sqlite3PagerRefcount(pPager) );
  return rc;
}

#else /* ifndef SQLITE_OMIT_AUTOVACUUM */
# define setChildPtrmaps(x) SQLITE_OK
#endif

................................................................................
    if( rc2!=SQLITE_OK ){
      rc = rc2;
    }

    /* The rollback may have destroyed the pPage1->aData value.  So
    ** call btreeGetPage() on page 1 again to make
    ** sure pPage1->aData is set correctly. */
    if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){
      int nPage = get4byte(28+(u8*)pPage1->aData);
      testcase( nPage==0 );
      if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
      testcase( pBt->nPage!=nPage );
      pBt->nPage = nPage;
      releasePage(pPage1);
    }
................................................................................
      }
    }
  }
#endif

  assert( next==0 || rc==SQLITE_DONE );
  if( rc==SQLITE_OK ){
    rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0));
    assert( rc==SQLITE_OK || pPage==0 );
    if( rc==SQLITE_OK ){
      next = get4byte(pPage->aData);
    }
  }

  *pPgnoNext = next;
................................................................................
          nextPage = get4byte(aWrite);
          memcpy(aWrite, aSave, 4);
        }else
#endif

        {
          DbPage *pDbPage;
          rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
              (eOp==0 ? PAGER_ACQUIRE_READONLY : 0)
          );
          if( rc==SQLITE_OK ){
            aPayload = sqlite3PagerGetData(pDbPage);
            nextPage = get4byte(aPayload);
            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
            sqlite3PagerUnref(pDbPage);
            offset = 0;
          }
................................................................................
  int i = pCur->iPage;
  MemPage *pNewPage;
  BtShared *pBt = pCur->pBt;

  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
  assert( pCur->iPage>=0 );
  if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
    return SQLITE_CORRUPT_BKPT;
  }
  rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0));
  if( rc ) return rc;
  pCur->apPage[i+1] = pNewPage;
  pCur->aiIdx[i+1] = 0;
  pCur->iPage++;

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
................................................................................
      releasePage(pCur->apPage[i]);
    }
    pCur->iPage = 0;
  }else if( pCur->pgnoRoot==0 ){
    pCur->eState = CURSOR_INVALID;
    return SQLITE_OK;
  }else{
    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    pCur->iPage = 0;

    /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
................................................................................
      }else{
        iTrunk = get4byte(&pPage1->aData[32]);
      }
      testcase( iTrunk==mxPage );
      if( iTrunk>mxPage ){
        rc = SQLITE_CORRUPT_BKPT;
      }else{
        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
      }
      if( rc ){
        pTrunk = 0;
        goto end_allocate_page;
      }
      assert( pTrunk!=0 );
      assert( pTrunk->aData!=0 );
................................................................................
          MemPage *pNewTrunk;
          Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
          if( iNewTrunk>mxPage ){ 
            rc = SQLITE_CORRUPT_BKPT;
            goto end_allocate_page;
          }
          testcase( iNewTrunk==mxPage );
          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0);
          if( rc!=SQLITE_OK ){
            goto end_allocate_page;
          }
          rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
          if( rc!=SQLITE_OK ){
            releasePage(pNewTrunk);
            goto end_allocate_page;
................................................................................
          rc = sqlite3PagerWrite(pTrunk->pDbPage);
          if( rc ) goto end_allocate_page;
          if( closest<k-1 ){
            memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
          }
          put4byte(&aData[4], k-1);
          noContent = !btreeGetHasContent(pBt, *pPgno);
          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent, 0);
          if( rc==SQLITE_OK ){
            rc = sqlite3PagerWrite((*ppPage)->pDbPage);
            if( rc!=SQLITE_OK ){
              releasePage(*ppPage);
            }
          }
          searchList = 0;
................................................................................
      /* If *pPgno refers to a pointer-map page, allocate two new pages
      ** at the end of the file instead of one. The first allocated page
      ** becomes a new pointer-map page, the second is used by the caller.
      */
      MemPage *pPg = 0;
      TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
      assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0);
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerWrite(pPg->pDbPage);
        releasePage(pPg);
      }
      if( rc ) return rc;
      pBt->nPage++;
      if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
    }
#endif
    put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
    *pPgno = pBt->nPage;

    assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0);
    if( rc ) return rc;
    rc = sqlite3PagerWrite((*ppPage)->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
    }
    TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  }
................................................................................
  nFree = get4byte(&pPage1->aData[36]);
  put4byte(&pPage1->aData[36], nFree+1);

  if( pBt->btsFlags & BTS_SECURE_DELETE ){
    /* If the secure_delete option is enabled, then
    ** always fully overwrite deleted information with zeros.
    */
    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) )
     ||            ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
    ){
      goto freepage_out;
    }
    memset(pPage->aData, 0, pPage->pBt->pageSize);
  }

................................................................................
  ** first trunk page in the current free-list. This block tests if it
  ** is possible to add the page as a new free-list leaf.
  */
  if( nFree!=0 ){
    u32 nLeaf;                /* Initial number of leaf cells on trunk page */

    iTrunk = get4byte(&pPage1->aData[32]);
    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
    if( rc!=SQLITE_OK ){
      goto freepage_out;
    }

    nLeaf = get4byte(&pTrunk->aData[4]);
    assert( pBt->usableSize>32 );
    if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
................................................................................

  /* If control flows to this point, then it was not possible to add the
  ** the page being freed as a leaf page of the first trunk in the free-list.
  ** Possibly because the free-list is empty, or possibly because the 
  ** first trunk in the free-list is full. Either way, the page being freed
  ** will become the new first trunk page in the free-list.
  */
  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){
    goto freepage_out;
  }
  rc = sqlite3PagerWrite(pPage->pDbPage);
  if( rc!=SQLITE_OK ){
    goto freepage_out;
  }
  put4byte(pPage->aData, iTrunk);
................................................................................
  if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
    pRight = &pParent->aData[pParent->hdrOffset+8];
  }else{
    pRight = findCell(pParent, i+nxDiv-pParent->nOverflow);
  }
  pgno = get4byte(pRight);
  while( 1 ){
    rc = getAndInitPage(pBt, pgno, &apOld[i], 0);
    if( rc ){
      memset(apOld, 0, (i+1)*sizeof(MemPage*));
      goto balance_cleanup;
    }
    nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
    if( (i--)==0 ) break;

................................................................................
      ** allocated pgnoMove. If required (i.e. if it was not allocated
      ** by extending the file), the current page at position pgnoMove
      ** is already journaled.
      */
      u8 eType = 0;
      Pgno iPtrPage = 0;

      /* Save the positions of any open cursors. This is required in
      ** case they are holding a reference to an xFetch reference
      ** corresponding to page pgnoRoot.  */
      rc = saveAllCursors(pBt, 0, 0);
      releasePage(pPageMove);
      if( rc!=SQLITE_OK ){
        return rc;
      }

      /* Move the page currently at pgnoRoot to pgnoMove. */
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
      if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
        rc = SQLITE_CORRUPT_BKPT;
      }
................................................................................
      rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
      releasePage(pRoot);

      /* Obtain the page at pgnoRoot */
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = sqlite3PagerWrite(pRoot->pDbPage);
      if( rc!=SQLITE_OK ){
        releasePage(pRoot);
        return rc;
................................................................................
  int i;

  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pgno>btreePagecount(pBt) ){
    return SQLITE_CORRUPT_BKPT;
  }

  rc = getAndInitPage(pBt, pgno, &pPage, 0);
  if( rc ) return rc;
  for(i=0; i<pPage->nCell; i++){
    pCell = findCell(pPage, i);
    if( !pPage->leaf ){
      rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
      if( rc ) goto cleardatabasepage_out;
    }
................................................................................
  ** This error is caught long before control reaches this point.
  */
  if( NEVER(pBt->pCursor) ){
    sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
    return SQLITE_LOCKED_SHAREDCACHE;
  }

  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0);
  if( rc ) return rc;
  rc = sqlite3BtreeClearTable(p, iTable, 0);
  if( rc ){
    releasePage(pPage);
    return rc;
  }

................................................................................
      }else{
        /* The table being dropped does not have the largest root-page
        ** number in the database. So move the page that does into the 
        ** gap left by the deleted root-page.
        */
        MemPage *pMove;
        releasePage(pPage);
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
        releasePage(pMove);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        pMove = 0;
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
        freePage(pMove, &rc);
        releasePage(pMove);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        *piMoved = maxRootPgno;
      }
................................................................................

  /* Check that the page exists
  */
  pBt = pCheck->pBt;
  usableSize = pBt->usableSize;
  if( iPage==0 ) return 0;
  if( checkRef(pCheck, iPage, zParentContext) ) return 0;
  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){
    checkAppendMsg(pCheck, zContext,
       "unable to get the page. error code=%d", rc);
    return 0;
  }

  /* Clear MemPage.isInit to make sure the corruption detection code in
  ** btreeInitPage() is executed.  */
................................................................................
  if( rc!=SQLITE_OK ){
    return rc;
  }
  assert( pCsr->eState!=CURSOR_REQUIRESEEK );
  if( pCsr->eState!=CURSOR_VALID ){
    return SQLITE_ABORT;
  }

  /* Save the positions of all other cursors open on this table. This is
  ** required in case any of them are holding references to an xFetch
  ** version of the b-tree page modified by the accessPayload call below.
  **
  ** Note that pCsr must be open on a BTREE_INTKEY table and saveCursorPosition()
  ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence
  ** saveAllCursors can only return SQLITE_OK.
  */
  VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
  assert( rc==SQLITE_OK );

  /* Check some assumptions: 
  **   (a) the cursor is open for writing,
  **   (b) there is a read/write transaction open,
  **   (c) the connection holds a write-lock on the table (if required),
  **   (d) there are no conflicting read-locks, and
  **   (e) the cursor points at a valid row of an intKey table.

Changes to src/btree.h.

59
60
61
62
63
64
65

66
67
68
69
70
71
72
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
#define BTREE_MEMORY        2  /* This is an in-memory DB */
#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */

int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);

int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeMaxPageCount(Btree*,int);
u32 sqlite3BtreeLastPage(Btree*);
int sqlite3BtreeSecureDelete(Btree*,int);







>







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
#define BTREE_MEMORY        2  /* This is an in-memory DB */
#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */

int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeMaxPageCount(Btree*,int);
u32 sqlite3BtreeLastPage(Btree*);
int sqlite3BtreeSecureDelete(Btree*,int);

Changes to src/ctime.c.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58



59
60
61
62
63
64
65
...
143
144
145
146
147
148
149



150
151
152
153
154
155
156
...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
...
378
379
380
381
382
383
384
385
386



387
388
389
390
391
392
393
#endif
#ifdef SQLITE_CHECK_PAGES
  "CHECK_PAGES",
#endif
#ifdef SQLITE_COVERAGE_TEST
  "COVERAGE_TEST",
#endif
#ifdef SQLITE_CURDIR
  "CURDIR",
#endif
#ifdef SQLITE_DEBUG
  "DEBUG",
#endif
#ifdef SQLITE_DEFAULT_LOCKING_MODE
  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),



#endif
#ifdef SQLITE_DISABLE_DIRSYNC
  "DISABLE_DIRSYNC",
#endif
#ifdef SQLITE_DISABLE_LFS
  "DISABLE_LFS",
#endif
................................................................................
#endif
#ifdef SQLITE_INT64_TYPE
  "INT64_TYPE",
#endif
#ifdef SQLITE_LOCK_TRACE
  "LOCK_TRACE",
#endif



#ifdef SQLITE_MAX_SCHEMA_RETRY
  "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
#endif
#ifdef SQLITE_MEMDEBUG
  "MEMDEBUG",
#endif
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
................................................................................
#endif
#ifdef SQLITE_OMIT_CAST
  "OMIT_CAST",
#endif
#ifdef SQLITE_OMIT_CHECK
  "OMIT_CHECK",
#endif
/* // redundant
** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
**   "OMIT_COMPILEOPTION_DIAGS",
** #endif
*/
#ifdef SQLITE_OMIT_COMPLETE
  "OMIT_COMPLETE",
#endif
#ifdef SQLITE_OMIT_COMPOUND_SELECT
  "OMIT_COMPOUND_SELECT",
#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
................................................................................
#endif
#ifdef SQLITE_SOUNDEX
  "SOUNDEX",
#endif
#ifdef SQLITE_TCL
  "TCL",
#endif
#ifdef SQLITE_TEMP_STORE
  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
#endif
#ifdef SQLITE_TEST
  "TEST",
#endif
#ifdef SQLITE_THREADSAFE
  "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#endif
#ifdef SQLITE_USE_ALLOCA
  "USE_ALLOCA",
#endif
#ifdef SQLITE_ZERO_MALLOC
  "ZERO_MALLOC"
................................................................................
  int i, n;
  if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
  n = sqlite3Strlen30(zOptName);

  /* Since ArraySize(azCompileOpt) is normally in single digits, a
  ** linear search is adequate.  No need for a binary search. */
  for(i=0; i<ArraySize(azCompileOpt); i++){
    if(   (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0)
       && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;



  }
  return 0;
}

/*
** Return the N-th compile-time option string.  If N is out of range,
** return a NULL pointer.







<
<
<





>
>
>







 







>
>
>







 







<
<
<
<
<







 







|





|







 







|
|
>
>
>







44
45
46
47
48
49
50



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
203
204
205
206
207
208
209





210
211
212
213
214
215
216
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
#endif
#ifdef SQLITE_CHECK_PAGES
  "CHECK_PAGES",
#endif
#ifdef SQLITE_COVERAGE_TEST
  "COVERAGE_TEST",
#endif



#ifdef SQLITE_DEBUG
  "DEBUG",
#endif
#ifdef SQLITE_DEFAULT_LOCKING_MODE
  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
  "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
#endif
#ifdef SQLITE_DISABLE_DIRSYNC
  "DISABLE_DIRSYNC",
#endif
#ifdef SQLITE_DISABLE_LFS
  "DISABLE_LFS",
#endif
................................................................................
#endif
#ifdef SQLITE_INT64_TYPE
  "INT64_TYPE",
#endif
#ifdef SQLITE_LOCK_TRACE
  "LOCK_TRACE",
#endif
#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
  "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
#endif
#ifdef SQLITE_MAX_SCHEMA_RETRY
  "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
#endif
#ifdef SQLITE_MEMDEBUG
  "MEMDEBUG",
#endif
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
................................................................................
#endif
#ifdef SQLITE_OMIT_CAST
  "OMIT_CAST",
#endif
#ifdef SQLITE_OMIT_CHECK
  "OMIT_CHECK",
#endif





#ifdef SQLITE_OMIT_COMPLETE
  "OMIT_COMPLETE",
#endif
#ifdef SQLITE_OMIT_COMPOUND_SELECT
  "OMIT_COMPOUND_SELECT",
#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
................................................................................
#endif
#ifdef SQLITE_SOUNDEX
  "SOUNDEX",
#endif
#ifdef SQLITE_TCL
  "TCL",
#endif
#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
#endif
#ifdef SQLITE_TEST
  "TEST",
#endif
#if defined(SQLITE_THREADSAFE)
  "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#endif
#ifdef SQLITE_USE_ALLOCA
  "USE_ALLOCA",
#endif
#ifdef SQLITE_ZERO_MALLOC
  "ZERO_MALLOC"
................................................................................
  int i, n;
  if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
  n = sqlite3Strlen30(zOptName);

  /* Since ArraySize(azCompileOpt) is normally in single digits, a
  ** linear search is adequate.  No need for a binary search. */
  for(i=0; i<ArraySize(azCompileOpt); i++){
    if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
     && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
    ){
      return 1;
    }
  }
  return 0;
}

/*
** Return the N-th compile-time option string.  If N is out of range,
** return a NULL pointer.

Changes to src/func.c.

688
689
690
691
692
693
694







695
696
697
698
699
700
701
        return 0;
      }
      prevEscape = 0;
    }
  }
  return *zString==0;
}








/*
** Count the number of times that the LIKE operator (or GLOB which is
** just a variation of LIKE) gets called.  This is used for testing
** only.
*/
#ifdef SQLITE_TEST







>
>
>
>
>
>
>







688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
        return 0;
      }
      prevEscape = 0;
    }
  }
  return *zString==0;
}

/*
** The sqlite3_strglob() interface.
*/
int sqlite3_strglob(const char *zGlobPattern, const char *zString){
  return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
}

/*
** Count the number of times that the LIKE operator (or GLOB which is
** just a variation of LIKE) gets called.  This is used for testing
** only.
*/
#ifdef SQLITE_TEST

Changes to src/global.c.

152
153
154
155
156
157
158


159
160
161
162
163
164
165
   500,                       /* nLookaside */
   {0,0,0,0,0,0,0,0},         /* m */
   {0,0,0,0,0,0,0,0,0},       /* mutex */
   {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
   (void*)0,                  /* pHeap */
   0,                         /* nHeap */
   0, 0,                      /* mnHeap, mxHeap */


   (void*)0,                  /* pScratch */
   0,                         /* szScratch */
   0,                         /* nScratch */
   (void*)0,                  /* pPage */
   0,                         /* szPage */
   0,                         /* nPage */
   0,                         /* mxParserStack */







>
>







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

Changes to src/legacy.c.

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  void *pArg,                 /* First argument to xCallback() */
  char **pzErrMsg             /* Write error messages here */
){
  int rc = SQLITE_OK;         /* Return code */
  const char *zLeftover;      /* Tail of unprocessed SQL */
  sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
  char **azCols = 0;          /* Names of result columns */
  int nRetry = 0;             /* Number of retry attempts */
  int callbackIsInit;         /* True if callback data is initialized */

  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
  if( zSql==0 ) zSql = "";

  sqlite3_mutex_enter(db->mutex);
  sqlite3Error(db, SQLITE_OK, 0);
  while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
    int nCol;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
    assert( rc==SQLITE_OK || pStmt==0 );
    if( rc!=SQLITE_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
................................................................................
          goto exec_out;
        }
      }

      if( rc!=SQLITE_ROW ){
        rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
        pStmt = 0;
        if( rc!=SQLITE_SCHEMA ){
          nRetry = 0;
          zSql = zLeftover;
          while( sqlite3Isspace(zSql[0]) ) zSql++;
        }
        break;
      }
    }

    sqlite3DbFree(db, azCols);
    azCols = 0;
  }







<







|




|







 







<
<
|
|
<







34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
...
103
104
105
106
107
108
109


110
111

112
113
114
115
116
117
118
  void *pArg,                 /* First argument to xCallback() */
  char **pzErrMsg             /* Write error messages here */
){
  int rc = SQLITE_OK;         /* Return code */
  const char *zLeftover;      /* Tail of unprocessed SQL */
  sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
  char **azCols = 0;          /* Names of result columns */

  int callbackIsInit;         /* True if callback data is initialized */

  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
  if( zSql==0 ) zSql = "";

  sqlite3_mutex_enter(db->mutex);
  sqlite3Error(db, SQLITE_OK, 0);
  while( rc==SQLITE_OK && zSql[0] ){
    int nCol;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
    assert( rc==SQLITE_OK || pStmt==0 );
    if( rc!=SQLITE_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
................................................................................
          goto exec_out;
        }
      }

      if( rc!=SQLITE_ROW ){
        rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
        pStmt = 0;


        zSql = zLeftover;
        while( sqlite3Isspace(zSql[0]) ) zSql++;

        break;
      }
    }

    sqlite3DbFree(db, azCols);
    azCols = 0;
  }

Changes to src/loadext.c.

411
412
413
414
415
416
417


418
419













420
421
422
423
424
425
426
...
429
430
431
432
433
434
435
436
437
438
439
440








441
442
443
444
445
446
447
448
449
450
451
452
453


































454
455
456
457
458
459
460
461
462
463
464


465


466
467
468
469
470
471
472
473
  const char *zProc,    /* Entry point.  Use "sqlite3_extension_init" if 0 */
  char **pzErrMsg       /* Put error message here if not 0 */
){
  sqlite3_vfs *pVfs = db->pVfs;
  void *handle;
  int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
  char *zErrmsg = 0;


  void **aHandle;
  int nMsg = 300 + sqlite3Strlen30(zFile);














  if( pzErrMsg ) *pzErrMsg = 0;

  /* Ticket #1863.  To avoid a creating security problems for older
  ** applications that relink against newer versions of SQLite, the
  ** ability to run load_extension is turned off by default.  One
  ** must call sqlite3_enable_load_extension() to turn on extension
................................................................................
  if( (db->flags & SQLITE_LoadExtension)==0 ){
    if( pzErrMsg ){
      *pzErrMsg = sqlite3_mprintf("not authorized");
    }
    return SQLITE_ERROR;
  }

  if( zProc==0 ){
    zProc = "sqlite3_extension_init";
  }

  handle = sqlite3OsDlOpen(pVfs, zFile);








  if( handle==0 ){
    if( pzErrMsg ){
      *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
      if( zErrmsg ){
        sqlite3_snprintf(nMsg, zErrmsg, 
            "unable to open shared library [%s]", zFile);
        sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
      }
    }
    return SQLITE_ERROR;
  }
  xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
                   sqlite3OsDlSym(pVfs, handle, zProc);


































  if( xInit==0 ){
    if( pzErrMsg ){
      nMsg += sqlite3Strlen30(zProc);
      *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
      if( zErrmsg ){
        sqlite3_snprintf(nMsg, zErrmsg,
            "no entry point [%s] in shared library [%s]", zProc,zFile);
        sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
      }
      sqlite3OsDlClose(pVfs, handle);
    }


    return SQLITE_ERROR;


  }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){
    if( pzErrMsg ){
      *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
    }
    sqlite3_free(zErrmsg);
    sqlite3OsDlClose(pVfs, handle);
    return SQLITE_ERROR;
  }







>
>


>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
|
|
<

>
>
>
>
>
>
>
>












|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|



|


<

>
>

>
>
|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
...
444
445
446
447
448
449
450

451
452

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525
526
527
528
529
530
531
  const char *zProc,    /* Entry point.  Use "sqlite3_extension_init" if 0 */
  char **pzErrMsg       /* Put error message here if not 0 */
){
  sqlite3_vfs *pVfs = db->pVfs;
  void *handle;
  int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
  char *zErrmsg = 0;
  const char *zEntry;
  char *zAltEntry = 0;
  void **aHandle;
  int nMsg = 300 + sqlite3Strlen30(zFile);
  int ii;

  /* Shared library endings to try if zFile cannot be loaded as written */
  static const char *azEndings[] = {
#if SQLITE_OS_WIN
     "dll"   
#elif defined(__APPLE__)
     "dylib"
#else
     "so"
#endif
  };


  if( pzErrMsg ) *pzErrMsg = 0;

  /* Ticket #1863.  To avoid a creating security problems for older
  ** applications that relink against newer versions of SQLite, the
  ** ability to run load_extension is turned off by default.  One
  ** must call sqlite3_enable_load_extension() to turn on extension
................................................................................
  if( (db->flags & SQLITE_LoadExtension)==0 ){
    if( pzErrMsg ){
      *pzErrMsg = sqlite3_mprintf("not authorized");
    }
    return SQLITE_ERROR;
  }


  zEntry = zProc ? zProc : "sqlite3_extension_init";


  handle = sqlite3OsDlOpen(pVfs, zFile);
#if SQLITE_OS_UNIX || SQLITE_OS_WIN
  for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
    char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]);
    if( zAltFile==0 ) return SQLITE_NOMEM;
    handle = sqlite3OsDlOpen(pVfs, zAltFile);
    sqlite3_free(zAltFile);
  }
#endif
  if( handle==0 ){
    if( pzErrMsg ){
      *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
      if( zErrmsg ){
        sqlite3_snprintf(nMsg, zErrmsg, 
            "unable to open shared library [%s]", zFile);
        sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
      }
    }
    return SQLITE_ERROR;
  }
  xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
                   sqlite3OsDlSym(pVfs, handle, zEntry);

  /* If no entry point was specified and the default legacy
  ** entry point name "sqlite3_extension_init" was not found, then
  ** construct an entry point name "sqlite3_X_init" where the X is
  ** replaced by the lowercase value of every ASCII alphabetic 
  ** character in the filename after the last "/" upto the first ".",
  ** and eliding the first three characters if they are "lib".  
  ** Examples:
  **
  **    /usr/local/lib/libExample5.4.3.so ==>  sqlite3_example_init
  **    C:/lib/mathfuncs.dll              ==>  sqlite3_mathfuncs_init
  */
  if( xInit==0 && zProc==0 ){
    int iFile, iEntry, c;
    int ncFile = sqlite3Strlen30(zFile);
    zAltEntry = sqlite3_malloc(ncFile+30);
    if( zAltEntry==0 ){
      sqlite3OsDlClose(pVfs, handle);
      return SQLITE_NOMEM;
    }
    memcpy(zAltEntry, "sqlite3_", 8);
    for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
    iFile++;
    if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
    for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
      if( sqlite3Isalpha(c) ){
        zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
      }
    }
    memcpy(zAltEntry+iEntry, "_init", 6);
    zEntry = zAltEntry;
    xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
                     sqlite3OsDlSym(pVfs, handle, zEntry);
  }
  if( xInit==0 ){
    if( pzErrMsg ){
      nMsg += sqlite3Strlen30(zEntry);
      *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
      if( zErrmsg ){
        sqlite3_snprintf(nMsg, zErrmsg,
            "no entry point [%s] in shared library [%s]", zEntry, zFile);
        sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
      }

    }
    sqlite3OsDlClose(pVfs, handle);
    sqlite3_free(zAltEntry);
    return SQLITE_ERROR;
  }
  sqlite3_free(zAltEntry);
  if( xInit(db, &zErrmsg, &sqlite3Apis) ){
    if( pzErrMsg ){
      *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
    }
    sqlite3_free(zErrmsg);
    sqlite3OsDlClose(pVfs, handle);
    return SQLITE_ERROR;
  }

Changes to src/main.c.

491
492
493
494
495
496
497













498
499
500
501
502
503
504
....
2333
2334
2335
2336
2337
2338
2339

2340
2341
2342
2343
2344
2345
2346
    case SQLITE_CONFIG_SQLLOG: {
      typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
      sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
      sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
      break;
    }
#endif














    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
................................................................................
  db->magic = SQLITE_MAGIC_BUSY;
  db->aDb = db->aDbStatic;

  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  db->autoCommit = 1;
  db->nextAutovac = -1;

  db->nextPagesize = 0;
  db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
#if SQLITE_DEFAULT_FILE_FORMAT<4
                 | SQLITE_LegacyFileFmt
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
                 | SQLITE_LoadExtension







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
....
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
    case SQLITE_CONFIG_SQLLOG: {
      typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
      sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
      sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
      break;
    }
#endif

    case SQLITE_CONFIG_MMAP_SIZE: {
      sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64);
      sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64);
      if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
        mxMmap = SQLITE_MAX_MMAP_SIZE;
      }
      sqlite3GlobalConfig.mxMmap = mxMmap;
      if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
      if( szMmap>mxMmap) szMmap = mxMmap;
      sqlite3GlobalConfig.szMmap = szMmap;
      break;
    }

    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
................................................................................
  db->magic = SQLITE_MAGIC_BUSY;
  db->aDb = db->aDbStatic;

  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  db->autoCommit = 1;
  db->nextAutovac = -1;
  db->szMmap = sqlite3GlobalConfig.szMmap;
  db->nextPagesize = 0;
  db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
#if SQLITE_DEFAULT_FILE_FORMAT<4
                 | SQLITE_LegacyFileFmt
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
                 | SQLITE_LoadExtension

Changes to src/memjournal.c.

226
227
228
229
230
231
232
233


234
235
236
237
238
239
240
  0,                /* xCheckReservedLock */
  0,                /* xFileControl */
  0,                /* xSectorSize */
  0,                /* xDeviceCharacteristics */
  0,                /* xShmMap */
  0,                /* xShmLock */
  0,                /* xShmBarrier */
  0                 /* xShmUnlock */


};

/* 
** Open a journal file.
*/
void sqlite3MemJournalOpen(sqlite3_file *pJfd){
  MemJournal *p = (MemJournal *)pJfd;







|
>
>







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  0,                /* xCheckReservedLock */
  0,                /* xFileControl */
  0,                /* xSectorSize */
  0,                /* xDeviceCharacteristics */
  0,                /* xShmMap */
  0,                /* xShmLock */
  0,                /* xShmBarrier */
  0,                /* xShmUnmap */
  0,                /* xFetch */
  0                 /* xUnfetch */
};

/* 
** Open a journal file.
*/
void sqlite3MemJournalOpen(sqlite3_file *pJfd){
  MemJournal *p = (MemJournal *)pJfd;

Changes to src/os.c.

136
137
138
139
140
141
142




















143
144
145
146
147
148
149
  int pgsz,
  int bExtend,                    /* True to extend file if necessary */
  void volatile **pp              /* OUT: Pointer to mapping */
){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
}





















/*
** The next group of routines are convenience wrappers around the
** VFS methods.
*/
int sqlite3OsOpen(
  sqlite3_vfs *pVfs, 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  int pgsz,
  int bExtend,                    /* True to extend file if necessary */
  void volatile **pp              /* OUT: Pointer to mapping */
){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
}

#if SQLITE_MAX_MMAP_SIZE>0
/* The real implementation of xFetch and xUnfetch */
int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xFetch(id, iOff, iAmt, pp);
}
int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
  return id->pMethods->xUnfetch(id, iOff, p);
}
#else
/* No-op stubs to use when memory-mapped I/O is disabled */
int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
  *pp = 0;
  return SQLITE_OK;
}
int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
  return SQLITE_OK;
}
#endif

/*
** The next group of routines are convenience wrappers around the
** VFS methods.
*/
int sqlite3OsOpen(
  sqlite3_vfs *pVfs, 

Changes to src/os.h.

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
255
256
257
258
259
260
261


262
263
264
265
266
267
268
** Determine if we are dealing with WinRT, which provides only a subset of
** the full Win32 API.
*/
#if !defined(SQLITE_OS_WINRT)
# define SQLITE_OS_WINRT 0
#endif

/*
** When compiled for WinCE or WinRT, there is no concept of the current
** directory.
 */
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
# define SQLITE_CURDIR 1
#endif

/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
#ifndef SET_FULLSYNC
# define SET_FULLSYNC(x,y)
#endif

................................................................................
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
void sqlite3OsShmBarrier(sqlite3_file *id);
int sqlite3OsShmUnmap(sqlite3_file *id, int);




/* 
** Functions for accessing sqlite3_vfs methods 
*/
int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
int sqlite3OsDelete(sqlite3_vfs *, const char *, int);







<
<
<
<
<
<
<
<







 







>
>







95
96
97
98
99
100
101








102
103
104
105
106
107
108
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
** Determine if we are dealing with WinRT, which provides only a subset of
** the full Win32 API.
*/
#if !defined(SQLITE_OS_WINRT)
# define SQLITE_OS_WINRT 0
#endif









/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
#ifndef SET_FULLSYNC
# define SET_FULLSYNC(x,y)
#endif

................................................................................
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
void sqlite3OsShmBarrier(sqlite3_file *id);
int sqlite3OsShmUnmap(sqlite3_file *id, int);
int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
int sqlite3OsUnfetch(sqlite3_file *, i64, void *);


/* 
** Functions for accessing sqlite3_vfs methods 
*/
int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
int sqlite3OsDelete(sqlite3_vfs *, const char *, int);

Changes to src/os_unix.c.

221
222
223
224
225
226
227





228
229
230
231
232
233
234
...
245
246
247
248
249
250
251

252

253
254
255
256
257
258
259
...
269
270
271
272
273
274
275

276
277
278
279
280
281
282
...
302
303
304
305
306
307
308











309
310
311
312
313
314
315
...
433
434
435
436
437
438
439













440
441
442
443
444
445
446
...
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
....
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
....
1265
1266
1267
1268
1269
1270
1271












































1272
1273
1274
1275
1276
1277
1278
....
1796
1797
1798
1799
1800
1801
1802

1803
1804



1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
....
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847
1848
1849
1850
....
3077
3078
3079
3080
3081
3082
3083

















3084
3085
3086
3087
3088
3089
3090
....
3179
3180
3181
3182
3183
3184
3185

















3186
3187
3188
3189
3190
3191
3192
....
3463
3464
3465
3466
3467
3468
3469








3470
3471
3472
3473
3474
3475
3476
....
3551
3552
3553
3554
3555
3556
3557













3558
3559
3560
3561
3562
3563
3564
....
3618
3619
3620
3621
3622
3623
3624












3625
3626
3627
3628
3629
3630
3631
....
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
....
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
....
4420
4421
4422
4423
4424
4425
4426






































































































































































































































4427
4428
4429
4430
4431
4432
4433
....
4479
4480
4481
4482
4483
4484
4485
4486


4487
4488
4489
4490
4491
4492
4493
....
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
....
4747
4748
4749
4750
4751
4752
4753

4754
4755
4756
4757
4758
4759
4760
....
4891
4892
4893
4894
4895
4896
4897

4898
4899
4900
4901
4902
4903
4904
....
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
  unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */





#ifdef __QNXNTO__
  int sectorSize;                     /* Device sector size */
  int deviceCharacteristics;          /* Precomputed device characteristics */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
  int openFlags;                      /* The flags specified at open() */
#endif
................................................................................
  ** occur if a file is updated without also updating the transaction
  ** counter.  This test is made to avoid new problems similar to the
  ** one described by ticket #3584. 
  */
  unsigned char transCntrChng;   /* True if the transaction counter changed */
  unsigned char dbUpdate;        /* True if any part of database file changed */
  unsigned char inNormalWrite;   /* True if in a normal write operation */

#endif

#ifdef SQLITE_TEST
  /* In test mode, increase the size of this structure a bit so that 
  ** it is larger than the struct CrashFile defined in test6.c.
  */
  char aPadding[32];
#endif
};
................................................................................
#else
# define UNIXFILE_DIRSYNC    0x00
#endif
#define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
#define UNIXFILE_DELETE      0x20     /* Delete on close */
#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */


/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"

/*
................................................................................
*/
#if SQLITE_THREADSAFE
#define threadid pthread_self()
#else
#define threadid 0
#endif












/*
** Different Unix systems declare open() in different ways.  Same use
** open(const char*,int,mode_t).  Others use open(const char*,int,...).
** The difference is important when using a pointer to the function.
**
** The safest way to deal with the problem is to always use this wrapper
** which always has the same well-defined interface.
................................................................................

  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)

  { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)














}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.
................................................................................
  case ENOSYS:
    /* these should force the client to close the file and reconnect */
    
  default: 
    return sqliteIOErr;
  }
}



/******************************************************************************
****************** Begin Unique File ID Utility Used By VxWorks ***************
**
** On most versions of unix, we can get a unique ID for a file by concatenating
** the device number and the inode number.  But this does not work on VxWorks.
................................................................................
  /* This is a threadsafe build, but strerror_r() is not available. */
  zErr = "";
#else
  /* Non-threadsafe build, use strerror(). */
  zErr = strerror(iErrno);
#endif

  assert( errcode!=SQLITE_OK );
  if( zPath==0 ) zPath = "";
  sqlite3_log(errcode,
      "os_unix.c:%d: (%d) %s(%s) - %s",
      iLine, iErrno, zFunc, zPath, zErr
  );

  return errcode;
................................................................................
  }else{
    pInode->nRef++;
  }
  *ppInode = pInode;
  return SQLITE_OK;
}














































/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero.  The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
................................................................................
** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int unixUnlock(sqlite3_file *id, int eFileLock){

  return posixUnlock(id, eFileLock, 0);
}




/*
** This function performs the parts of the "close file" operation 
** common to all locking schemes. It closes the directory and file
** handles, if they are valid, and sets all fields of the unixFile
** structure to 0.
**
** It is *not* necessary to hold the mutex when this routine is called,
** even on VxWorks.  A mutex will be acquired on VxWorks by the
** vxworksReleaseFileId() routine.
*/
static int closeUnixFile(sqlite3_file *id){
  unixFile *pFile = (unixFile*)id;

  if( pFile->h>=0 ){
    robust_close(pFile, pFile->h, __LINE__);
    pFile->h = -1;
  }
#if OS_VXWORKS
  if( pFile->pId ){
    if( pFile->ctrlFlags & UNIXFILE_DELETE ){
................................................................................

/*
** Close a file.
*/
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile *)id;

  unixUnlock(id, NO_LOCK);
  unixEnterMutex();

  /* unixFile.pInode is always valid here. Otherwise, a different close
  ** routine (e.g. nolockClose()) would be called instead.
  */
  assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
................................................................................
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif


















  got = seekAndRead(pFile, offset, pBuf, amt);
  if( got==amt ){
    return SQLITE_OK;
  }else if( got<0 ){
    /* lastErrno set by seekAndRead */
    return SQLITE_IOERR_READ;
................................................................................
      SimulateIOErrorBenign(1);
      rc = seekAndRead(pFile, 24, oldCntr, 4);
      SimulateIOErrorBenign(0);
      if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
        pFile->transCntrChng = 1;  /* The transaction counter has changed */
      }
    }

















  }
#endif

  while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
    amt -= wrote;
    offset += wrote;
    pBuf = &((char*)pBuf)[wrote];
................................................................................
    ** when restoring a database using the backup API from a zero-length
    ** source.
    */
    if( pFile->inNormalWrite && nByte==0 ){
      pFile->transCntrChng = 1;
    }
#endif









    return SQLITE_OK;
  }
}

/*
** Determine the current size of a file in bytes
................................................................................
        int nWrite = seekAndWrite(pFile, iWrite, "", 1);
        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
        iWrite += nBlk;
      }
#endif
    }
  }














  return SQLITE_OK;
}

/*
** If *pArg is inititially negative then this is a query.  Set *pArg to
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
................................................................................
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
      if( zTFile ){
        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;












    }
#ifdef SQLITE_DEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
................................................................................
  assert( unixMutexHeld() );
  if( p && p->nRef==0 ){
    int i;
    assert( p->pInode==pFd->pInode );
    sqlite3_mutex_free(p->mutex);
    for(i=0; i<p->nRegion; i++){
      if( p->h>=0 ){
        munmap(p->apRegion[i], p->szRegion);
      }else{
        sqlite3_free(p->apRegion[i]);
      }
    }
    sqlite3_free(p->apRegion);
    if( p->h>=0 ){
      robust_close(pFd, p->h, __LINE__);
................................................................................
      rc = SQLITE_IOERR_NOMEM;
      goto shmpage_out;
    }
    pShmNode->apRegion = apNew;
    while(pShmNode->nRegion<=iRegion){
      void *pMem;
      if( pShmNode->h>=0 ){
        pMem = mmap(0, szRegion,
            pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
        );
        if( pMem==MAP_FAILED ){
          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
          goto shmpage_out;
        }
................................................................................

#else
# define unixShmMap     0
# define unixShmLock    0
# define unixShmBarrier 0
# define unixShmUnmap   0
#endif /* #ifndef SQLITE_OMIT_WAL */







































































































































































































































/*
** Here ends the implementation of all sqlite3_file methods.
**
********************** End sqlite3_file Methods *******************************
******************************************************************************/

................................................................................
   CKLOCK,                     /* xCheckReservedLock */                      \
   unixFileControl,            /* xFileControl */                            \
   unixSectorSize,             /* xSectorSize */                             \
   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
   unixShmMap,                 /* xShmMap */                                 \
   unixShmLock,                /* xShmLock */                                \
   unixShmBarrier,             /* xShmBarrier */                             \
   unixShmUnmap                /* xShmUnmap */                               \


};                                                                           \
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  return &METHOD;                                                            \
}                                                                            \
static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
    = FINDER##Impl;
................................................................................
** Here are all of the sqlite3_io_methods objects for each of the
** locking strategies.  Functions that return pointers to these methods
** are also created.
*/
IOMETHODS(
  posixIoFinder,            /* Finder function name */
  posixIoMethods,           /* sqlite3_io_methods object name */
  2,                        /* shared memory is enabled */
  unixClose,                /* xClose method */
  unixLock,                 /* xLock method */
  unixUnlock,               /* xUnlock method */
  unixCheckReservedLock     /* xCheckReservedLock method */
)
IOMETHODS(
  nolockIoFinder,           /* Finder function name */
................................................................................
  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
  pNew->ctrlFlags = (u8)ctrlFlags;

  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pNew->ctrlFlags |= UNIXFILE_PSOW;
  }
  if( strcmp(pVfs->zName,"unix-excl")==0 ){
    pNew->ctrlFlags |= UNIXFILE_EXCL;
  }
................................................................................
  if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
#endif
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;
    OpenCounter(+1);

  }
  return rc;
}

/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
................................................................................
    UNIXVFS("unix-proxy",    proxyIoFinder ),
#endif
  };
  unsigned int i;          /* Loop counter */

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==21 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  return SQLITE_OK; 
}







>
>
>
>
>







 







>

>







 







>







 







>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







<







 







<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>


>
>
>













>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
>
>







 







|







 







>







 







>







 







|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
...
794
795
796
797
798
799
800

801
802
803
804
805
806
807
....
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
....
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
....
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
....
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
....
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
....
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
....
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
....
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
....
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
....
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
....
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
....
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
....
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
....
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
....
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
....
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
....
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
  unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
  int nFetchOut;                      /* Number of outstanding xFetch refs */
  sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
  sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
  sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
  void *pMapRegion;                   /* Memory mapped region */
#ifdef __QNXNTO__
  int sectorSize;                     /* Device sector size */
  int deviceCharacteristics;          /* Precomputed device characteristics */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
  int openFlags;                      /* The flags specified at open() */
#endif
................................................................................
  ** occur if a file is updated without also updating the transaction
  ** counter.  This test is made to avoid new problems similar to the
  ** one described by ticket #3584. 
  */
  unsigned char transCntrChng;   /* True if the transaction counter changed */
  unsigned char dbUpdate;        /* True if any part of database file changed */
  unsigned char inNormalWrite;   /* True if in a normal write operation */

#endif

#ifdef SQLITE_TEST
  /* In test mode, increase the size of this structure a bit so that 
  ** it is larger than the struct CrashFile defined in test6.c.
  */
  char aPadding[32];
#endif
};
................................................................................
#else
# define UNIXFILE_DIRSYNC    0x00
#endif
#define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
#define UNIXFILE_DELETE      0x20     /* Delete on close */
#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
#define UNIXFILE_WARNED    0x0100     /* verifyDbFile() warnings have been issued */

/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"

/*
................................................................................
*/
#if SQLITE_THREADSAFE
#define threadid pthread_self()
#else
#define threadid 0
#endif

/*
** HAVE_MREMAP defaults to true on Linux and false everywhere else.
*/
#if !defined(HAVE_MREMAP)
# if defined(__linux__) && defined(_GNU_SOURCE)
#  define HAVE_MREMAP 1
# else
#  define HAVE_MREMAP 0
# endif
#endif

/*
** Different Unix systems declare open() in different ways.  Same use
** open(const char*,int,mode_t).  Others use open(const char*,int,...).
** The difference is important when using a pointer to the function.
**
** The safest way to deal with the problem is to always use this wrapper
** which always has the same well-defined interface.
................................................................................

  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)

  { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)

  { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)

  { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)

#if HAVE_MREMAP
  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
#else
  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
#endif
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)

}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.
................................................................................
  case ENOSYS:
    /* these should force the client to close the file and reconnect */
    
  default: 
    return sqliteIOErr;
  }
}



/******************************************************************************
****************** Begin Unique File ID Utility Used By VxWorks ***************
**
** On most versions of unix, we can get a unique ID for a file by concatenating
** the device number and the inode number.  But this does not work on VxWorks.
................................................................................
  /* This is a threadsafe build, but strerror_r() is not available. */
  zErr = "";
#else
  /* Non-threadsafe build, use strerror(). */
  zErr = strerror(iErrno);
#endif


  if( zPath==0 ) zPath = "";
  sqlite3_log(errcode,
      "os_unix.c:%d: (%d) %s(%s) - %s",
      iLine, iErrno, zFunc, zPath, zErr
  );

  return errcode;
................................................................................
  }else{
    pInode->nRef++;
  }
  *ppInode = pInode;
  return SQLITE_OK;
}


/*
** Check a unixFile that is a database.  Verify the following:
**
** (1) There is exactly one hard link on the file
** (2) The file is not a symbolic link
** (3) The file has not been renamed or unlinked
**
** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
*/
static void verifyDbFile(unixFile *pFile){
  struct stat buf;
  int rc;
  if( pFile->ctrlFlags & UNIXFILE_WARNED ){
    /* One or more of the following warnings have already been issued.  Do not
    ** repeat them so as not to clutter the error log */
    return;
  }
  rc = osFstat(pFile->h, &buf);
  if( rc!=0 ){
    sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
    pFile->ctrlFlags |= UNIXFILE_WARNED;
    return;
  }
  if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
    sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
    pFile->ctrlFlags |= UNIXFILE_WARNED;
    return;
  }
  if( buf.st_nlink>1 ){
    sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
    pFile->ctrlFlags |= UNIXFILE_WARNED;
    return;
  }
  if( pFile->pInode!=0
   && ((rc = osStat(pFile->zPath, &buf))!=0
       || buf.st_ino!=pFile->pInode->fileId.ino)
  ){
    sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
    pFile->ctrlFlags |= UNIXFILE_WARNED;
    return;
  }
}


/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero.  The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
................................................................................
** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int unixUnlock(sqlite3_file *id, int eFileLock){
  assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
  return posixUnlock(id, eFileLock, 0);
}

static int unixMapfile(unixFile *pFd, i64 nByte);
static void unixUnmapfile(unixFile *pFd);

/*
** This function performs the parts of the "close file" operation 
** common to all locking schemes. It closes the directory and file
** handles, if they are valid, and sets all fields of the unixFile
** structure to 0.
**
** It is *not* necessary to hold the mutex when this routine is called,
** even on VxWorks.  A mutex will be acquired on VxWorks by the
** vxworksReleaseFileId() routine.
*/
static int closeUnixFile(sqlite3_file *id){
  unixFile *pFile = (unixFile*)id;
  unixUnmapfile(pFile);
  if( pFile->h>=0 ){
    robust_close(pFile, pFile->h, __LINE__);
    pFile->h = -1;
  }
#if OS_VXWORKS
  if( pFile->pId ){
    if( pFile->ctrlFlags & UNIXFILE_DELETE ){
................................................................................

/*
** Close a file.
*/
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile *)id;
  verifyDbFile(pFile);
  unixUnlock(id, NO_LOCK);
  unixEnterMutex();

  /* unixFile.pInode is always valid here. Otherwise, a different close
  ** routine (e.g. nolockClose()) would be called instead.
  */
  assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
................................................................................
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif

#if SQLITE_MAX_MMAP_SIZE>0
  /* Deal with as much of this read request as possible by transfering
  ** data from the memory mapping using memcpy().  */
  if( offset<pFile->mmapSize ){
    if( offset+amt <= pFile->mmapSize ){
      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
      return SQLITE_OK;
    }else{
      int nCopy = pFile->mmapSize - offset;
      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

  got = seekAndRead(pFile, offset, pBuf, amt);
  if( got==amt ){
    return SQLITE_OK;
  }else if( got<0 ){
    /* lastErrno set by seekAndRead */
    return SQLITE_IOERR_READ;
................................................................................
      SimulateIOErrorBenign(1);
      rc = seekAndRead(pFile, 24, oldCntr, 4);
      SimulateIOErrorBenign(0);
      if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
        pFile->transCntrChng = 1;  /* The transaction counter has changed */
      }
    }
  }
#endif

#if SQLITE_MAX_MMAP_SIZE>0
  /* Deal with as much of this write request as possible by transfering
  ** data from the memory mapping using memcpy().  */
  if( offset<pFile->mmapSize ){
    if( offset+amt <= pFile->mmapSize ){
      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
      return SQLITE_OK;
    }else{
      int nCopy = pFile->mmapSize - offset;
      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

  while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
    amt -= wrote;
    offset += wrote;
    pBuf = &((char*)pBuf)[wrote];
................................................................................
    ** when restoring a database using the backup API from a zero-length
    ** source.
    */
    if( pFile->inNormalWrite && nByte==0 ){
      pFile->transCntrChng = 1;
    }
#endif

    /* If the file was just truncated to a size smaller than the currently
    ** mapped region, reduce the effective mapping size as well. SQLite will
    ** use read() and write() to access data beyond this point from now on.  
    */
    if( nByte<pFile->mmapSize ){
      pFile->mmapSize = nByte;
    }

    return SQLITE_OK;
  }
}

/*
** Determine the current size of a file in bytes
................................................................................
        int nWrite = seekAndWrite(pFile, iWrite, "", 1);
        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
        iWrite += nBlk;
      }
#endif
    }
  }

  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
    int rc;
    if( pFile->szChunk<=0 ){
      if( robust_ftruncate(pFile->h, nByte) ){
        pFile->lastErrno = errno;
        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
      }
    }

    rc = unixMapfile(pFile, nByte);
    return rc;
  }

  return SQLITE_OK;
}

/*
** If *pArg is inititially negative then this is a query.  Set *pArg to
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
................................................................................
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
      if( zTFile ){
        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_MMAP_SIZE: {
      i64 newLimit = *(i64*)pArg;
      if( newLimit>sqlite3GlobalConfig.mxMmap ){
        newLimit = sqlite3GlobalConfig.mxMmap;
      }
      *(i64*)pArg = pFile->mmapSizeMax;
      if( newLimit>=0 ){
        pFile->mmapSizeMax = newLimit;
        if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
      }
      return SQLITE_OK;
    }
#ifdef SQLITE_DEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
................................................................................
  assert( unixMutexHeld() );
  if( p && p->nRef==0 ){
    int i;
    assert( p->pInode==pFd->pInode );
    sqlite3_mutex_free(p->mutex);
    for(i=0; i<p->nRegion; i++){
      if( p->h>=0 ){
        osMunmap(p->apRegion[i], p->szRegion);
      }else{
        sqlite3_free(p->apRegion[i]);
      }
    }
    sqlite3_free(p->apRegion);
    if( p->h>=0 ){
      robust_close(pFd, p->h, __LINE__);
................................................................................
      rc = SQLITE_IOERR_NOMEM;
      goto shmpage_out;
    }
    pShmNode->apRegion = apNew;
    while(pShmNode->nRegion<=iRegion){
      void *pMem;
      if( pShmNode->h>=0 ){
        pMem = osMmap(0, szRegion,
            pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
        );
        if( pMem==MAP_FAILED ){
          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
          goto shmpage_out;
        }
................................................................................

#else
# define unixShmMap     0
# define unixShmLock    0
# define unixShmBarrier 0
# define unixShmUnmap   0
#endif /* #ifndef SQLITE_OMIT_WAL */

/*
** If it is currently memory mapped, unmap file pFd.
*/
static void unixUnmapfile(unixFile *pFd){
  assert( pFd->nFetchOut==0 );
#if SQLITE_MAX_MMAP_SIZE>0
  if( pFd->pMapRegion ){
    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
    pFd->pMapRegion = 0;
    pFd->mmapSize = 0;
    pFd->mmapSizeActual = 0;
  }
#endif
}

#if SQLITE_MAX_MMAP_SIZE>0
/*
** Return the system page size.
*/
static int unixGetPagesize(void){
#if HAVE_MREMAP
  return 512;
#elif defined(_BSD_SOURCE)
  return getpagesize();
#else
  return (int)sysconf(_SC_PAGESIZE);
#endif
}
#endif /* SQLITE_MAX_MMAP_SIZE>0 */

#if SQLITE_MAX_MMAP_SIZE>0
/*
** Attempt to set the size of the memory mapping maintained by file 
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
**
** If successful, this function sets the following variables:
**
**       unixFile.pMapRegion
**       unixFile.mmapSize
**       unixFile.mmapSizeActual
**
** If unsuccessful, an error message is logged via sqlite3_log() and
** the three variables above are zeroed. In this case SQLite should
** continue accessing the database using the xRead() and xWrite()
** methods.
*/
static void unixRemapfile(
  unixFile *pFd,                  /* File descriptor object */
  i64 nNew                        /* Required mapping size */
){
  const char *zErr = "mmap";
  int h = pFd->h;                      /* File descriptor open on db file */
  u8 *pOrig = (u8 *)pFd->pMapRegion;   /* Pointer to current file mapping */
  i64 nOrig = pFd->mmapSizeActual;     /* Size of pOrig region in bytes */
  u8 *pNew = 0;                        /* Location of new mapping */
  int flags = PROT_READ;               /* Flags to pass to mmap() */

  assert( pFd->nFetchOut==0 );
  assert( nNew>pFd->mmapSize );
  assert( nNew<=pFd->mmapSizeMax );
  assert( nNew>0 );
  assert( pFd->mmapSizeActual>=pFd->mmapSize );
  assert( MAP_FAILED!=0 );

  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;

  if( pOrig ){
    const int szSyspage = unixGetPagesize();
    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
    u8 *pReq = &pOrig[nReuse];

    /* Unmap any pages of the existing mapping that cannot be reused. */
    if( nReuse!=nOrig ){
      osMunmap(pReq, nOrig-nReuse);
    }

#if HAVE_MREMAP
    pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
    zErr = "mremap";
#else
    pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
    if( pNew!=MAP_FAILED ){
      if( pNew!=pReq ){
        osMunmap(pNew, nNew - nReuse);
        pNew = 0;
      }else{
        pNew = pOrig;
      }
    }
#endif

    /* The attempt to extend the existing mapping failed. Free it. */
    if( pNew==MAP_FAILED || pNew==0 ){
      osMunmap(pOrig, nReuse);
    }
  }

  /* If pNew is still NULL, try to create an entirely new mapping. */
  if( pNew==0 ){
    pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
  }

  if( pNew==MAP_FAILED ){
    pNew = 0;
    nNew = 0;
    unixLogError(SQLITE_OK, zErr, pFd->zPath);

    /* If the mmap() above failed, assume that all subsequent mmap() calls
    ** will probably fail too. Fall back to using xRead/xWrite exclusively
    ** in this case.  */
    pFd->mmapSizeMax = 0;
  }
  pFd->pMapRegion = (void *)pNew;
  pFd->mmapSize = pFd->mmapSizeActual = nNew;
}
#endif

/*
** Memory map or remap the file opened by file-descriptor pFd (if the file
** is already mapped, the existing mapping is replaced by the new). Or, if 
** there already exists a mapping for this file, and there are still 
** outstanding xFetch() references to it, this function is a no-op.
**
** If parameter nByte is non-negative, then it is the requested size of 
** the mapping to create. Otherwise, if nByte is less than zero, then the 
** requested size is the size of the file on disk. The actual size of the
** created mapping is either the requested size or the value configured 
** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
**
** SQLITE_OK is returned if no error occurs (even if the mapping is not
** recreated as a result of outstanding references) or an SQLite error
** code otherwise.
*/
static int unixMapfile(unixFile *pFd, i64 nByte){
#if SQLITE_MAX_MMAP_SIZE>0
  i64 nMap = nByte;
  int rc;

  assert( nMap>=0 || pFd->nFetchOut==0 );
  if( pFd->nFetchOut>0 ) return SQLITE_OK;

  if( nMap<0 ){
    struct stat statbuf;          /* Low-level file information */
    rc = osFstat(pFd->h, &statbuf);
    if( rc!=SQLITE_OK ){
      return SQLITE_IOERR_FSTAT;
    }
    nMap = statbuf.st_size;
  }
  if( nMap>pFd->mmapSizeMax ){
    nMap = pFd->mmapSizeMax;
  }

  if( nMap!=pFd->mmapSize ){
    if( nMap>0 ){
      unixRemapfile(pFd, nMap);
    }else{
      unixUnmapfile(pFd);
    }
  }
#endif

  return SQLITE_OK;
}

/*
** If possible, return a pointer to a mapping of file fd starting at offset
** iOff. The mapping must be valid for at least nAmt bytes.
**
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
** If this function does return a pointer, the caller must eventually 
** release the reference by calling unixUnfetch().
*/
static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
#endif
  *pp = 0;

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFd->mmapSizeMax>0 ){
    if( pFd->pMapRegion==0 ){
      int rc = unixMapfile(pFd, -1);
      if( rc!=SQLITE_OK ) return rc;
    }
    if( pFd->mmapSize >= iOff+nAmt ){
      *pp = &((u8 *)pFd->pMapRegion)[iOff];
      pFd->nFetchOut++;
    }
  }
#endif
  return SQLITE_OK;
}

/*
** If the third argument is non-NULL, then this function releases a 
** reference obtained by an earlier call to unixFetch(). The second
** argument passed to this function must be the same as the corresponding
** argument that was passed to the unixFetch() invocation. 
**
** Or, if the third argument is NULL, then this function is being called 
** to inform the VFS layer that, according to POSIX, any existing mapping 
** may now be invalid and should be unmapped.
*/
static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
  UNUSED_PARAMETER(iOff);

  /* If p==0 (unmap the entire file) then there must be no outstanding 
  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
  ** then there must be at least one outstanding.  */
  assert( (p==0)==(pFd->nFetchOut==0) );

  /* If p!=0, it must match the iOff value. */
  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );

  if( p ){
    pFd->nFetchOut--;
  }else{
    unixUnmapfile(pFd);
  }

  assert( pFd->nFetchOut>=0 );
  return SQLITE_OK;
}

/*
** Here ends the implementation of all sqlite3_file methods.
**
********************** End sqlite3_file Methods *******************************
******************************************************************************/

................................................................................
   CKLOCK,                     /* xCheckReservedLock */                      \
   unixFileControl,            /* xFileControl */                            \
   unixSectorSize,             /* xSectorSize */                             \
   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
   unixShmMap,                 /* xShmMap */                                 \
   unixShmLock,                /* xShmLock */                                \
   unixShmBarrier,             /* xShmBarrier */                             \
   unixShmUnmap,               /* xShmUnmap */                               \
   unixFetch,                  /* xFetch */                                  \
   unixUnfetch,                /* xUnfetch */                                \
};                                                                           \
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  return &METHOD;                                                            \
}                                                                            \
static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
    = FINDER##Impl;
................................................................................
** Here are all of the sqlite3_io_methods objects for each of the
** locking strategies.  Functions that return pointers to these methods
** are also created.
*/
IOMETHODS(
  posixIoFinder,            /* Finder function name */
  posixIoMethods,           /* sqlite3_io_methods object name */
  3,                        /* shared memory and mmap are enabled */
  unixClose,                /* xClose method */
  unixLock,                 /* xLock method */
  unixUnlock,               /* xUnlock method */
  unixCheckReservedLock     /* xCheckReservedLock method */
)
IOMETHODS(
  nolockIoFinder,           /* Finder function name */
................................................................................
  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
  pNew->ctrlFlags = (u8)ctrlFlags;
  pNew->mmapSizeMax = sqlite3GlobalConfig.mxMmap;
  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pNew->ctrlFlags |= UNIXFILE_PSOW;
  }
  if( strcmp(pVfs->zName,"unix-excl")==0 ){
    pNew->ctrlFlags |= UNIXFILE_EXCL;
  }
................................................................................
  if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
#endif
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;
    OpenCounter(+1);
    verifyDbFile(pNew);
  }
  return rc;
}

/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
................................................................................
    UNIXVFS("unix-proxy",    proxyIoFinder ),
#endif
  };
  unsigned int i;          /* Loop counter */

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==24 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  return SQLITE_OK; 
}

Changes to src/os_win.c.

146
147
148
149
150
151
152








153
154
155
156
157

158
159
160
161
162
163
164
....
2057
2058
2059
2060
2061
2062
2063





2064
2065
2066
2067
2068
2069
2070
....
2078
2079
2080
2081
2082
2083
2084






2085
2086
2087
2088
2089
2090
2091
....
2126
2127
2128
2129
2130
2131
2132

2133
2134

















2135
2136
2137
2138
2139
2140
2141
....
2177
2178
2179
2180
2181
2182
2183

















2184
2185
2186
2187
2188
2189
2190
....
2245
2246
2247
2248
2249
2250
2251

2252
2253
2254
2255
2256
2257
2258
....
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272

2273
2274
2275










2276
2277
2278
2279
2280
2281
2282
....
2777
2778
2779
2780
2781
2782
2783











2784
2785
2786
2787
2788
2789
2790
....
3446
3447
3448
3449
3450
3451
3452
3453
3454


























































































































































































3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
....
3474
3475
3476
3477
3478
3479
3480
3481


3482
3483
3484
3485
3486
3487
3488
....
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
....
3863
3864
3865
3866
3867
3868
3869



3870
3871
3872
3873
3874







3875
3876
3877
3878
3879
3880
3881
....
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
#if SQLITE_OS_WINCE
  LPWSTR zDeleteOnClose;  /* Name of file to delete when closing */
  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
  HANDLE hShared;         /* Shared memory segment used for locking */
  winceLock local;        /* Locks obtained by this instance of winFile */
  winceLock *shared;      /* Global shared lock memory for the file  */
#endif








};

/*
** Allowed values for winFile.ctrlFlags
*/

#define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
#define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */

/*
 * The size of the buffer used by sqlite3_win32_write_debug().
 */
#ifndef SQLITE_WIN32_DBG_BUF_SIZE
................................................................................
    return 1;
  }

  return 0;
#endif
}






/*
** Close a file.
**
** It is reported that an attempt to close a handle might sometimes
** fail.  This is a very unreasonable result, but Windows is notorious
** for being unreasonable so I do not doubt that it might happen.  If
** the close fails, we pause for 100 milliseconds and try again.  As
................................................................................

  assert( id!=0 );
#ifndef SQLITE_OMIT_WAL
  assert( pFile->pShm==0 );
#endif
  OSTRACE(("CLOSE %d\n", pFile->h));
  assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );






  do{
    rc = osCloseHandle(pFile->h);
    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
#if SQLITE_OS_WINCE
#define WINCE_DELETION_ATTEMPTS 3
  winceDestroyLock(pFile);
................................................................................
  OVERLAPPED overlapped;          /* The offset for ReadFile. */
#endif
  winFile *pFile = (winFile*)id;  /* file handle */
  DWORD nRead;                    /* Number of bytes actually read from file */
  int nRetry = 0;                 /* Number of retrys */

  assert( id!=0 );

  SimulateIOError(return SQLITE_IOERR_READ);
  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));


















#if SQLITE_OS_WINCE
  if( seekWinFile(pFile, offset) ){
    return SQLITE_FULL;
  }
  while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
#else
................................................................................

  assert( amt>0 );
  assert( pFile );
  SimulateIOError(return SQLITE_IOERR_WRITE);
  SimulateDiskfullError(return SQLITE_FULL);

  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));


















#if SQLITE_OS_WINCE
  rc = seekWinFile(pFile, offset);
  if( rc==0 ){
#else
  {
#endif
................................................................................

/*
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
  winFile *pFile = (winFile*)id;  /* File handle object */
  int rc = SQLITE_OK;             /* Return code for this function */


  assert( pFile );

  OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
  SimulateIOError(return SQLITE_IOERR_TRUNCATE);

  /* If the user has configured a chunk-size for this file, truncate the
................................................................................
  if( pFile->szChunk>0 ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }

  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( seekWinFile(pFile, nByte) ){
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
             "winTruncate1", pFile->zPath);
  }else if( 0==osSetEndOfFile(pFile->h) ){
    pFile->lastErrno = osGetLastError();

    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
             "winTruncate2", pFile->zPath);
  }











  OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
  return rc;
}

#ifdef SQLITE_TEST
/*
................................................................................
      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
      if( zTFile ){
        getTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;
    }











  }
  return SQLITE_NOTFOUND;
}

/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
................................................................................

#else
# define winShmMap     0
# define winShmLock    0
# define winShmBarrier 0
# define winShmUnmap   0
#endif /* #ifndef SQLITE_OMIT_WAL */

/*


























































































































































































** Here ends the implementation of all sqlite3_file methods.
**
********************** End sqlite3_file Methods *******************************
******************************************************************************/

/*
** This vector defines all the methods that can operate on an
** sqlite3_file for win32.
*/
static const sqlite3_io_methods winIoMethod = {
  2,                              /* iVersion */
  winClose,                       /* xClose */
  winRead,                        /* xRead */
  winWrite,                       /* xWrite */
  winTruncate,                    /* xTruncate */
  winSync,                        /* xSync */
  winFileSize,                    /* xFileSize */
  winLock,                        /* xLock */
................................................................................
  winCheckReservedLock,           /* xCheckReservedLock */
  winFileControl,                 /* xFileControl */
  winSectorSize,                  /* xSectorSize */
  winDeviceCharacteristics,       /* xDeviceCharacteristics */
  winShmMap,                      /* xShmMap */
  winShmLock,                     /* xShmLock */
  winShmBarrier,                  /* xShmBarrier */
  winShmUnmap                     /* xShmUnmap */


};

/****************************************************************************
**************************** sqlite3_vfs methods ****************************
**
** This division contains the implementation of methods on the
** sqlite3_vfs object.
................................................................................
#if !defined(NDEBUG) || SQLITE_OS_WINCE
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
#endif

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
#ifndef NDEBUG
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
#endif
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);

#ifndef NDEBUG
  int isOpenJournal = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL 
     || eType==SQLITE_OPEN_MAIN_JOURNAL 
     || eType==SQLITE_OPEN_WAL
................................................................................
  {
    sqlite3_free(zConverted);
  }

  pFile->pMethod = &winIoMethod;
  pFile->pVfs = pVfs;
  pFile->h = h;



  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pFile->ctrlFlags |= WINFILE_PSOW;
  }
  pFile->lastErrno = NO_ERROR;
  pFile->zPath = zName;








  OpenCounter(+1);
  return rc;
}

/*
** Delete the named file.
................................................................................
    winNextSystemCall,   /* xNextSystemCall */
  };

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==74 );

#ifndef SQLITE_OMIT_WAL
  /* get memory map allocation granularity */
  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
#if SQLITE_OS_WINRT
  osGetNativeSystemInfo(&winSysInfo);
#else
  osGetSystemInfo(&winSysInfo);
#endif
  assert(winSysInfo.dwAllocationGranularity > 0);
#endif

  sqlite3_vfs_register(&winVfs, 1);
  return SQLITE_OK; 
}

int sqlite3_os_end(void){ 
#if SQLITE_OS_WINRT







>
>
>
>
>
>
>
>





>







 







>
>
>
>
>







 







>
>
>
>
>
>







 







>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







|
|
|
>

|

>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>







 









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|







 







|
>
>







 







<

<







 







>
>
>





>
>
>
>
>
>
>







 







<







|
|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
....
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
....
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
....
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
....
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
....
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
....
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
....
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
....
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
....
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
....
3916
3917
3918
3919
3920
3921
3922

3923

3924
3925
3926
3927
3928
3929
3930
....
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
....
4770
4771
4772
4773
4774
4775
4776

4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
#if SQLITE_OS_WINCE
  LPWSTR zDeleteOnClose;  /* Name of file to delete when closing */
  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
  HANDLE hShared;         /* Shared memory segment used for locking */
  winceLock local;        /* Locks obtained by this instance of winFile */
  winceLock *shared;      /* Global shared lock memory for the file  */
#endif
#if SQLITE_MAX_MMAP_SIZE>0
  int nFetchOut;                /* Number of outstanding xFetch references */
  HANDLE hMap;                  /* Handle for accessing memory mapping */
  void *pMapRegion;             /* Area memory mapped */
  sqlite3_int64 mmapSize;       /* Usable size of mapped region */
  sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
  sqlite3_int64 mmapSizeMax;    /* Configured FCNTL_MMAP_SIZE value */
#endif
};

/*
** Allowed values for winFile.ctrlFlags
*/
#define WINFILE_RDONLY          0x02   /* Connection is read only */
#define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
#define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */

/*
 * The size of the buffer used by sqlite3_win32_write_debug().
 */
#ifndef SQLITE_WIN32_DBG_BUF_SIZE
................................................................................
    return 1;
  }

  return 0;
#endif
}

#if SQLITE_MAX_MMAP_SIZE>0
/* Forward references to VFS methods */
static int winUnmapfile(winFile*);
#endif

/*
** Close a file.
**
** It is reported that an attempt to close a handle might sometimes
** fail.  This is a very unreasonable result, but Windows is notorious
** for being unreasonable so I do not doubt that it might happen.  If
** the close fails, we pause for 100 milliseconds and try again.  As
................................................................................

  assert( id!=0 );
#ifndef SQLITE_OMIT_WAL
  assert( pFile->pShm==0 );
#endif
  OSTRACE(("CLOSE %d\n", pFile->h));
  assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );

#if SQLITE_MAX_MMAP_SIZE>0
  rc = winUnmapfile(pFile);
  if( rc!=SQLITE_OK ) return rc;
#endif

  do{
    rc = osCloseHandle(pFile->h);
    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
#if SQLITE_OS_WINCE
#define WINCE_DELETION_ATTEMPTS 3
  winceDestroyLock(pFile);
................................................................................
  OVERLAPPED overlapped;          /* The offset for ReadFile. */
#endif
  winFile *pFile = (winFile*)id;  /* file handle */
  DWORD nRead;                    /* Number of bytes actually read from file */
  int nRetry = 0;                 /* Number of retrys */

  assert( id!=0 );
  assert( amt>0 );
  SimulateIOError(return SQLITE_IOERR_READ);
  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));

#if SQLITE_MAX_MMAP_SIZE>0
  /* Deal with as much of this read request as possible by transfering
  ** data from the memory mapping using memcpy().  */
  if( offset<pFile->mmapSize ){
    if( offset+amt <= pFile->mmapSize ){
      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
      return SQLITE_OK;
    }else{
      int nCopy = (int)(pFile->mmapSize - offset);
      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE
  if( seekWinFile(pFile, offset) ){
    return SQLITE_FULL;
  }
  while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
#else
................................................................................

  assert( amt>0 );
  assert( pFile );
  SimulateIOError(return SQLITE_IOERR_WRITE);
  SimulateDiskfullError(return SQLITE_FULL);

  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));

#if SQLITE_MAX_MMAP_SIZE>0
  /* Deal with as much of this write request as possible by transfering
  ** data from the memory mapping using memcpy().  */
  if( offset<pFile->mmapSize ){
    if( offset+amt <= pFile->mmapSize ){
      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
      return SQLITE_OK;
    }else{
      int nCopy = (int)(pFile->mmapSize - offset);
      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE
  rc = seekWinFile(pFile, offset);
  if( rc==0 ){
#else
  {
#endif
................................................................................

/*
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
  winFile *pFile = (winFile*)id;  /* File handle object */
  int rc = SQLITE_OK;             /* Return code for this function */
  DWORD lastErrno;

  assert( pFile );

  OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
  SimulateIOError(return SQLITE_IOERR_TRUNCATE);

  /* If the user has configured a chunk-size for this file, truncate the
................................................................................
  if( pFile->szChunk>0 ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }

  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( seekWinFile(pFile, nByte) ){
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate1", pFile->zPath);
  }else if( 0==osSetEndOfFile(pFile->h) &&
            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
    pFile->lastErrno = lastErrno;
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate2", pFile->zPath);
  }

#if SQLITE_MAX_MMAP_SIZE>0
  /* If the file was truncated to a size smaller than the currently
  ** mapped region, reduce the effective mapping size as well. SQLite will
  ** use read() and write() to access data beyond this point from now on.
  */
  if( pFile->pMapRegion && nByte<pFile->mmapSize ){
    pFile->mmapSize = nByte;
  }
#endif

  OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
  return rc;
}

#ifdef SQLITE_TEST
/*
................................................................................
      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
      if( zTFile ){
        getTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;
    }
#if SQLITE_MAX_MMAP_SIZE>0
    case SQLITE_FCNTL_MMAP_SIZE: {
      i64 newLimit = *(i64*)pArg;
      if( newLimit>sqlite3GlobalConfig.mxMmap ){
        newLimit = sqlite3GlobalConfig.mxMmap;
      }
      *(i64*)pArg = pFile->mmapSizeMax;
      if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
      return SQLITE_OK;
    }
#endif
  }
  return SQLITE_NOTFOUND;
}

/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
................................................................................

#else
# define winShmMap     0
# define winShmLock    0
# define winShmBarrier 0
# define winShmUnmap   0
#endif /* #ifndef SQLITE_OMIT_WAL */

/*
** Cleans up the mapped region of the specified file, if any.
*/
#if SQLITE_MAX_MMAP_SIZE>0
static int winUnmapfile(winFile *pFile){
  assert( pFile!=0 );
  if( pFile->pMapRegion ){
    if( !osUnmapViewOfFile(pFile->pMapRegion) ){
      pFile->lastErrno = osGetLastError();
      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
                         "winUnmap1", pFile->zPath);
    }
    pFile->pMapRegion = 0;
    pFile->mmapSize = 0;
    pFile->mmapSizeActual = 0;
  }
  if( pFile->hMap!=NULL ){
    if( !osCloseHandle(pFile->hMap) ){
      pFile->lastErrno = osGetLastError();
      return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
                         "winUnmap2", pFile->zPath);
    }
    pFile->hMap = NULL;
  }
  return SQLITE_OK;
}

/*
** Memory map or remap the file opened by file-descriptor pFd (if the file
** is already mapped, the existing mapping is replaced by the new). Or, if 
** there already exists a mapping for this file, and there are still 
** outstanding xFetch() references to it, this function is a no-op.
**
** If parameter nByte is non-negative, then it is the requested size of 
** the mapping to create. Otherwise, if nByte is less than zero, then the 
** requested size is the size of the file on disk. The actual size of the
** created mapping is either the requested size or the value configured 
** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
**
** SQLITE_OK is returned if no error occurs (even if the mapping is not
** recreated as a result of outstanding references) or an SQLite error
** code otherwise.
*/
static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
  sqlite3_int64 nMap = nByte;
  int rc;

  assert( nMap>=0 || pFd->nFetchOut==0 );
  if( pFd->nFetchOut>0 ) return SQLITE_OK;

  if( nMap<0 ){
    rc = winFileSize((sqlite3_file*)pFd, &nMap);
    if( rc ){
      return SQLITE_IOERR_FSTAT;
    }
  }
  if( nMap>pFd->mmapSizeMax ){
    nMap = pFd->mmapSizeMax;
  }
  nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
 
  if( nMap==0 && pFd->mmapSize>0 ){
    winUnmapfile(pFd);
  }
  if( nMap!=pFd->mmapSize ){
    void *pNew = 0;
    DWORD protect = PAGE_READONLY;
    DWORD flags = FILE_MAP_READ;

    winUnmapfile(pFd);
    if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
      protect = PAGE_READWRITE;
      flags |= FILE_MAP_WRITE;
    }
#if SQLITE_OS_WINRT
    pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
#elif defined(SQLITE_WIN32_HAS_WIDE)
    pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
                                (DWORD)((nMap>>32) & 0xffffffff),
                                (DWORD)(nMap & 0xffffffff), NULL);
#elif defined(SQLITE_WIN32_HAS_ANSI)
    pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
                                (DWORD)((nMap>>32) & 0xffffffff),
                                (DWORD)(nMap & 0xffffffff), NULL);
#endif
    if( pFd->hMap==NULL ){
      pFd->lastErrno = osGetLastError();
      rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
                       "winMapfile", pFd->zPath);
      /* Log the error, but continue normal operation using xRead/xWrite */
      return SQLITE_OK;
    }
    assert( (nMap % winSysInfo.dwPageSize)==0 );
#if SQLITE_OS_WINRT
    pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
#else
    assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
    pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
#endif
    if( pNew==NULL ){
      osCloseHandle(pFd->hMap);
      pFd->hMap = NULL;
      pFd->lastErrno = osGetLastError();
      winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
                  "winMapfile", pFd->zPath);
      return SQLITE_OK;
    }
    pFd->pMapRegion = pNew;
    pFd->mmapSize = nMap;
    pFd->mmapSizeActual = nMap;
  }

  return SQLITE_OK;
}
#endif /* SQLITE_MAX_MMAP_SIZE>0 */

/*
** If possible, return a pointer to a mapping of file fd starting at offset
** iOff. The mapping must be valid for at least nAmt bytes.
**
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
** If this function does return a pointer, the caller must eventually 
** release the reference by calling unixUnfetch().
*/
static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
  winFile *pFd = (winFile*)fd;   /* The underlying database file */
#endif
  *pp = 0;

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFd->mmapSizeMax>0 ){
    if( pFd->pMapRegion==0 ){
      int rc = winMapfile(pFd, -1);
      if( rc!=SQLITE_OK ) return rc;
    }
    if( pFd->mmapSize >= iOff+nAmt ){
      *pp = &((u8 *)pFd->pMapRegion)[iOff];
      pFd->nFetchOut++;
    }
  }
#endif
  return SQLITE_OK;
}

/*
** If the third argument is non-NULL, then this function releases a 
** reference obtained by an earlier call to unixFetch(). The second
** argument passed to this function must be the same as the corresponding
** argument that was passed to the unixFetch() invocation. 
**
** Or, if the third argument is NULL, then this function is being called 
** to inform the VFS layer that, according to POSIX, any existing mapping 
** may now be invalid and should be unmapped.
*/
static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
#if SQLITE_MAX_MMAP_SIZE>0
  winFile *pFd = (winFile*)fd;   /* The underlying database file */

  /* If p==0 (unmap the entire file) then there must be no outstanding 
  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
  ** then there must be at least one outstanding.  */
  assert( (p==0)==(pFd->nFetchOut==0) );

  /* If p!=0, it must match the iOff value. */
  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );

  if( p ){
    pFd->nFetchOut--;
  }else{
    /* FIXME:  If Windows truly always prevents truncating or deleting a
    ** file while a mapping is held, then the following winUnmapfile() call
    ** is unnecessary can can be omitted - potentially improving
    ** performance.  */
    winUnmapfile(pFd);
  }

  assert( pFd->nFetchOut>=0 );
#endif
  return SQLITE_OK;
}

/*
** Here ends the implementation of all sqlite3_file methods.
**
********************** End sqlite3_file Methods *******************************
******************************************************************************/

/*
** This vector defines all the methods that can operate on an
** sqlite3_file for win32.
*/
static const sqlite3_io_methods winIoMethod = {
  3,                              /* iVersion */
  winClose,                       /* xClose */
  winRead,                        /* xRead */
  winWrite,                       /* xWrite */
  winTruncate,                    /* xTruncate */
  winSync,                        /* xSync */
  winFileSize,                    /* xFileSize */
  winLock,                        /* xLock */
................................................................................
  winCheckReservedLock,           /* xCheckReservedLock */
  winFileControl,                 /* xFileControl */
  winSectorSize,                  /* xSectorSize */
  winDeviceCharacteristics,       /* xDeviceCharacteristics */
  winShmMap,                      /* xShmMap */
  winShmLock,                     /* xShmLock */
  winShmBarrier,                  /* xShmBarrier */
  winShmUnmap,                    /* xShmUnmap */
  winFetch,                       /* xFetch */
  winUnfetch                      /* xUnfetch */
};

/****************************************************************************
**************************** sqlite3_vfs methods ****************************
**
** This division contains the implementation of methods on the
** sqlite3_vfs object.
................................................................................
#if !defined(NDEBUG) || SQLITE_OS_WINCE
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
#endif

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);

  int isReadonly   = (flags & SQLITE_OPEN_READONLY);

  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);

#ifndef NDEBUG
  int isOpenJournal = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL 
     || eType==SQLITE_OPEN_MAIN_JOURNAL 
     || eType==SQLITE_OPEN_WAL
................................................................................
  {
    sqlite3_free(zConverted);
  }

  pFile->pMethod = &winIoMethod;
  pFile->pVfs = pVfs;
  pFile->h = h;
  if( isReadonly ){
    pFile->ctrlFlags |= WINFILE_RDONLY;
  }
  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pFile->ctrlFlags |= WINFILE_PSOW;
  }
  pFile->lastErrno = NO_ERROR;
  pFile->zPath = zName;
#if SQLITE_MAX_MMAP_SIZE>0
  pFile->hMap = NULL;
  pFile->pMapRegion = 0;
  pFile->mmapSize = 0;
  pFile->mmapSizeActual = 0;
  pFile->mmapSizeMax = sqlite3GlobalConfig.mxMmap;
#endif

  OpenCounter(+1);
  return rc;
}

/*
** Delete the named file.
................................................................................
    winNextSystemCall,   /* xNextSystemCall */
  };

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==74 );


  /* get memory map allocation granularity */
  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
#if SQLITE_OS_WINRT
  osGetNativeSystemInfo(&winSysInfo);
#else
  osGetSystemInfo(&winSysInfo);
#endif
  assert( winSysInfo.dwAllocationGranularity>0 );
  assert( winSysInfo.dwPageSize>0 );

  sqlite3_vfs_register(&winVfs, 1);
  return SQLITE_OK; 
}

int sqlite3_os_end(void){ 
#if SQLITE_OS_WINRT

Changes to src/pager.c.

651
652
653
654
655
656
657





658
659
660
661
662
663
664
...
761
762
763
764
765
766
767










768
769
770
771
772
773
774
....
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
....
2639
2640
2641
2642
2643
2644
2645

2646
2647
2648
2649
2650
2651
2652
....
2739
2740
2741
2742
2743
2744
2745
2746


2747
2748
2749
2750
2751
2752
2753
....
2809
2810
2811
2812
2813
2814
2815




2816
2817
2818
2819
2820
2821
2822
....
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
....
2929
2930
2931
2932
2933
2934
2935

2936
2937
2938
2939
2940



2941

2942
2943
2944
2945
2946
2947
2948
....
3078
3079
3080
3081
3082
3083
3084

3085
3086
3087
3088
3089
3090
3091
....
3338
3339
3340
3341
3342
3343
3344























3345
3346
3347
3348
3349
3350
3351
....
3574
3575
3576
3577
3578
3579
3580

3581
3582
3583
3584
3585
3586
3587
....
3798
3799
3800
3801
3802
3803
3804











































































3805
3806
3807
3808
3809
3810
3811
....
3819
3820
3821
3822
3823
3824
3825

3826
3827
3828
3829
3830
3831
3832
....
4080
4081
4082
4083
4084
4085
4086
4087


4088
4089
4090
4091
4092
4093
4094
....
4634
4635
4636
4637
4638
4639
4640

4641
4642
4643
4644
4645
4646
4647
....
4925
4926
4927
4928
4929
4930
4931
4932

4933

4934
4935
4936
4937
4938
4939
4940
4941
....
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968










4969
4970
4971
4972
4973
4974
4975
....
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
....
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072













5073
5074
5075

5076
5077
5078
5079
5080
5081
5082
5083
5084
5085

































5086
5087
5088
5089
5090
5091
5092
....
5137
5138
5139
5140
5141
5142
5143




5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
....
5192
5193
5194
5195
5196
5197
5198



5199

5200
5201
5202
5203
5204
5205
5206
....
5527
5528
5529
5530
5531
5532
5533

5534
5535
5536
5537
5538
5539
5540
....
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
....
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828

6829
6830
6831
6832
6833
6834
6835
....
6912
6913
6914
6915
6916
6917
6918

6919
6920
6921
6922
6923
6924
6925
  sqlite3_file *sjfd;         /* File descriptor for sub-journal */
  i64 journalOff;             /* Current write offset in the journal file */
  i64 journalHdr;             /* Byte offset to previous journal header */
  sqlite3_backup *pBackup;    /* Pointer to list of ongoing backup processes */
  PagerSavepoint *aSavepoint; /* Array of active savepoints */
  int nSavepoint;             /* Number of elements in aSavepoint[] */
  char dbFileVers[16];        /* Changes whenever database file changes */





  /*
  ** End of the routinely-changing class members
  ***************************************************************************/

  u16 nExtra;                 /* Add this many bytes to each in-memory page */
  i16 nReserve;               /* Number of unused bytes at end of each page */
  u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
................................................................................
*/
#ifdef SQLITE_OMIT_MEMORYDB
# define MEMDB 0
#else
# define MEMDB pPager->memDb
#endif











/*
** The maximum legal page number is (2^31 - 1).
*/
#define PAGER_MAX_PGNO 2147483647

/*
** The argument to this macro is a file descriptor (type sqlite3_file*).
................................................................................
  if( isOpen(pPager->fd)
   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
   && isSynced
  ){
    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
    testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
    assert( !pagerUseWal(pPager) );
    rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst);
    if( pgno>pPager->dbFileSize ){
      pPager->dbFileSize = pgno;
    }
    if( pPager->pBackup ){
      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
................................................................................
  u32 nRec;                /* Number of Records in the journal */
  u32 u;                   /* Unsigned loop counter */
  Pgno mxPg = 0;           /* Size of the original file in pages */
  int rc;                  /* Result code of a subroutine */
  int res = 1;             /* Value returned by sqlite3OsAccess() */
  char *zMaster = 0;       /* Name of master journal file if any */
  int needPagerReset;      /* True to reset page prior to first page rollback */


  /* Figure out how many records are in the journal.  Abort early if
  ** the journal is empty.
  */
  assert( isOpen(pPager->jfd) );
  rc = sqlite3OsFileSize(pPager->jfd, &szJ);
  if( rc!=SQLITE_OK ){
................................................................................
    */
    for(u=0; u<nRec; u++){
      if( needPagerReset ){
        pager_reset(pPager);
        needPagerReset = 0;
      }
      rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
      if( rc!=SQLITE_OK ){


        if( rc==SQLITE_DONE ){
          pPager->journalOff = szJ;
          break;
        }else if( rc==SQLITE_IOERR_SHORT_READ ){
          /* If the journal has been truncated, simply stop reading and
          ** processing the journal. This might happen if the journal was
          ** not completely written and synced prior to a crash.  In that
................................................................................
  if( rc==SQLITE_OK && zMaster[0] && res ){
    /* If there was a master journal and this routine will return success,
    ** see if it is possible to delete the master journal.
    */
    rc = pager_delmaster(pPager, zMaster);
    testcase( rc!=SQLITE_OK );
  }





  /* The Pager.sectorSize variable may have been updated while rolling
  ** back a journal created by a process with a different sector size
  ** value. Reset it to the correct value for this process.
  */
  setSectorSize(pPager);
  return rc;
................................................................................
**
** If page 1 is read, then the value of Pager.dbFileVers[] is set to
** the value read from the database file.
**
** If an IO error occurs, then the IO error is returned to the caller.
** Otherwise, SQLITE_OK is returned.
*/
static int readDbPage(PgHdr *pPg){
  Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
  Pgno pgno = pPg->pgno;       /* Page number to read */
  int rc = SQLITE_OK;          /* Return code */
  int isInWal = 0;             /* True if page is in log file */
  int pgsz = pPager->pageSize; /* Number of bytes to read */

  assert( pPager->eState>=PAGER_READER && !MEMDB );
  assert( isOpen(pPager->fd) );

  if( NEVER(!isOpen(pPager->fd)) ){
    assert( pPager->tempFile );
    memset(pPg->pData, 0, pPager->pageSize);
    return SQLITE_OK;
  }

  if( pagerUseWal(pPager) ){
    /* Try to pull the page from the write-ahead log. */
    rc = sqlite3WalRead(pPager->pWal, pgno, &isInWal, pgsz, pPg->pData);
  }
  if( rc==SQLITE_OK && !isInWal ){
    i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
    rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
    if( rc==SQLITE_IOERR_SHORT_READ ){
      rc = SQLITE_OK;
    }
  }

................................................................................
** return an SQLite error code. Otherwise, SQLITE_OK.
*/
static int pagerUndoCallback(void *pCtx, Pgno iPg){
  int rc = SQLITE_OK;
  Pager *pPager = (Pager *)pCtx;
  PgHdr *pPg;


  pPg = sqlite3PagerLookup(pPager, iPg);
  if( pPg ){
    if( sqlite3PcachePageRefcount(pPg)==1 ){
      sqlite3PcacheDrop(pPg);
    }else{



      rc = readDbPage(pPg);

      if( rc==SQLITE_OK ){
        pPager->xReiniter(pPg);
      }
      sqlite3PagerUnref(pPg);
    }
  }

................................................................................
  ** the duplicate call is harmless.
  */
  sqlite3WalEndReadTransaction(pPager->pWal);

  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
  if( rc!=SQLITE_OK || changed ){
    pager_reset(pPager);

  }

  return rc;
}
#endif

/*
................................................................................

/*
** Change the maximum number of in-memory pages that are allowed.
*/
void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
  sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
}
























/*
** Free as much memory as possible from the pager.
*/
void sqlite3PagerShrink(Pager *pPager){
  sqlite3PcacheShrink(pPager->pPCache);
}
................................................................................

  *pPageSize = pPager->pageSize;
  if( rc==SQLITE_OK ){
    if( nReserve<0 ) nReserve = pPager->nReserve;
    assert( nReserve>=0 && nReserve<1000 );
    pPager->nReserve = (i16)nReserve;
    pagerReportSize(pPager);

  }
  return rc;
}

/*
** Return a pointer to the "temporary page" buffer held internally
** by the pager.  This is a buffer that is big enough to hold the
................................................................................
    rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
  }
  return rc;
}












































































/*
** Shutdown the page cache.  Free all memory and close all files.
**
** If a transaction was in progress when this routine is called, that
** transaction is rolled back.  All outstanding pages are invalidated
** and their memory is freed.  Any attempt to use a page associated
................................................................................
*/
int sqlite3PagerClose(Pager *pPager){
  u8 *pTmp = (u8 *)pPager->pTmpSpace;

  assert( assert_pager_state(pPager) );
  disable_simulated_io_errors();
  sqlite3BeginBenignMalloc();

  /* pPager->errCode = 0; */
  pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
  sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
  pPager->pWal = 0;
#endif
  pager_reset(pPager);
................................................................................
    rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
  }

  /* Before the first write, give the VFS a hint of what the final
  ** file size will be.
  */
  assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
  if( rc==SQLITE_OK && pPager->dbSize>pPager->dbHintSize ){


    sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
    pPager->dbHintSize = pPager->dbSize;
  }

  while( rc==SQLITE_OK && pList ){
    Pgno pgno = pList->pgno;
................................................................................
  }else if( memDb ){
    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
  }
  /* pPager->xBusyHandler = 0; */
  /* pPager->pBusyHandlerArg = 0; */
  pPager->xReiniter = xReinit;
  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */


  *ppPager = pPager;
  return SQLITE_OK;
}



................................................................................

      assert( pPager->eState==PAGER_OPEN );
      assert( (pPager->eLock==SHARED_LOCK)
           || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
      );
    }

    if( !pPager->tempFile 

     && (pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0) 

    ){
      /* The shared-lock has just been acquired on the database file
      ** and there are already pages in the cache (from a previous
      ** read or write transaction).  Check to see if the database
      ** has been modified.  If the database has changed, flush the
      ** cache.
      **
      ** Database changes is detected by looking at 15 bytes beginning
................................................................................

      rc = pagerPagecount(pPager, &nPage);
      if( rc ) goto failed;

      if( nPage>0 ){
        IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
        rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
        if( rc!=SQLITE_OK ){
          goto failed;
        }
      }else{
        memset(dbFileVers, 0, sizeof(dbFileVers));
      }

      if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
        pager_reset(pPager);










      }
    }

    /* If there is a WAL file in the file-system, open this database in WAL
    ** mode. Otherwise, the following function call is a no-op.
    */
    rc = pagerOpenWalIfPresent(pPager);
................................................................................
** transaction and unlock the pager.
**
** Except, in locking_mode=EXCLUSIVE when there is nothing to in
** the rollback journal, the unlock is not performed and there is
** nothing to rollback, so this routine is a no-op.
*/ 
static void pagerUnlockIfUnused(Pager *pPager){
  if( (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
    pagerUnlockAndRollback(pPager);
  }
}

/*
** Acquire a reference to page number pgno in pager pPager (a page
** reference has type DbPage*). If the requested reference is 
................................................................................
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
int sqlite3PagerAcquire(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int noContent       /* Do not bother reading content from disk if true */
){
  int rc;
  PgHdr *pPg;














  assert( pPager->eState>=PAGER_READER );
  assert( assert_pager_state(pPager) );


  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
  }

  /* If the pager is in the error state, return an error immediately. 
  ** Otherwise, request the page from the PCache layer. */
  if( pPager->errCode!=SQLITE_OK ){
    rc = pPager->errCode;
  }else{

































    rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
  }

  if( rc!=SQLITE_OK ){
    /* Either the call to sqlite3PcacheFetch() returned an error or the
    ** pager was already in the error-state when this function was called.
    ** Set pPg to 0 and jump to the exception handler.  */
................................................................................
        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
        testcase( rc==SQLITE_NOMEM );
        sqlite3EndBenignMalloc();
      }
      memset(pPg->pData, 0, pPager->pageSize);
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{




      assert( pPg->pPager==pPager );
      pPager->aStat[PAGER_STAT_MISS]++;
      rc = readDbPage(pPg);
      if( rc!=SQLITE_OK ){
        goto pager_acquire_err;
      }
    }
    pager_set_pagehash(pPg);
  }

................................................................................
** page is added to the LRU list.  When all references to all pages
** are released, a rollback occurs and the lock on the database is
** removed.
*/
void sqlite3PagerUnref(DbPage *pPg){
  if( pPg ){
    Pager *pPager = pPg->pPager;



    sqlite3PcacheRelease(pPg);

    pagerUnlockIfUnused(pPager);
  }
}

/*
** This function is called at the start of every write transaction.
** There must already be a RESERVED or EXCLUSIVE lock on the database 
................................................................................
int sqlite3PagerWrite(DbPage *pDbPage){
  int rc = SQLITE_OK;

  PgHdr *pPg = pDbPage;
  Pager *pPager = pPg->pPager;
  Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);


  assert( pPager->eState>=PAGER_WRITER_LOCKED );
  assert( pPager->eState!=PAGER_ERROR );
  assert( assert_pager_state(pPager) );

  if( nPagePerSector>1 ){
    Pgno nPageCount;          /* Total number of pages in database file */
    Pgno pg1;                 /* First page of the sector pPg is located on. */
................................................................................
      return rc;
    }
  }else{
    rc = pager_playback(pPager, 0);
  }

  assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
  assert( rc==SQLITE_OK || rc==SQLITE_FULL
          || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );

  /* If an error occurs during a ROLLBACK, we can no longer trust the pager
  ** cache. So call pager_error() on the way out to make any error persistent.
  */
  return pager_error(pPager, rc);
}
................................................................................
    rc = pagerExclusiveLock(pPager);
  }

  /* Open the connection to the log file. If this operation fails, 
  ** (e.g. due to malloc() failure), return an error code.
  */
  if( rc==SQLITE_OK ){
    rc = sqlite3WalOpen(pPager->pVfs, 
        pPager->fd, pPager->zWal, pPager->exclusiveMode,
        pPager->journalSizeLimit, &pPager->pWal
    );
  }


  return rc;
}


/*
** The caller must be holding a SHARED lock on the database file to call
................................................................................
  */
  if( rc==SQLITE_OK && pPager->pWal ){
    rc = pagerExclusiveLock(pPager);
    if( rc==SQLITE_OK ){
      rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
                           pPager->pageSize, (u8*)pPager->pTmpSpace);
      pPager->pWal = 0;

    }
  }
  return rc;
}

#endif /* !SQLITE_OMIT_WAL */








>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>







 







|







 







>







 







|
>
>







 







>
>
>
>







 







|



<











|

|
|
<







 







>





>
>
>
|
>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







|
>
>







 







>







 







|
>
|
>
|







 







|








>
>
>
>
>
>
>
>
>
>







 







|







 







|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>



>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>


|







 







>
>
>
|
>







 







>







 







|







 







|




>







 







>







651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
....
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
....
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
....
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
....
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
....
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862

2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877

2878
2879
2880
2881
2882
2883
2884
....
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
....
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
....
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
....
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
....
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
....
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
....
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
....
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
....
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
....
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
....
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
....
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
....
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
....
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
....
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
....
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
....
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
....
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
  sqlite3_file *sjfd;         /* File descriptor for sub-journal */
  i64 journalOff;             /* Current write offset in the journal file */
  i64 journalHdr;             /* Byte offset to previous journal header */
  sqlite3_backup *pBackup;    /* Pointer to list of ongoing backup processes */
  PagerSavepoint *aSavepoint; /* Array of active savepoints */
  int nSavepoint;             /* Number of elements in aSavepoint[] */
  char dbFileVers[16];        /* Changes whenever database file changes */

  u8 bUseFetch;               /* True to use xFetch() */
  int nMmapOut;               /* Number of mmap pages currently outstanding */
  sqlite3_int64 szMmap;       /* Desired maximum mmap size */
  PgHdr *pMmapFreelist;       /* List of free mmap page headers (pDirty) */
  /*
  ** End of the routinely-changing class members
  ***************************************************************************/

  u16 nExtra;                 /* Add this many bytes to each in-memory page */
  i16 nReserve;               /* Number of unused bytes at end of each page */
  u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
................................................................................
*/
#ifdef SQLITE_OMIT_MEMORYDB
# define MEMDB 0
#else
# define MEMDB pPager->memDb
#endif

/*
** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
** interfaces to access the database using memory-mapped I/O.
*/
#if SQLITE_MAX_MMAP_SIZE>0
# define USEFETCH(x) ((x)->bUseFetch)
#else
# define USEFETCH(x) 0
#endif

/*
** The maximum legal page number is (2^31 - 1).
*/
#define PAGER_MAX_PGNO 2147483647

/*
** The argument to this macro is a file descriptor (type sqlite3_file*).
................................................................................
  if( isOpen(pPager->fd)
   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
   && isSynced
  ){
    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
    testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
    assert( !pagerUseWal(pPager) );
    rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
    if( pgno>pPager->dbFileSize ){
      pPager->dbFileSize = pgno;
    }
    if( pPager->pBackup ){
      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
................................................................................
  u32 nRec;                /* Number of Records in the journal */
  u32 u;                   /* Unsigned loop counter */
  Pgno mxPg = 0;           /* Size of the original file in pages */
  int rc;                  /* Result code of a subroutine */
  int res = 1;             /* Value returned by sqlite3OsAccess() */
  char *zMaster = 0;       /* Name of master journal file if any */
  int needPagerReset;      /* True to reset page prior to first page rollback */
  int nPlayback = 0;       /* Total number of pages restored from journal */

  /* Figure out how many records are in the journal.  Abort early if
  ** the journal is empty.
  */
  assert( isOpen(pPager->jfd) );
  rc = sqlite3OsFileSize(pPager->jfd, &szJ);
  if( rc!=SQLITE_OK ){
................................................................................
    */
    for(u=0; u<nRec; u++){
      if( needPagerReset ){
        pager_reset(pPager);
        needPagerReset = 0;
      }
      rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
      if( rc==SQLITE_OK ){
        nPlayback++;
      }else{
        if( rc==SQLITE_DONE ){
          pPager->journalOff = szJ;
          break;
        }else if( rc==SQLITE_IOERR_SHORT_READ ){
          /* If the journal has been truncated, simply stop reading and
          ** processing the journal. This might happen if the journal was
          ** not completely written and synced prior to a crash.  In that
................................................................................
  if( rc==SQLITE_OK && zMaster[0] && res ){
    /* If there was a master journal and this routine will return success,
    ** see if it is possible to delete the master journal.
    */
    rc = pager_delmaster(pPager, zMaster);
    testcase( rc!=SQLITE_OK );
  }
  if( isHot && nPlayback ){
    sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
                nPlayback, pPager->zJournal);
  }

  /* The Pager.sectorSize variable may have been updated while rolling
  ** back a journal created by a process with a different sector size
  ** value. Reset it to the correct value for this process.
  */
  setSectorSize(pPager);
  return rc;
................................................................................
**
** If page 1 is read, then the value of Pager.dbFileVers[] is set to
** the value read from the database file.
**
** If an IO error occurs, then the IO error is returned to the caller.
** Otherwise, SQLITE_OK is returned.
*/
static int readDbPage(PgHdr *pPg, u32 iFrame){
  Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
  Pgno pgno = pPg->pgno;       /* Page number to read */
  int rc = SQLITE_OK;          /* Return code */

  int pgsz = pPager->pageSize; /* Number of bytes to read */

  assert( pPager->eState>=PAGER_READER && !MEMDB );
  assert( isOpen(pPager->fd) );

  if( NEVER(!isOpen(pPager->fd)) ){
    assert( pPager->tempFile );
    memset(pPg->pData, 0, pPager->pageSize);
    return SQLITE_OK;
  }

  if( iFrame ){
    /* Try to pull the page from the write-ahead log. */
    rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
  }else{

    i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
    rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
    if( rc==SQLITE_IOERR_SHORT_READ ){
      rc = SQLITE_OK;
    }
  }

................................................................................
** return an SQLite error code. Otherwise, SQLITE_OK.
*/
static int pagerUndoCallback(void *pCtx, Pgno iPg){
  int rc = SQLITE_OK;
  Pager *pPager = (Pager *)pCtx;
  PgHdr *pPg;

  assert( pagerUseWal(pPager) );
  pPg = sqlite3PagerLookup(pPager, iPg);
  if( pPg ){
    if( sqlite3PcachePageRefcount(pPg)==1 ){
      sqlite3PcacheDrop(pPg);
    }else{
      u32 iFrame = 0;
      rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
      if( rc==SQLITE_OK ){
        rc = readDbPage(pPg, iFrame);
      }
      if( rc==SQLITE_OK ){
        pPager->xReiniter(pPg);
      }
      sqlite3PagerUnref(pPg);
    }
  }

................................................................................
  ** the duplicate call is harmless.
  */
  sqlite3WalEndReadTransaction(pPager->pWal);

  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
  if( rc!=SQLITE_OK || changed ){
    pager_reset(pPager);
    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
  }

  return rc;
}
#endif

/*
................................................................................

/*
** Change the maximum number of in-memory pages that are allowed.
*/
void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
  sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
}

/*
** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
*/
static void pagerFixMaplimit(Pager *pPager){
#if SQLITE_MAX_MMAP_SIZE>0
  sqlite3_file *fd = pPager->fd;
  if( isOpen(fd) ){
    sqlite3_int64 sz;
    pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
    sz = pPager->szMmap;
    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
  }
#endif
}

/*
** Change the maximum size of any memory mapping made of the database file.
*/
void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
  pPager->szMmap = szMmap;
  pagerFixMaplimit(pPager);
}

/*
** Free as much memory as possible from the pager.
*/
void sqlite3PagerShrink(Pager *pPager){
  sqlite3PcacheShrink(pPager->pPCache);
}
................................................................................

  *pPageSize = pPager->pageSize;
  if( rc==SQLITE_OK ){
    if( nReserve<0 ) nReserve = pPager->nReserve;
    assert( nReserve>=0 && nReserve<1000 );
    pPager->nReserve = (i16)nReserve;
    pagerReportSize(pPager);
    pagerFixMaplimit(pPager);
  }
  return rc;
}

/*
** Return a pointer to the "temporary page" buffer held internally
** by the pager.  This is a buffer that is big enough to hold the
................................................................................
    rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
  }
  return rc;
}

/*
** Obtain a reference to a memory mapped page object for page number pgno. 
** The new object will use the pointer pData, obtained from xFetch().
** If successful, set *ppPage to point to the new page reference
** and return SQLITE_OK. Otherwise, return an SQLite error code and set
** *ppPage to zero.
**
** Page references obtained by calling this function should be released
** by calling pagerReleaseMapPage().
*/
static int pagerAcquireMapPage(
  Pager *pPager,                  /* Pager object */
  Pgno pgno,                      /* Page number */
  void *pData,                    /* xFetch()'d data for this page */
  PgHdr **ppPage                  /* OUT: Acquired page object */
){
  PgHdr *p;                       /* Memory mapped page to return */

  if( pPager->pMmapFreelist ){
    *ppPage = p = pPager->pMmapFreelist;
    pPager->pMmapFreelist = p->pDirty;
    p->pDirty = 0;
    memset(p->pExtra, 0, pPager->nExtra);
  }else{
    *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
    if( p==0 ){
      sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
      return SQLITE_NOMEM;
    }
    p->pExtra = (void *)&p[1];
    p->flags = PGHDR_MMAP;
    p->nRef = 1;
    p->pPager = pPager;
  }

  assert( p->pExtra==(void *)&p[1] );
  assert( p->pPage==0 );
  assert( p->flags==PGHDR_MMAP );
  assert( p->pPager==pPager );
  assert( p->nRef==1 );

  p->pgno = pgno;
  p->pData = pData;
  pPager->nMmapOut++;

  return SQLITE_OK;
}

/*
** Release a reference to page pPg. pPg must have been returned by an 
** earlier call to pagerAcquireMapPage().
*/
static void pagerReleaseMapPage(PgHdr *pPg){
  Pager *pPager = pPg->pPager;
  pPager->nMmapOut--;
  pPg->pDirty = pPager->pMmapFreelist;
  pPager->pMmapFreelist = pPg;

  assert( pPager->fd->pMethods->iVersion>=3 );
  sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
}

/*
** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
*/
static void pagerFreeMapHdrs(Pager *pPager){
  PgHdr *p;
  PgHdr *pNext;
  for(p=pPager->pMmapFreelist; p; p=pNext){
    pNext = p->pDirty;
    sqlite3_free(p);
  }
}


/*
** Shutdown the page cache.  Free all memory and close all files.
**
** If a transaction was in progress when this routine is called, that
** transaction is rolled back.  All outstanding pages are invalidated
** and their memory is freed.  Any attempt to use a page associated
................................................................................
*/
int sqlite3PagerClose(Pager *pPager){
  u8 *pTmp = (u8 *)pPager->pTmpSpace;

  assert( assert_pager_state(pPager) );
  disable_simulated_io_errors();
  sqlite3BeginBenignMalloc();
  pagerFreeMapHdrs(pPager);
  /* pPager->errCode = 0; */
  pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
  sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
  pPager->pWal = 0;
#endif
  pager_reset(pPager);
................................................................................
    rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
  }

  /* Before the first write, give the VFS a hint of what the final
  ** file size will be.
  */
  assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
  if( rc==SQLITE_OK 
   && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize 
  ){
    sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
    pPager->dbHintSize = pPager->dbSize;
  }

  while( rc==SQLITE_OK && pList ){
    Pgno pgno = pList->pgno;
................................................................................
  }else if( memDb ){
    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
  }
  /* pPager->xBusyHandler = 0; */
  /* pPager->pBusyHandlerArg = 0; */
  pPager->xReiniter = xReinit;
  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
  /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */

  *ppPager = pPager;
  return SQLITE_OK;
}



................................................................................

      assert( pPager->eState==PAGER_OPEN );
      assert( (pPager->eLock==SHARED_LOCK)
           || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
      );
    }

    if( !pPager->tempFile && (
        pPager->pBackup 
     || sqlite3PcachePagecount(pPager->pPCache)>0 
     || USEFETCH(pPager)
    )){
      /* The shared-lock has just been acquired on the database file
      ** and there are already pages in the cache (from a previous
      ** read or write transaction).  Check to see if the database
      ** has been modified.  If the database has changed, flush the
      ** cache.
      **
      ** Database changes is detected by looking at 15 bytes beginning
................................................................................

      rc = pagerPagecount(pPager, &nPage);
      if( rc ) goto failed;

      if( nPage>0 ){
        IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
        rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
        if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
          goto failed;
        }
      }else{
        memset(dbFileVers, 0, sizeof(dbFileVers));
      }

      if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
        pager_reset(pPager);

        /* Unmap the database file. It is possible that external processes
        ** may have truncated the database file and then extended it back
        ** to its original size while this process was not holding a lock.
        ** In this case there may exist a Pager.pMap mapping that appears
        ** to be the right size but is not actually valid. Avoid this
        ** possibility by unmapping the db here. */
        if( USEFETCH(pPager) ){
          sqlite3OsUnfetch(pPager->fd, 0, 0);
        }
      }
    }

    /* If there is a WAL file in the file-system, open this database in WAL
    ** mode. Otherwise, the following function call is a no-op.
    */
    rc = pagerOpenWalIfPresent(pPager);
................................................................................
** transaction and unlock the pager.
**
** Except, in locking_mode=EXCLUSIVE when there is nothing to in
** the rollback journal, the unlock is not performed and there is
** nothing to rollback, so this routine is a no-op.
*/ 
static void pagerUnlockIfUnused(Pager *pPager){
  if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
    pagerUnlockAndRollback(pPager);
  }
}

/*
** Acquire a reference to page number pgno in pager pPager (a page
** reference has type DbPage*). If the requested reference is 
................................................................................
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
int sqlite3PagerAcquire(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_ACQUIRE_XXX flags */
){
  int rc = SQLITE_OK;
  PgHdr *pPg = 0;
  u32 iFrame = 0;                 /* Frame to read from WAL file */
  const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);

  /* It is acceptable to use a read-only (mmap) page for any page except
  ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
  ** flag was specified by the caller. And so long as the db is not a 
  ** temporary or in-memory database.  */
  const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
   && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
#ifdef SQLITE_HAS_CODEC
   && pPager->xCodec==0
#endif
  );

  assert( pPager->eState>=PAGER_READER );
  assert( assert_pager_state(pPager) );
  assert( noContent==0 || bMmapOk==0 );

  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
  }

  /* If the pager is in the error state, return an error immediately. 
  ** Otherwise, request the page from the PCache layer. */
  if( pPager->errCode!=SQLITE_OK ){
    rc = pPager->errCode;
  }else{

    if( bMmapOk && pagerUseWal(pPager) ){
      rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
      if( rc!=SQLITE_OK ) goto pager_acquire_err;
    }

    if( iFrame==0 && bMmapOk ){
      void *pData = 0;

      rc = sqlite3OsFetch(pPager->fd, 
          (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
      );

      if( rc==SQLITE_OK && pData ){
        if( pPager->eState>PAGER_READER ){
          (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
        }
        if( pPg==0 ){
          rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
        }else{
          sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
        }
        if( pPg ){
          assert( rc==SQLITE_OK );
          *ppPage = pPg;
          return SQLITE_OK;
        }
      }
      if( rc!=SQLITE_OK ){
        goto pager_acquire_err;
      }
    }

    rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
  }

  if( rc!=SQLITE_OK ){
    /* Either the call to sqlite3PcacheFetch() returned an error or the
    ** pager was already in the error-state when this function was called.
    ** Set pPg to 0 and jump to the exception handler.  */
................................................................................
        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
        testcase( rc==SQLITE_NOMEM );
        sqlite3EndBenignMalloc();
      }
      memset(pPg->pData, 0, pPager->pageSize);
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{
      if( pagerUseWal(pPager) && bMmapOk==0 ){
        rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
        if( rc!=SQLITE_OK ) goto pager_acquire_err;
      }
      assert( pPg->pPager==pPager );
      pPager->aStat[PAGER_STAT_MISS]++;
      rc = readDbPage(pPg, iFrame);
      if( rc!=SQLITE_OK ){
        goto pager_acquire_err;
      }
    }
    pager_set_pagehash(pPg);
  }

................................................................................
** page is added to the LRU list.  When all references to all pages
** are released, a rollback occurs and the lock on the database is
** removed.
*/
void sqlite3PagerUnref(DbPage *pPg){
  if( pPg ){
    Pager *pPager = pPg->pPager;
    if( pPg->flags & PGHDR_MMAP ){
      pagerReleaseMapPage(pPg);
    }else{
      sqlite3PcacheRelease(pPg);
    }
    pagerUnlockIfUnused(pPager);
  }
}

/*
** This function is called at the start of every write transaction.
** There must already be a RESERVED or EXCLUSIVE lock on the database 
................................................................................
int sqlite3PagerWrite(DbPage *pDbPage){
  int rc = SQLITE_OK;

  PgHdr *pPg = pDbPage;
  Pager *pPager = pPg->pPager;
  Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);

  assert( (pPg->flags & PGHDR_MMAP)==0 );
  assert( pPager->eState>=PAGER_WRITER_LOCKED );
  assert( pPager->eState!=PAGER_ERROR );
  assert( assert_pager_state(pPager) );

  if( nPagePerSector>1 ){
    Pgno nPageCount;          /* Total number of pages in database file */
    Pgno pg1;                 /* First page of the sector pPg is located on. */
................................................................................
      return rc;
    }
  }else{
    rc = pager_playback(pPager, 0);
  }

  assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
  assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
          || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );

  /* If an error occurs during a ROLLBACK, we can no longer trust the pager
  ** cache. So call pager_error() on the way out to make any error persistent.
  */
  return pager_error(pPager, rc);
}
................................................................................
    rc = pagerExclusiveLock(pPager);
  }

  /* Open the connection to the log file. If this operation fails, 
  ** (e.g. due to malloc() failure), return an error code.
  */
  if( rc==SQLITE_OK ){
    rc = sqlite3WalOpen(pPager->pVfs,
        pPager->fd, pPager->zWal, pPager->exclusiveMode,
        pPager->journalSizeLimit, &pPager->pWal
    );
  }
  pagerFixMaplimit(pPager);

  return rc;
}


/*
** The caller must be holding a SHARED lock on the database file to call
................................................................................
  */
  if( rc==SQLITE_OK && pPager->pWal ){
    rc = pagerExclusiveLock(pPager);
    if( rc==SQLITE_OK ){
      rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
                           pPager->pageSize, (u8*)pPager->pTmpSpace);
      pPager->pWal = 0;
      pagerFixMaplimit(pPager);
    }
  }
  return rc;
}

#endif /* !SQLITE_OMIT_WAL */

Changes to src/pager.h.

74
75
76
77
78
79
80






81
82
83
84
85
86
87
..
98
99
100
101
102
103
104

105
106
107
108
109
110
111
#define PAGER_JOURNALMODE_DELETE      0   /* Commit by deleting journal file */
#define PAGER_JOURNALMODE_PERSIST     1   /* Commit by zeroing journal header */
#define PAGER_JOURNALMODE_OFF         2   /* Journal omitted.  */
#define PAGER_JOURNALMODE_TRUNCATE    3   /* Commit by truncating journal */
#define PAGER_JOURNALMODE_MEMORY      4   /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL         5   /* Use write-ahead logging */







/*
** The remainder of this file contains the declarations of the functions
** that make up the Pager sub-system API. See source code comments for 
** a detailed description of each routine.
*/

/* Open and close a Pager connection. */ 
................................................................................
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);

/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
int sqlite3PagerSetPagesize(Pager*, u32*, int);
int sqlite3PagerMaxPageCount(Pager*, int);
void sqlite3PagerSetCachesize(Pager*, int);

void sqlite3PagerShrink(Pager*);
void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerSetJournalMode(Pager *, int);
int sqlite3PagerGetJournalMode(Pager*);
int sqlite3PagerOkToChangeJournalMode(Pager*);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);







>
>
>
>
>
>







 







>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#define PAGER_JOURNALMODE_DELETE      0   /* Commit by deleting journal file */
#define PAGER_JOURNALMODE_PERSIST     1   /* Commit by zeroing journal header */
#define PAGER_JOURNALMODE_OFF         2   /* Journal omitted.  */
#define PAGER_JOURNALMODE_TRUNCATE    3   /* Commit by truncating journal */
#define PAGER_JOURNALMODE_MEMORY      4   /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL         5   /* Use write-ahead logging */

/*
** Flags that make up the mask passed to sqlite3PagerAcquire().
*/
#define PAGER_ACQUIRE_NOCONTENT     0x01  /* Do not load data from disk */
#define PAGER_ACQUIRE_READONLY      0x02  /* Read-only page is acceptable */

/*
** The remainder of this file contains the declarations of the functions
** that make up the Pager sub-system API. See source code comments for 
** a detailed description of each routine.
*/

/* Open and close a Pager connection. */ 
................................................................................
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);

/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
int sqlite3PagerSetPagesize(Pager*, u32*, int);
int sqlite3PagerMaxPageCount(Pager*, int);
void sqlite3PagerSetCachesize(Pager*, int);
void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
void sqlite3PagerShrink(Pager*);
void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerSetJournalMode(Pager *, int);
int sqlite3PagerGetJournalMode(Pager*);
int sqlite3PagerOkToChangeJournalMode(Pager*);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);

Changes to src/pcache.h.

48
49
50
51
52
53
54


55
56
57
58
59
60
61
/* Bit values for PgHdr.flags */
#define PGHDR_DIRTY             0x002  /* Page has changed */
#define PGHDR_NEED_SYNC         0x004  /* Fsync the rollback journal before
                                       ** writing this page to the database */
#define PGHDR_NEED_READ         0x008  /* Content is unread */
#define PGHDR_REUSE_UNLIKELY    0x010  /* A hint that reuse is unlikely */
#define PGHDR_DONT_WRITE        0x020  /* Do not write content to disk */



/* Initialize and shutdown the page cache subsystem */
int sqlite3PcacheInitialize(void);
void sqlite3PcacheShutdown(void);

/* Page cache buffer management:
** These routines implement SQLITE_CONFIG_PAGECACHE.







>
>







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/* Bit values for PgHdr.flags */
#define PGHDR_DIRTY             0x002  /* Page has changed */
#define PGHDR_NEED_SYNC         0x004  /* Fsync the rollback journal before
                                       ** writing this page to the database */
#define PGHDR_NEED_READ         0x008  /* Content is unread */
#define PGHDR_REUSE_UNLIKELY    0x010  /* A hint that reuse is unlikely */
#define PGHDR_DONT_WRITE        0x020  /* Do not write content to disk */

#define PGHDR_MMAP              0x040  /* This is an mmap page object */

/* Initialize and shutdown the page cache subsystem */
int sqlite3PcacheInitialize(void);
void sqlite3PcacheShutdown(void);

/* Page cache buffer management:
** These routines implement SQLITE_CONFIG_PAGECACHE.

Changes to src/pragma.c.

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
...
740
741
742
743
744
745
746





































747
748
749
750
751
752
753
  const char *zDb = 0;   /* The database name */
  Token *pId;            /* Pointer to <id> token */
  int iDb;               /* Database index for <database> */
  char *aFcntl[4];       /* Argument to SQLITE_FCNTL_PRAGMA */
  int rc;                      /* return value form SQLITE_FCNTL_PRAGMA */
  sqlite3 *db = pParse->db;    /* The database connection */
  Db *pDb;                     /* The specific database being pragmaed */
  Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);  /* Prepared statement */

  if( v==0 ) return;
  sqlite3VdbeRunOnlyOnce(v);
  pParse->nMem = 2;

  /* Interpret the [database.] part of the pragma statement. iDb is the
  ** index of the database this pragma is being applied to in db.aDb[]. */
................................................................................
  ** size.  But continue to take the absolute value of the default cache
  ** size of historical compatibility.
  */
  if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
    static const VdbeOpList getCacheSize[] = {
      { OP_Transaction, 0, 0,        0},                         /* 0 */
      { OP_ReadCookie,  0, 1,        BTREE_DEFAULT_CACHE_SIZE},  /* 1 */
      { OP_IfPos,       1, 7,        0},
      { OP_Integer,     0, 2,        0},
      { OP_Subtract,    1, 2,        1},
      { OP_IfPos,       1, 7,        0},
      { OP_Integer,     0, 1,        0},                         /* 6 */

      { OP_ResultRow,   1, 1,        0},
    };
    int addr;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    sqlite3VdbeUsesBtree(v, iDb);
    if( !zRight ){
      sqlite3VdbeSetNumCols(v, 1);
................................................................................
    }else{
      int size = sqlite3Atoi(zRight);
      pDb->pSchema->cache_size = size;
      sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
    }
  }else






































  /*
  **   PRAGMA temp_store
  **   PRAGMA temp_store = "default"|"memory"|"file"
  **
  ** Return or set the local value of the temp_store flag.  Changing
  ** the local value does not make changes to the disk file and the default
  ** value will be restored the next time the database is opened.







|







 







|


|

>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
...
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
  const char *zDb = 0;   /* The database name */
  Token *pId;            /* Pointer to <id> token */
  int iDb;               /* Database index for <database> */
  char *aFcntl[4];       /* Argument to SQLITE_FCNTL_PRAGMA */
  int rc;                      /* return value form SQLITE_FCNTL_PRAGMA */
  sqlite3 *db = pParse->db;    /* The database connection */
  Db *pDb;                     /* The specific database being pragmaed */
  Vdbe *v = sqlite3GetVdbe(pParse);  /* Prepared statement */

  if( v==0 ) return;
  sqlite3VdbeRunOnlyOnce(v);
  pParse->nMem = 2;

  /* Interpret the [database.] part of the pragma statement. iDb is the
  ** index of the database this pragma is being applied to in db.aDb[]. */
................................................................................
  ** size.  But continue to take the absolute value of the default cache
  ** size of historical compatibility.
  */
  if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
    static const VdbeOpList getCacheSize[] = {
      { OP_Transaction, 0, 0,        0},                         /* 0 */
      { OP_ReadCookie,  0, 1,        BTREE_DEFAULT_CACHE_SIZE},  /* 1 */
      { OP_IfPos,       1, 8,        0},
      { OP_Integer,     0, 2,        0},
      { OP_Subtract,    1, 2,        1},
      { OP_IfPos,       1, 8,        0},
      { OP_Integer,     0, 1,        0},                         /* 6 */
      { OP_Noop,        0, 0,        0},
      { OP_ResultRow,   1, 1,        0},
    };
    int addr;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    sqlite3VdbeUsesBtree(v, iDb);
    if( !zRight ){
      sqlite3VdbeSetNumCols(v, 1);
................................................................................
    }else{
      int size = sqlite3Atoi(zRight);
      pDb->pSchema->cache_size = size;
      sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
    }
  }else

  /*
  **  PRAGMA [database.]mmap_size(N)
  **
  ** Used to set mapping size limit. The mapping size limit is
  ** used to limit the aggregate size of all memory mapped regions of the
  ** database file. If this parameter is set to zero, then memory mapping
  ** is not used at all.  If N is negative, then the default memory map
  ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set.
  ** The parameter N is measured in bytes.
  **
  ** This value is advisory.  The underlying VFS is free to memory map
  ** as little or as much as it wants.  Except, if N is set to 0 then the
  ** upper layers will never invoke the xFetch interfaces to the VFS.
  */
  if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){
    sqlite3_int64 sz;
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    if( zRight ){
      int ii;
      sqlite3Atoi64(zRight, &sz, 1000, SQLITE_UTF8);
      if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
      if( pId2->n==0 ) db->szMmap = sz;
      for(ii=db->nDb-1; ii>=0; ii--){
        if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
          sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz);
        }
      }
    }
    sz = -1;
    if( sqlite3_file_control(db,zDb,SQLITE_FCNTL_MMAP_SIZE,&sz)==SQLITE_OK ){
#if SQLITE_MAX_MMAP_SIZE==0
      sz = 0;
#endif
      returnSingleInt(pParse, "mmap_size", sz);
    }
  }else

  /*
  **   PRAGMA temp_store
  **   PRAGMA temp_store = "default"|"memory"|"file"
  **
  ** Return or set the local value of the temp_store flag.  Changing
  ** the local value does not make changes to the disk file and the default
  ** value will be restored the next time the database is opened.

Changes to src/prepare.c.

650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
    for(i=iFirst; i<mx; i++){
      sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
                            azColName[i], SQLITE_STATIC);
    }
  }
#endif

  assert( db->init.busy==0 || saveSqlFlag==0 );
  if( db->init.busy==0 ){
    Vdbe *pVdbe = pParse->pVdbe;
    sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
  }
  if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
    sqlite3VdbeFinalize(pParse->pVdbe);
    assert(!(*ppStmt));







<







650
651
652
653
654
655
656

657
658
659
660
661
662
663
    for(i=iFirst; i<mx; i++){
      sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
                            azColName[i], SQLITE_STATIC);
    }
  }
#endif


  if( db->init.busy==0 ){
    Vdbe *pVdbe = pParse->pVdbe;
    sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
  }
  if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
    sqlite3VdbeFinalize(pParse->pVdbe);
    assert(!(*ppStmt));

Changes to src/resolve.c.

384
385
386
387
388
389
390
391



392
393
394
395
396
397
398
...
475
476
477
478
479
480
481

482

483
484
485
486
487
488
489
....
1150
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
    **     SELECT a+b AS x FROM table WHERE x<10;
    **
    ** In cases like this, replace pExpr with a copy of the expression that
    ** forms the result set entry ("a+b" in the example) and return immediately.
    ** Note that the expression in the result set should have already been
    ** resolved by the time the WHERE clause is resolved.
    */
    if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){



      for(j=0; j<pEList->nExpr; j++){
        char *zAs = pEList->a[j].zName;
        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
          Expr *pOrig;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->x.pList==0 );
          assert( pExpr->x.pSelect==0 );
................................................................................
  pExpr->pLeft = 0;
  sqlite3ExprDelete(db, pExpr->pRight);
  pExpr->pRight = 0;
  pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
lookupname_end:
  if( cnt==1 ){
    assert( pNC!=0 );

    sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);

    /* Increment the nRef value on all name contexts from TopNC up to
    ** the point where the name matched. */
    for(;;){
      assert( pTopNC!=0 );
      pTopNC->nRef++;
      if( pTopNC==pNC ) break;
      pTopNC = pTopNC->pNext;
................................................................................
    ** expressions in the WHERE clause (etc.) can refer to expressions by
    ** aliases in the result set.
    **
    ** Minor point: If this is the case, then the expression will be
    ** re-evaluated for each reference to it.
    */
    sNC.pEList = p->pEList;
    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ||

       sqlite3ResolveExprNames(&sNC, p->pHaving)
    ){
      return WRC_Abort;
    }

    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.ncFlags |= NC_AllowAgg;








|
>
>
>







 







>
|
>







 







|
>
|
<
|
<







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
....
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165

1166
1167
1168
1169
1170
1171
1172
    **     SELECT a+b AS x FROM table WHERE x<10;
    **
    ** In cases like this, replace pExpr with a copy of the expression that
    ** forms the result set entry ("a+b" in the example) and return immediately.
    ** Note that the expression in the result set should have already been
    ** resolved by the time the WHERE clause is resolved.
    */
    if( (pEList = pNC->pEList)!=0
     && zTab==0
     && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
    ){
      for(j=0; j<pEList->nExpr; j++){
        char *zAs = pEList->a[j].zName;
        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
          Expr *pOrig;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->x.pList==0 );
          assert( pExpr->x.pSelect==0 );
................................................................................
  pExpr->pLeft = 0;
  sqlite3ExprDelete(db, pExpr->pRight);
  pExpr->pRight = 0;
  pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
lookupname_end:
  if( cnt==1 ){
    assert( pNC!=0 );
    if( pExpr->op!=TK_AS ){
      sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
    }
    /* Increment the nRef value on all name contexts from TopNC up to
    ** the point where the name matched. */
    for(;;){
      assert( pTopNC!=0 );
      pTopNC->nRef++;
      if( pTopNC==pNC ) break;
      pTopNC = pTopNC->pNext;
................................................................................
    ** expressions in the WHERE clause (etc.) can refer to expressions by
    ** aliases in the result set.
    **
    ** Minor point: If this is the case, then the expression will be
    ** re-evaluated for each reference to it.
    */
    sNC.pEList = p->pEList;
    if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
    sNC.ncFlags |= NC_AsMaybe;
    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;

    sNC.ncFlags &= ~NC_AsMaybe;


    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.ncFlags |= NC_AllowAgg;

Changes to src/shell.c.

1547
1548
1549
1550
1551
1552
1553





































1554
1555
1556
1557
1558
1559
1560
....
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
....
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
....
2743
2744
2745
2746
2747
2748
2749




2750
2751
2752
2753
2754
2755
2756
....
2878
2879
2880
2881
2882
2883
2884

2885
2886
2887
2888
2889
2890
2891
....
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
....
3022
3023
3024
3025
3026
3027
3028



3029
3030
3031
3032
3033
3034
3035
....
3107
3108
3109
3110
3111
3112
3113


3114
3115
3116
3117
3118
3119
3120
....
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
....
3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158
3159
3160
3161
  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
    return 0;
  }
  fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
          zArg);
  return 0;
}






































/*
** Close an output file, assuming it is not stderr or stdout
*/
static void output_file_close(FILE *f){
  if( f && f!=stdout && f!=stderr ) fclose(f);
}
................................................................................
            fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
          }
          break;

        /* sqlite3_test_control(int, uint) */
        case SQLITE_TESTCTRL_PENDING_BYTE:        
          if( nArg==3 ){
            unsigned int opt = (unsigned int)atoi(azArg[2]);        
            rc = sqlite3_test_control(testctrl, opt);
            printf("%d (0x%08x)\n", rc, rc);
          } else {
            fprintf(stderr,"Error: testctrl %s takes a single unsigned"
                           " int option\n", azArg[1]);
          }
          break;
................................................................................
      }
    }
  }else

#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
    extern int sqlite3WhereTrace;
    sqlite3WhereTrace = atoi(azArg[1]);
  }else
#endif

  if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
    int j;
    assert( nArg<=ArraySize(azArg) );
    for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
................................................................................
          fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
        }
        errCnt++;
      }
      free(zSql);
      zSql = 0;
      nSql = 0;




    }
  }
  if( zSql ){
    if( !_all_whitespace(zSql) ){
      fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
    }
    free(zSql);
................................................................................
  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
#endif
  "   -help                show this message\n"
  "   -html                set output mode to HTML\n"
  "   -interactive         force interactive I/O\n"
  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"

#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
  "   -separator SEP       set output field separator. Default: '|'\n"
  "   -stats               print memory stats before each finalize\n"
  "   -version             show SQLite version\n"
................................................................................
    }else if( strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      int j, c;
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = atoi(zSize);
      for(j=0; (c = zSize[j])!=0; j++){
        if( c=='M' ){ szHeap *= 1000000; break; }
        if( c=='K' ){ szHeap *= 1000; break; }
        if( c=='G' ){ szHeap *= 1000000000; break; }
      }
      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
................................................................................
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiple_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif



    }else if( strcmp(z,"-vfs")==0 ){
      sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
      if( pVfs ){
        sqlite3_vfs_register(pVfs, 1);
      }else{
        fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
        exit(1);
................................................................................
      return 0;
    }else if( strcmp(z,"-interactive")==0 ){
      stdin_is_interactive = 1;
    }else if( strcmp(z,"-batch")==0 ){
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
      i++;


    }else if( strcmp(z,"-vfs")==0 ){
      i++;
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      i++;
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
................................................................................
    }else if( strcmp(z,"-help")==0 ){
      usage(1);
    }else if( strcmp(z,"-cmd")==0 ){
      if( i==argc-1 ) break;
      z = cmdline_option_value(argc,argv,++i);
      if( z[0]=='.' ){
        rc = do_meta_command(z, &data);
        if( rc && bail_on_error ) return rc;
      }else{
        open_db(&data);
        rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
        if( zErrMsg!=0 ){
          fprintf(stderr,"Error: %s\n", zErrMsg);
          if( bail_on_error ) return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
................................................................................
  }

  if( zFirstCmd ){
    /* Run just the command that follows the database name
    */
    if( zFirstCmd[0]=='.' ){
      rc = do_meta_command(zFirstCmd, &data);

    }else{
      open_db(&data);
      rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg);
      if( zErrMsg!=0 ){
        fprintf(stderr,"Error: %s\n", zErrMsg);
        return rc!=0 ? rc : 1;
      }else if( rc!=0 ){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







>
>
>
>







 







>







 







|
<
<
<
<
<







 







>
>
>







 







>
>







 







|







 







>







1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
....
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
....
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
....
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
....
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
....
3039
3040
3041
3042
3043
3044
3045
3046





3047
3048
3049
3050
3051
3052
3053
....
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
....
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
....
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
....
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
    return 0;
  }
  fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
          zArg);
  return 0;
}

/*
** Interpret zArg as an integer value, possibly with suffixes.
*/
static sqlite3_int64 integerValue(const char *zArg){
  sqlite3_int64 v = 0;
  static const struct { char *zSuffix; int iMult; } aMult[] = {
    { "KiB", 1024 },
    { "MiB", 1024*1024 },
    { "GiB", 1024*1024*1024 },
    { "KB",  1000 },
    { "MB",  1000000 },
    { "GB",  1000000000 },
    { "K",   1000 },
    { "M",   1000000 },
    { "G",   1000000000 },
  };
  int i;
  int isNeg = 0;
  if( zArg[0]=='-' ){
    isNeg = 1;
    zArg++;
  }else if( zArg[0]=='+' ){
    zArg++;
  }
  while( isdigit(zArg[0]) ){
    v = v*10 + zArg[0] - '0';
    zArg++;
  }
  for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
      v *= aMult[i].iMult;
      break;
    }
  }
  return isNeg? -v : v;
}

/*
** Close an output file, assuming it is not stderr or stdout
*/
static void output_file_close(FILE *f){
  if( f && f!=stdout && f!=stderr ) fclose(f);
}
................................................................................
            fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
          }
          break;

        /* sqlite3_test_control(int, uint) */
        case SQLITE_TESTCTRL_PENDING_BYTE:        
          if( nArg==3 ){
            unsigned int opt = (unsigned int)integerValue(azArg[2]);        
            rc = sqlite3_test_control(testctrl, opt);
            printf("%d (0x%08x)\n", rc, rc);
          } else {
            fprintf(stderr,"Error: testctrl %s takes a single unsigned"
                           " int option\n", azArg[1]);
          }
          break;
................................................................................
      }
    }
  }else

#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
    extern int sqlite3WhereTrace;
    sqlite3WhereTrace = booleanValue(azArg[1]);
  }else
#endif

  if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
    int j;
    assert( nArg<=ArraySize(azArg) );
    for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
................................................................................
          fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
        }
        errCnt++;
      }
      free(zSql);
      zSql = 0;
      nSql = 0;
    }else if( zSql && _all_whitespace(zSql) ){
      free(zSql);
      zSql = 0;
      nSql = 0;
    }
  }
  if( zSql ){
    if( !_all_whitespace(zSql) ){
      fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
    }
    free(zSql);
................................................................................
  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
#endif
  "   -help                show this message\n"
  "   -html                set output mode to HTML\n"
  "   -interactive         force interactive I/O\n"
  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"
  "   -mmap N              default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
  "   -separator SEP       set output field separator. Default: '|'\n"
  "   -stats               print memory stats before each finalize\n"
  "   -version             show SQLite version\n"
................................................................................
    }else if( strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      int j, c;
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = integerValue(zSize);





      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
................................................................................
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiple_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif
    }else if( strcmp(z,"-mmap")==0 ){
      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
      sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
    }else if( strcmp(z,"-vfs")==0 ){
      sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
      if( pVfs ){
        sqlite3_vfs_register(pVfs, 1);
      }else{
        fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
        exit(1);
................................................................................
      return 0;
    }else if( strcmp(z,"-interactive")==0 ){
      stdin_is_interactive = 1;
    }else if( strcmp(z,"-batch")==0 ){
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
      i++;
    }else if( strcmp(z,"-mmap")==0 ){
      i++;
    }else if( strcmp(z,"-vfs")==0 ){
      i++;
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
      i++;
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
................................................................................
    }else if( strcmp(z,"-help")==0 ){
      usage(1);
    }else if( strcmp(z,"-cmd")==0 ){
      if( i==argc-1 ) break;
      z = cmdline_option_value(argc,argv,++i);
      if( z[0]=='.' ){
        rc = do_meta_command(z, &data);
        if( rc && bail_on_error ) return rc==2 ? 0 : rc;
      }else{
        open_db(&data);
        rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
        if( zErrMsg!=0 ){
          fprintf(stderr,"Error: %s\n", zErrMsg);
          if( bail_on_error ) return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
................................................................................
  }

  if( zFirstCmd ){
    /* Run just the command that follows the database name
    */
    if( zFirstCmd[0]=='.' ){
      rc = do_meta_command(zFirstCmd, &data);
      if( rc==2 ) rc = 0;
    }else{
      open_db(&data);
      rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg);
      if( zErrMsg!=0 ){
        fprintf(stderr,"Error: %s\n", zErrMsg);
        return rc!=0 ? rc : 1;
      }else if( rc!=0 ){

Changes to src/sqlite.h.in.

416
417
418
419
420
421
422


423
424
425
426
427
428
429
...
466
467
468
469
470
471
472

473
474
475
476
477
478
479
...
485
486
487
488
489
490
491


492
493
494
495
496
497
498
...
724
725
726
727
728
729
730



731
732
733
734
735
736
737
...
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876
877

878
879
880
881
882
883
884










885
886
887
888
889
890
891
...
896
897
898
899
900
901
902

903
904
905
906
907
908
909
....
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
















1631
1632
1633
1634
1635
1636
1637
....
1647
1648
1649
1650
1651
1652
1653

1654
1655
1656
1657
1658
1659
1660
....
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
....
4977
4978
4979
4980
4981
4982
4983
4984





4985
4986
4987
4988




4989
4990
4991
4992
4993
4994
4995
....
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
....
6803
6804
6805
6806
6807
6808
6809















6810
6811
6812
6813
6814
6815
6816
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_FORMAT      24   /* Auxiliary database format error */
#define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB      26   /* File opened that is not a database file */


#define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
/* end-of-error-codes */

/*
** CAPI3REF: Extended Result Codes
** KEYWORDS: {extended error code} {extended error codes}
................................................................................
#define SQLITE_IOERR_DIR_CLOSE         (SQLITE_IOERR | (17<<8))
#define SQLITE_IOERR_SHMOPEN           (SQLITE_IOERR | (18<<8))
#define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))

#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
................................................................................
#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))



/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
................................................................................
  int (*xDeviceCharacteristics)(sqlite3_file*);
  /* Methods above are valid for version 1 */
  int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
  int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
  void (*xShmBarrier)(sqlite3_file*);
  int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
  /* Methods above are valid for version 2 */



  /* Additional methods may be added in future releases */
};

/*
** CAPI3REF: Standard File Control Opcodes
**
** These integer constants are opcodes for the xFileControl method
................................................................................
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
** that the VFS encountered an error while handling the [PRAGMA] and the
** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
** file control occurs at the beginning of pragma statement analysis and so
** it is able to override built-in [PRAGMA] statements.
**
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]

** ^This file-control may be invoked by SQLite on the database file handle
** shortly after it is opened in order to provide a custom VFS with access
** to the connections busy-handler callback. The argument is of type (void **)
** - an array of two (void *) values. The first (void *) actually points
** to a function of type (int (*)(void *)). In order to invoke the connections
** busy-handler, this function should be invoked with the second (void *) in
** the array as the only argument. If it returns non-zero, then the operation
** should be retried. If it returns zero, the custom VFS should abandon the
** current operation.
**
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]

** ^Application can invoke this file-control to have SQLite generate a
** temporary filename using the same algorithm that is followed to generate
** temporary filenames for TEMP tables and other internal uses.  The
** argument should be a char** which will be filled with the filename
** written into memory obtained from [sqlite3_malloc()].  The caller should
** invoke [sqlite3_free()] on the result to avoid a memory leak.
**










** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_GET_LOCKPROXYFILE             2
#define SQLITE_SET_LOCKPROXYFILE             3
#define SQLITE_LAST_ERRNO                    4
#define SQLITE_FCNTL_SIZE_HINT               5
................................................................................
#define SQLITE_FCNTL_PERSIST_WAL            10
#define SQLITE_FCNTL_OVERWRITE              11
#define SQLITE_FCNTL_VFSNAME                12
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
#define SQLITE_FCNTL_PRAGMA                 14
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16


/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only
................................................................................
** disable the optimization allows the older, buggy application code to work
** without change even with newer versions of SQLite.
**
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
** <dd> These options are obsolete and should not be used by new code.
** They are retained for backwards compatibility but are now no-ops.
** </dl>
**
** [[SQLITE_CONFIG_SQLLOG]]
** <dt>SQLITE_CONFIG_SQLLOG
** <dd>This option is only available if sqlite is compiled with the
** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
** The second should be of type (void*). The callback is invoked by the library
** in three separate circumstances, identified by the value passed as the
** fourth parameter. If the fourth parameter is 0, then the database connection
** passed as the second argument has just been opened. The third argument
** points to a buffer containing the name of the main database file. If the
** fourth parameter is 1, then the SQL statement that the third parameter
** points to has just been executed. Or, if the fourth parameter is 2, then
** the connection being passed as the second parameter is being closed. The
** third parameter is passed NULL In this case.
















** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
................................................................................
#define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
#define SQLITE_CONFIG_URI          17  /* int */
#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */


/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
................................................................................
** argument is SQLITE_STATIC, it means that the content pointer is constant
** and will never change.  It does not need to be destroyed.  ^The
** SQLITE_TRANSIENT value means that the content will likely change in
** the near future and that SQLite should make its own private copy of
** the content before returning.
**
** The typedef is necessary to work around problems in certain
** C++ compilers.  See ticket #2191.
*/
typedef void (*sqlite3_destructor_type)(void*);
#define SQLITE_STATIC      ((sqlite3_destructor_type)0)
#define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)

/*
** CAPI3REF: Setting The Result Of An SQL Function
................................................................................

/*
** CAPI3REF: Load An Extension
**
** ^This interface loads an SQLite extension library from the named file.
**
** ^The sqlite3_load_extension() interface attempts to load an
** SQLite extension library contained in the file zFile.





**
** ^The entry point is zProc.
** ^zProc may be 0, in which case the name of the entry point
** defaults to "sqlite3_extension_init".




** ^The sqlite3_load_extension() interface returns
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
** ^If an error occurs and pzErrMsg is not 0, then the
** [sqlite3_load_extension()] interface shall attempt to
** fill *pzErrMsg with error message text stored in memory
** obtained from [sqlite3_malloc()]. The calling function
** should free this memory by calling [sqlite3_free()].
................................................................................
  char **pzErrMsg       /* Put error message here if not 0 */
);

/*
** CAPI3REF: Enable Or Disable Extension Loading
**
** ^So as not to open security holes in older applications that are
** unprepared to deal with extension loading, and as a means of disabling
** extension loading while evaluating user-entered SQL, the following API
** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
**
** ^Extension loading is off by default. See ticket #1863.
** ^Call the sqlite3_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
*/
int sqlite3_enable_load_extension(sqlite3 *db, int onoff);

/*
** CAPI3REF: Automatically Load Statically Linked Extensions
**
** ^This interface causes the xEntryPoint() function to be invoked for
** each new [database connection] that is created.  The idea here is that
** xEntryPoint() is the entry point for a statically linked SQLite extension
** that is to be automatically loaded into all new database connections.
**
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects and integer result as if the signature of the
** entry point where as follows:
**
................................................................................
** and extensions to compare the contents of two buffers containing UTF-8
** strings in a case-independent fashion, using the same definition of "case
** independence" that SQLite uses internally when comparing identifiers.
*/
int sqlite3_stricmp(const char *, const char *);
int sqlite3_strnicmp(const char *, const char *, int);
















/*
** CAPI3REF: Error Logging Interface
**
** ^The [sqlite3_log()] interface writes a message into the error log
** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
** ^If logging is enabled, the zFormat string and subsequent arguments are
** used with [sqlite3_snprintf()] to generate the final output string.







>
>







 







>







 







>
>







 







>
>
>







 







>
|










>
|






>
>
>
>
>
>
>
>
>
>







 







>







 







|




|









|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







|







 







|
>
>
>
>
>


|
|
>
>
>
>







 







|
|


|











|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
...
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
...
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
....
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
....
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
....
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
....
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
....
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
....
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_FORMAT      24   /* Auxiliary database format error */
#define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB      26   /* File opened that is not a database file */
#define SQLITE_NOTICE      27   /* Notifications from sqlite3_log() */
#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
#define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
/* end-of-error-codes */

/*
** CAPI3REF: Extended Result Codes
** KEYWORDS: {extended error code} {extended error codes}
................................................................................
#define SQLITE_IOERR_DIR_CLOSE         (SQLITE_IOERR | (17<<8))
#define SQLITE_IOERR_SHMOPEN           (SQLITE_IOERR | (18<<8))
#define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
#define SQLITE_IOERR_MMAP              (SQLITE_IOERR | (24<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
................................................................................
#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
................................................................................
  int (*xDeviceCharacteristics)(sqlite3_file*);
  /* Methods above are valid for version 1 */
  int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
  int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
  void (*xShmBarrier)(sqlite3_file*);
  int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
  /* Methods above are valid for version 2 */
  int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
  /* Methods above are valid for version 3 */
  /* Additional methods may be added in future releases */
};

/*
** CAPI3REF: Standard File Control Opcodes
**
** These integer constants are opcodes for the xFileControl method
................................................................................
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
** that the VFS encountered an error while handling the [PRAGMA] and the
** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
** file control occurs at the beginning of pragma statement analysis and so
** it is able to override built-in [PRAGMA] statements.
**
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
** ^The [SQLITE_FCNTL_BUSYHANDLER]
** file-control may be invoked by SQLite on the database file handle
** shortly after it is opened in order to provide a custom VFS with access
** to the connections busy-handler callback. The argument is of type (void **)
** - an array of two (void *) values. The first (void *) actually points
** to a function of type (int (*)(void *)). In order to invoke the connections
** busy-handler, this function should be invoked with the second (void *) in
** the array as the only argument. If it returns non-zero, then the operation
** should be retried. If it returns zero, the custom VFS should abandon the
** current operation.
**
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
** to have SQLite generate a
** temporary filename using the same algorithm that is followed to generate
** temporary filenames for TEMP tables and other internal uses.  The
** argument should be a char** which will be filled with the filename
** written into memory obtained from [sqlite3_malloc()].  The caller should
** invoke [sqlite3_free()] on the result to avoid a memory leak.
**
** <li>[[SQLITE_FCNTL_MMAP_SIZE]]
** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the
** maximum number of bytes that will be used for memory-mapped I/O.
** The argument is a pointer to a value of type sqlite3_int64 that
** is an advisory maximum number of bytes in the file to memory map.  The
** pointer is overwritten with the old value.  The limit is not changed if
** the value originally pointed to is negative, and so the current limit 
** can be queried by passing in a pointer to a negative number.  This
** file-control is used internally to implement [PRAGMA mmap_size].
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_GET_LOCKPROXYFILE             2
#define SQLITE_SET_LOCKPROXYFILE             3
#define SQLITE_LAST_ERRNO                    4
#define SQLITE_FCNTL_SIZE_HINT               5
................................................................................
#define SQLITE_FCNTL_PERSIST_WAL            10
#define SQLITE_FCNTL_OVERWRITE              11
#define SQLITE_FCNTL_VFSNAME                12
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
#define SQLITE_FCNTL_PRAGMA                 14
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16
#define SQLITE_FCNTL_MMAP_SIZE              18

/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only
................................................................................
** disable the optimization allows the older, buggy application code to work
** without change even with newer versions of SQLite.
**
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
** <dd> These options are obsolete and should not be used by new code.
** They are retained for backwards compatibility but are now no-ops.
** </dd>
**
** [[SQLITE_CONFIG_SQLLOG]]
** <dt>SQLITE_CONFIG_SQLLOG
** <dd>This option is only available if sqlite is compiled with the
** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should
** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
** The second should be of type (void*). The callback is invoked by the library
** in three separate circumstances, identified by the value passed as the
** fourth parameter. If the fourth parameter is 0, then the database connection
** passed as the second argument has just been opened. The third argument
** points to a buffer containing the name of the main database file. If the
** fourth parameter is 1, then the SQL statement that the third parameter
** points to has just been executed. Or, if the fourth parameter is 2, then
** the connection being passed as the second parameter is being closed. The
** third parameter is passed NULL In this case.  An example of using this
** configuration option can be seen in the "test_sqllog.c" source file in
** the canonical SQLite source tree.</dd>
**
** [[SQLITE_CONFIG_MMAP_SIZE]]
** <dt>SQLITE_CONFIG_MMAP_SIZE
** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
** that are the default mmap size limit (the default setting for
** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
** The default setting can be overridden by each database connection using
** either the [PRAGMA mmap_size] command, or by using the
** [SQLITE_FCNTL_MMAP_SIZE] file control.  The maximum allowed mmap size
** cannot be changed at run-time.  Nor may the maximum allowed mmap size
** exceed the compile-time maximum mmap size set by the
** [SQLITE_MAX_MMAP_SIZE] compile-time option.  
** If either argument to this option is negative, then that argument is
** changed to its compile-time default.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
................................................................................
#define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
#define SQLITE_CONFIG_URI          17  /* int */
#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
#define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */

/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
................................................................................
** argument is SQLITE_STATIC, it means that the content pointer is constant
** and will never change.  It does not need to be destroyed.  ^The
** SQLITE_TRANSIENT value means that the content will likely change in
** the near future and that SQLite should make its own private copy of
** the content before returning.
**
** The typedef is necessary to work around problems in certain
** C++ compilers.
*/
typedef void (*sqlite3_destructor_type)(void*);
#define SQLITE_STATIC      ((sqlite3_destructor_type)0)
#define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)

/*
** CAPI3REF: Setting The Result Of An SQL Function
................................................................................

/*
** CAPI3REF: Load An Extension
**
** ^This interface loads an SQLite extension library from the named file.
**
** ^The sqlite3_load_extension() interface attempts to load an
** [SQLite extension] library contained in the file zFile.  If
** the file cannot be loaded directly, attempts are made to load
** with various operating-system specific extensions added.
** So for example, if "samplelib" cannot be loaded, then names like
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
** be tried also.
**
** ^The entry point is zProc.
** ^(zProc may be 0, in which case SQLite will try to come up with an
** entry point name on its own.  It first tries "sqlite3_extension_init".
** If that does not work, it constructs a name "sqlite3_X_init" where the
** X is consists of the lower-case equivalent of all ASCII alphabetic
** characters in the filename from the last "/" to the first following
** "." and omitting any initial "lib".)^
** ^The sqlite3_load_extension() interface returns
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
** ^If an error occurs and pzErrMsg is not 0, then the
** [sqlite3_load_extension()] interface shall attempt to
** fill *pzErrMsg with error message text stored in memory
** obtained from [sqlite3_malloc()]. The calling function
** should free this memory by calling [sqlite3_free()].
................................................................................
  char **pzErrMsg       /* Put error message here if not 0 */
);

/*
** CAPI3REF: Enable Or Disable Extension Loading
**
** ^So as not to open security holes in older applications that are
** unprepared to deal with [extension loading], and as a means of disabling
** [extension loading] while evaluating user-entered SQL, the following API
** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
**
** ^Extension loading is off by default.
** ^Call the sqlite3_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
*/
int sqlite3_enable_load_extension(sqlite3 *db, int onoff);

/*
** CAPI3REF: Automatically Load Statically Linked Extensions
**
** ^This interface causes the xEntryPoint() function to be invoked for
** each new [database connection] that is created.  The idea here is that
** xEntryPoint() is the entry point for a statically linked [SQLite extension]
** that is to be automatically loaded into all new database connections.
**
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects and integer result as if the signature of the
** entry point where as follows:
**
................................................................................
** and extensions to compare the contents of two buffers containing UTF-8
** strings in a case-independent fashion, using the same definition of "case
** independence" that SQLite uses internally when comparing identifiers.
*/
int sqlite3_stricmp(const char *, const char *);
int sqlite3_strnicmp(const char *, const char *, int);

/*
** CAPI3REF: String Globbing
*
** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches
** the glob pattern P, and it returns non-zero if string X does not match
** the glob pattern P.  ^The definition of glob pattern matching used in
** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
** SQL dialect used by SQLite.  ^The sqlite3_strglob(P,X) function is case
** sensitive.
**
** Note that this routine returns zero on a match and non-zero if the strings
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
*/
int sqlite3_strglob(const char *zGlob, const char *zStr);

/*
** CAPI3REF: Error Logging Interface
**
** ^The [sqlite3_log()] interface writes a message into the error log
** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
** ^If logging is enabled, the zFormat string and subsequent arguments are
** used with [sqlite3_snprintf()] to generate the final output string.

Changes to src/sqlite3ext.h.

465
466
467
468
469
470
471



472
473






474
475
#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
#define sqlite3_uri_int64              sqlite3_api->uri_int64
#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
#endif /* SQLITE_CORE */




#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
#define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;







#endif /* _SQLITE3EXT_H_ */







>
>
>
|
|
>
>
>
>
>
>


465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
#define sqlite3_uri_int64              sqlite3_api->uri_int64
#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
#endif /* SQLITE_CORE */

#ifndef SQLITE_CORE
  /* This case when the file really is being compiled as a loadable 
  ** extension */
# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
#else
  /* This case when the file is being statically linked into the 
  ** application */
# define SQLITE_EXTENSION_INIT1     /*no-op*/
# define SQLITE_EXTENSION_INIT2(v)  (void)v; /* unused parameter */
#endif

#endif /* _SQLITE3EXT_H_ */

Changes to src/sqliteInt.h.

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
...
388
389
390
391
392
393
394

395
396
397
398
399
400
401
...
535
536
537
538
539
540
541











































542
543
544
545
546
547
548
...
831
832
833
834
835
836
837

838
839
840
841
842
843
844
....
2074
2075
2076
2077
2078
2079
2080


2081
2082
2083
2084
2085
2086
2087
....
2513
2514
2515
2516
2517
2518
2519


2520
2521
2522
2523
2524
2525
2526
** threads can use SQLite as long as no two threads try to use the same
** database connection at the same time.
**
** Older versions of SQLite used an optional THREADSAFE macro.
** We support that for legacy.
*/
#if !defined(SQLITE_THREADSAFE)
#if defined(THREADSAFE)
# define SQLITE_THREADSAFE THREADSAFE
#else
# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
#endif
#endif

/*
** Powersafe overwrite is on by default.  But can be turned off using
** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
*/
#ifndef SQLITE_POWERSAFE_OVERWRITE
................................................................................

/*
** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
** on the command-line
*/
#ifndef SQLITE_TEMP_STORE
# define SQLITE_TEMP_STORE 1

#endif

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/
#ifndef offsetof
................................................................................
*/
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&3)==0)
#else
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&7)==0)
#endif













































/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle. 
**
** The sqlite.busyHandler member of the sqlite struct contains the busy
** callback for the database handle. Each pager opened via the sqlite
................................................................................
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
  sqlite3_mutex *mutex;         /* Connection mutex */
  Db *aDb;                      /* All backends */
  int nDb;                      /* Number of backends currently in use */
  int flags;                    /* Miscellaneous flags. See below */
  i64 lastRowid;                /* ROWID of most recent insert (see above) */

  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errMask;                  /* & result codes with this before returning */
  u16 dbOptFlags;               /* Flags to enable/disable optimizations */
  u8 autoCommit;                /* The auto-commit flag. */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
................................................................................
/*
** Allowed values for the NameContext, ncFlags field.
*/
#define NC_AllowAgg  0x01    /* Aggregate functions are allowed here */
#define NC_HasAgg    0x02    /* One or more aggregate functions seen */
#define NC_IsCheck   0x04    /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x08    /* True if analyzing arguments to an agg func */



/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
................................................................................
  int nLookaside;                   /* Default lookaside buffer count */
  sqlite3_mem_methods m;            /* Low-level memory allocation interface */
  sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
  sqlite3_pcache_methods2 pcache2;  /* Low-level page-cache interface */
  void *pHeap;                      /* Heap storage space */
  int nHeap;                        /* Size of pHeap[] */
  int mnReq, mxReq;                 /* Min and max heap requests sizes */


  void *pScratch;                   /* Scratch memory */
  int szScratch;                    /* Size of each scratch buffer */
  int nScratch;                     /* Number of scratch buffers */
  void *pPage;                      /* Page cache memory */
  int szPage;                       /* Size of each page in pPage[] */
  int nPage;                        /* Number of pages in pPage[] */
  int mxParserStack;                /* maximum depth of the parser stack */







|
|
|
|
|







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>
>







 







>
>







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
...
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
...
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
....
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
....
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
** threads can use SQLite as long as no two threads try to use the same
** database connection at the same time.
**
** Older versions of SQLite used an optional THREADSAFE macro.
** We support that for legacy.
*/
#if !defined(SQLITE_THREADSAFE)
# if defined(THREADSAFE)
#   define SQLITE_THREADSAFE THREADSAFE
# else
#   define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
# endif
#endif

/*
** Powersafe overwrite is on by default.  But can be turned off using
** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
*/
#ifndef SQLITE_POWERSAFE_OVERWRITE
................................................................................

/*
** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
** on the command-line
*/
#ifndef SQLITE_TEMP_STORE
# define SQLITE_TEMP_STORE 1
# define SQLITE_TEMP_STORE_xc 1  /* Exclude from ctime.c */
#endif

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/
#ifndef offsetof
................................................................................
*/
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&3)==0)
#else
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&7)==0)
#endif

/*
** Disable MMAP on platforms where it is known to not work
*/
#if defined(__OpenBSD__) || defined(__QNXNTO__)
# undef SQLITE_MAX_MMAP_SIZE
# define SQLITE_MAX_MMAP_SIZE 0
#endif

/*
** Default maximum size of memory used by memory-mapped I/O in the VFS
*/
#ifdef __APPLE__
# include <TargetConditionals.h>
# if TARGET_OS_IPHONE
#   undef SQLITE_MAX_MMAP_SIZE
#   define SQLITE_MAX_MMAP_SIZE 0
# endif
#endif
#ifndef SQLITE_MAX_MMAP_SIZE
# if defined(__linux__) \
  || defined(_WIN32) \
  || (defined(__APPLE__) && defined(__MACH__)) \
  || defined(__sun)
#   define SQLITE_MAX_MMAP_SIZE 2147483648
# else
#   define SQLITE_MAX_MMAP_SIZE 0
# endif
# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
#endif

/*
** The default MMAP_SIZE is zero on all platforms.  Or, even if a larger
** default MMAP_SIZE is specified at compile-time, make sure that it does
** not exceed the maximum mmap size.
*/
#ifndef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE 0
# define SQLITE_DEFAULT_MMAP_SIZE_xc 1  /* Exclude from ctime.c */
#endif
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
# undef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
#endif

/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle. 
**
** The sqlite.busyHandler member of the sqlite struct contains the busy
** callback for the database handle. Each pager opened via the sqlite
................................................................................
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
  sqlite3_mutex *mutex;         /* Connection mutex */
  Db *aDb;                      /* All backends */
  int nDb;                      /* Number of backends currently in use */
  int flags;                    /* Miscellaneous flags. See below */
  i64 lastRowid;                /* ROWID of most recent insert (see above) */
  i64 szMmap;                   /* Default mmap_size setting */
  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errMask;                  /* & result codes with this before returning */
  u16 dbOptFlags;               /* Flags to enable/disable optimizations */
  u8 autoCommit;                /* The auto-commit flag. */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
................................................................................
/*
** Allowed values for the NameContext, ncFlags field.
*/
#define NC_AllowAgg  0x01    /* Aggregate functions are allowed here */
#define NC_HasAgg    0x02    /* One or more aggregate functions seen */
#define NC_IsCheck   0x04    /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x08    /* True if analyzing arguments to an agg func */
#define NC_AsMaybe   0x10    /* Resolve to AS terms of the result set only
                             ** if no other resolution is available */

/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
................................................................................
  int nLookaside;                   /* Default lookaside buffer count */
  sqlite3_mem_methods m;            /* Low-level memory allocation interface */
  sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
  sqlite3_pcache_methods2 pcache2;  /* Low-level page-cache interface */
  void *pHeap;                      /* Heap storage space */
  int nHeap;                        /* Size of pHeap[] */
  int mnReq, mxReq;                 /* Min and max heap requests sizes */
  sqlite3_int64 szMmap;             /* mmap() space per open file */
  sqlite3_int64 mxMmap;             /* Maximum value for szMmap */
  void *pScratch;                   /* Scratch memory */
  int szScratch;                    /* Size of each scratch buffer */
  int nScratch;                     /* Number of scratch buffers */
  void *pPage;                      /* Page cache memory */
  int szPage;                       /* Size of each page in pPage[] */
  int nPage;                        /* Number of pages in pPage[] */
  int mxParserStack;                /* maximum depth of the parser stack */

Changes to src/test1.c.

112
113
114
115
116
117
118


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183


184
185
186
187
188
189
190
....
5839
5840
5841
5842
5843
5844
5845

























5846
5847
5848
5849
5850
5851
5852
....
6229
6230
6231
6232
6233
6234
6235



6236
6237
6238
6239
6240
6241
6242
  }
  return TCL_OK;
}


const char *sqlite3TestErrorName(int rc){
  const char *zName = 0;


  switch( rc ){
    case SQLITE_OK:                  zName = "SQLITE_OK";                break;
    case SQLITE_ERROR:               zName = "SQLITE_ERROR";             break;
    case SQLITE_INTERNAL:            zName = "SQLITE_INTERNAL";          break;
    case SQLITE_PERM:                zName = "SQLITE_PERM";              break;
    case SQLITE_ABORT:               zName = "SQLITE_ABORT";             break;
    case SQLITE_BUSY:                zName = "SQLITE_BUSY";              break;
    case SQLITE_LOCKED:              zName = "SQLITE_LOCKED";            break;
    case SQLITE_LOCKED_SHAREDCACHE:  zName = "SQLITE_LOCKED_SHAREDCACHE";break;
    case SQLITE_NOMEM:               zName = "SQLITE_NOMEM";             break;
    case SQLITE_READONLY:            zName = "SQLITE_READONLY";          break;
    case SQLITE_INTERRUPT:           zName = "SQLITE_INTERRUPT";         break;
    case SQLITE_IOERR:               zName = "SQLITE_IOERR";             break;
    case SQLITE_CORRUPT:             zName = "SQLITE_CORRUPT";           break;
    case SQLITE_NOTFOUND:            zName = "SQLITE_NOTFOUND";          break;
    case SQLITE_FULL:                zName = "SQLITE_FULL";              break;
    case SQLITE_CANTOPEN:            zName = "SQLITE_CANTOPEN";          break;
    case SQLITE_PROTOCOL:            zName = "SQLITE_PROTOCOL";          break;
    case SQLITE_EMPTY:               zName = "SQLITE_EMPTY";             break;
    case SQLITE_SCHEMA:              zName = "SQLITE_SCHEMA";            break;
    case SQLITE_TOOBIG:              zName = "SQLITE_TOOBIG";            break;
    case SQLITE_CONSTRAINT:          zName = "SQLITE_CONSTRAINT";        break;
    case SQLITE_CONSTRAINT_UNIQUE:   zName = "SQLITE_CONSTRAINT_UNIQUE"; break;
    case SQLITE_CONSTRAINT_TRIGGER:  zName = "SQLITE_CONSTRAINT_TRIGGER";break;
    case SQLITE_CONSTRAINT_FOREIGNKEY:
                                 zName = "SQLITE_CONSTRAINT_FOREIGNKEY"; break;
    case SQLITE_CONSTRAINT_CHECK:    zName = "SQLITE_CONSTRAINT_CHECK";  break;
    case SQLITE_CONSTRAINT_PRIMARYKEY:
                                 zName = "SQLITE_CONSTRAINT_PRIMARYKEY"; break;
    case SQLITE_CONSTRAINT_NOTNULL:  zName = "SQLITE_CONSTRAINT_NOTNULL";break;
    case SQLITE_CONSTRAINT_COMMITHOOK:
                                 zName = "SQLITE_CONSTRAINT_COMMITHOOK"; break;
    case SQLITE_CONSTRAINT_VTAB:     zName = "SQLITE_CONSTRAINT_VTAB";   break;
    case SQLITE_CONSTRAINT_FUNCTION: zName = "SQLITE_CONSTRAINT_FUNCTION";break;
    case SQLITE_MISMATCH:            zName = "SQLITE_MISMATCH";          break;
    case SQLITE_MISUSE:              zName = "SQLITE_MISUSE";            break;
    case SQLITE_NOLFS:               zName = "SQLITE_NOLFS";             break;
    case SQLITE_AUTH:                zName = "SQLITE_AUTH";              break;
    case SQLITE_FORMAT:              zName = "SQLITE_FORMAT";            break;
    case SQLITE_RANGE:               zName = "SQLITE_RANGE";             break;
    case SQLITE_NOTADB:              zName = "SQLITE_NOTADB";            break;
    case SQLITE_ROW:                 zName = "SQLITE_ROW";               break;


    case SQLITE_DONE:                zName = "SQLITE_DONE";              break;
    case SQLITE_IOERR_READ:          zName = "SQLITE_IOERR_READ";        break;
    case SQLITE_IOERR_SHORT_READ:    zName = "SQLITE_IOERR_SHORT_READ";  break;
    case SQLITE_IOERR_WRITE:         zName = "SQLITE_IOERR_WRITE";       break;
    case SQLITE_IOERR_FSYNC:         zName = "SQLITE_IOERR_FSYNC";       break;
    case SQLITE_IOERR_DIR_FSYNC:     zName = "SQLITE_IOERR_DIR_FSYNC";   break;
    case SQLITE_IOERR_TRUNCATE:      zName = "SQLITE_IOERR_TRUNCATE";    break;
    case SQLITE_IOERR_FSTAT:         zName = "SQLITE_IOERR_FSTAT";       break;
    case SQLITE_IOERR_UNLOCK:        zName = "SQLITE_IOERR_UNLOCK";      break;
    case SQLITE_IOERR_RDLOCK:        zName = "SQLITE_IOERR_RDLOCK";      break;
    case SQLITE_IOERR_DELETE:        zName = "SQLITE_IOERR_DELETE";      break;
    case SQLITE_IOERR_BLOCKED:       zName = "SQLITE_IOERR_BLOCKED";     break;
    case SQLITE_IOERR_NOMEM:         zName = "SQLITE_IOERR_NOMEM";       break;
    case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
    case SQLITE_IOERR_CHECKRESERVEDLOCK:
                               zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;
    case SQLITE_CORRUPT_VTAB:        zName = "SQLITE_CORRUPT_VTAB";      break;
    case SQLITE_READONLY_RECOVERY:   zName = "SQLITE_READONLY_RECOVERY"; break;
    case SQLITE_READONLY_CANTLOCK:   zName = "SQLITE_READONLY_CANTLOCK"; break;
    case SQLITE_READONLY_ROLLBACK:   zName = "SQLITE_READONLY_ROLLBACK"; break;
    default:                         zName = "SQLITE_Unknown";           break;
  }


  return zName;
}
#define t1ErrorName sqlite3TestErrorName

/*
** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
** fact that the sqlite3* is the first field in the Vdbe structure.
................................................................................
      break;
    }
  }

  Tcl_ResetResult(interp);
  return TCL_OK;
}


























#if SQLITE_OS_WIN
/*
** Information passed from the main thread into the windows file locker
** background thread.
*/
struct win32FileLocker {
................................................................................
     { "sqlite3_wal_checkpoint",   test_wal_checkpoint, 0  },
     { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0  },
     { "test_sqlite3_log",         test_sqlite3_log, 0  },
#ifndef SQLITE_OMIT_EXPLAIN
     { "print_explain_query_plan", test_print_eqp, 0  },
#endif
     { "sqlite3_test_control", test_test_control },



  };
  static int bitmask_size = sizeof(Bitmask)*8;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
  extern int sqlite3_xferopt_count;







>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
....
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
....
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
  }
  return TCL_OK;
}


const char *sqlite3TestErrorName(int rc){
  const char *zName = 0;
  int i;
  for(i=0; i<2 && zName==0; i++, rc &= 0xff){
    switch( rc ){
      case SQLITE_OK:                  zName = "SQLITE_OK";                break;
      case SQLITE_ERROR:               zName = "SQLITE_ERROR";             break;
      case SQLITE_INTERNAL:            zName = "SQLITE_INTERNAL";          break;
      case SQLITE_PERM:                zName = "SQLITE_PERM";              break;
      case SQLITE_ABORT:               zName = "SQLITE_ABORT";             break;
      case SQLITE_BUSY:                zName = "SQLITE_BUSY";              break;
      case SQLITE_LOCKED:              zName = "SQLITE_LOCKED";            break;
      case SQLITE_LOCKED_SHAREDCACHE:  zName = "SQLITE_LOCKED_SHAREDCACHE";break;
      case SQLITE_NOMEM:               zName = "SQLITE_NOMEM";             break;
      case SQLITE_READONLY:            zName = "SQLITE_READONLY";          break;
      case SQLITE_INTERRUPT:           zName = "SQLITE_INTERRUPT";         break;
      case SQLITE_IOERR:               zName = "SQLITE_IOERR";             break;
      case SQLITE_CORRUPT:             zName = "SQLITE_CORRUPT";           break;
      case SQLITE_NOTFOUND:            zName = "SQLITE_NOTFOUND";          break;
      case SQLITE_FULL:                zName = "SQLITE_FULL";              break;
      case SQLITE_CANTOPEN:            zName = "SQLITE_CANTOPEN";          break;
      case SQLITE_PROTOCOL:            zName = "SQLITE_PROTOCOL";          break;
      case SQLITE_EMPTY:               zName = "SQLITE_EMPTY";             break;
      case SQLITE_SCHEMA:              zName = "SQLITE_SCHEMA";            break;
      case SQLITE_TOOBIG:              zName = "SQLITE_TOOBIG";            break;
      case SQLITE_CONSTRAINT:          zName = "SQLITE_CONSTRAINT";        break;
      case SQLITE_CONSTRAINT_UNIQUE:   zName = "SQLITE_CONSTRAINT_UNIQUE"; break;
      case SQLITE_CONSTRAINT_TRIGGER:  zName = "SQLITE_CONSTRAINT_TRIGGER";break;
      case SQLITE_CONSTRAINT_FOREIGNKEY:
                                   zName = "SQLITE_CONSTRAINT_FOREIGNKEY"; break;
      case SQLITE_CONSTRAINT_CHECK:    zName = "SQLITE_CONSTRAINT_CHECK";  break;
      case SQLITE_CONSTRAINT_PRIMARYKEY:
                                   zName = "SQLITE_CONSTRAINT_PRIMARYKEY"; break;
      case SQLITE_CONSTRAINT_NOTNULL:  zName = "SQLITE_CONSTRAINT_NOTNULL";break;
      case SQLITE_CONSTRAINT_COMMITHOOK:
                                   zName = "SQLITE_CONSTRAINT_COMMITHOOK"; break;
      case SQLITE_CONSTRAINT_VTAB:     zName = "SQLITE_CONSTRAINT_VTAB";   break;
      case SQLITE_CONSTRAINT_FUNCTION: zName = "SQLITE_CONSTRAINT_FUNCTION";break;
      case SQLITE_MISMATCH:            zName = "SQLITE_MISMATCH";          break;
      case SQLITE_MISUSE:              zName = "SQLITE_MISUSE";            break;
      case SQLITE_NOLFS:               zName = "SQLITE_NOLFS";             break;
      case SQLITE_AUTH:                zName = "SQLITE_AUTH";              break;
      case SQLITE_FORMAT:              zName = "SQLITE_FORMAT";            break;
      case SQLITE_RANGE:               zName = "SQLITE_RANGE";             break;
      case SQLITE_NOTADB:              zName = "SQLITE_NOTADB";            break;
      case SQLITE_ROW:                 zName = "SQLITE_ROW";               break;
      case SQLITE_NOTICE:              zName = "SQLITE_NOTICE";            break;
      case SQLITE_WARNING:             zName = "SQLITE_WARNING";           break;
      case SQLITE_DONE:                zName = "SQLITE_DONE";              break;
      case SQLITE_IOERR_READ:          zName = "SQLITE_IOERR_READ";        break;
      case SQLITE_IOERR_SHORT_READ:    zName = "SQLITE_IOERR_SHORT_READ";  break;
      case SQLITE_IOERR_WRITE:         zName = "SQLITE_IOERR_WRITE";       break;
      case SQLITE_IOERR_FSYNC:         zName = "SQLITE_IOERR_FSYNC";       break;
      case SQLITE_IOERR_DIR_FSYNC:     zName = "SQLITE_IOERR_DIR_FSYNC";   break;
      case SQLITE_IOERR_TRUNCATE:      zName = "SQLITE_IOERR_TRUNCATE";    break;
      case SQLITE_IOERR_FSTAT:         zName = "SQLITE_IOERR_FSTAT";       break;
      case SQLITE_IOERR_UNLOCK:        zName = "SQLITE_IOERR_UNLOCK";      break;
      case SQLITE_IOERR_RDLOCK:        zName = "SQLITE_IOERR_RDLOCK";      break;
      case SQLITE_IOERR_DELETE:        zName = "SQLITE_IOERR_DELETE";      break;
      case SQLITE_IOERR_BLOCKED:       zName = "SQLITE_IOERR_BLOCKED";     break;
      case SQLITE_IOERR_NOMEM:         zName = "SQLITE_IOERR_NOMEM";       break;
      case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
      case SQLITE_IOERR_CHECKRESERVEDLOCK:
                                 zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
      case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;
      case SQLITE_CORRUPT_VTAB:        zName = "SQLITE_CORRUPT_VTAB";      break;
      case SQLITE_READONLY_RECOVERY:   zName = "SQLITE_READONLY_RECOVERY"; break;
      case SQLITE_READONLY_CANTLOCK:   zName = "SQLITE_READONLY_CANTLOCK"; break;
      case SQLITE_READONLY_ROLLBACK:   zName = "SQLITE_READONLY_ROLLBACK"; break;

    }
  }
  if( zName==0 ) zName = "SQLITE_Unknown";
  return zName;
}
#define t1ErrorName sqlite3TestErrorName

/*
** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
** fact that the sqlite3* is the first field in the Vdbe structure.
................................................................................
      break;
    }
  }

  Tcl_ResetResult(interp);
  return TCL_OK;
}

#if SQLITE_OS_UNIX
#include <sys/time.h>
#include <sys/resource.h>

static int test_getrusage(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  char buf[1024];
  struct rusage r;
  memset(&r, 0, sizeof(r));
  getrusage(RUSAGE_SELF, &r);

  sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d", 
    (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec, 
    (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec, 
    (int)r.ru_minflt, (int)r.ru_majflt
  );
  Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
  return TCL_OK;
}
#endif

#if SQLITE_OS_WIN
/*
** Information passed from the main thread into the windows file locker
** background thread.
*/
struct win32FileLocker {
................................................................................
     { "sqlite3_wal_checkpoint",   test_wal_checkpoint, 0  },
     { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0  },
     { "test_sqlite3_log",         test_sqlite3_log, 0  },
#ifndef SQLITE_OMIT_EXPLAIN
     { "print_explain_query_plan", test_print_eqp, 0  },
#endif
     { "sqlite3_test_control", test_test_control },
#if SQLITE_OS_UNIX
     { "getrusage", test_getrusage },
#endif
  };
  static int bitmask_size = sizeof(Bitmask)*8;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
  extern int sqlite3_xferopt_count;

Changes to src/test2.c.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
...
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/*
** Interpret an SQLite error number
*/
static char *errorName(int rc){
  char *zName;
  switch( rc ){
    case SQLITE_OK:         zName = "SQLITE_OK";          break;
    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
    case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
    case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
    case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
    case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
    case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
    case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
    case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break;
    default:                zName = "SQLITE_Unknown";     break;
  }
  return zName;
}

/*
** Page size and reserved size used for testing.
*/
static int test_pagesize = 1024;

/*
................................................................................
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
  rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0,
      SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB,
      pager_test_reiniter);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3PagerSetCachesize(pPager, nPage);
  pageSize = test_pagesize;
  sqlite3PagerSetPagesize(pPager, &pageSize, -1);
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager);
  Tcl_AppendResult(interp, zBuf, 0);
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerClose(pPager);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_rollback ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerRollback(pPager);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_commit ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  rc = sqlite3PagerCommitPhaseTwo(pPager);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stmt_begin ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerOpenSavepoint(pPager, 1);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stmt_rollback ID
................................................................................
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0);
  sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stmt_commit ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stats ID
................................................................................
  pPager = sqlite3TestTextToPtr(argv[1]);
  if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
  rc = sqlite3PagerSharedLock(pPager);
  if( rc==SQLITE_OK ){
    rc = sqlite3PagerGet(pPager, pgno, &pPage);
  }
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " PAGE DATA\"", 0);
    return TCL_ERROR;
  }
  pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerWrite(pPage);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  pData = sqlite3PagerGetData(pPage);
  strncpy(pData, argv[2], test_pagesize-1);
  pData[test_pagesize-1] = 0;
  return TCL_OK;
}
................................................................................
  if( zFile==0 ) return TCL_ERROR;
  memcpy(zFile, argv[2], nFile+1);
  zFile[nFile+1] = 0;
  rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd, 
      (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0
  );
  if( rc ){
    Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0);
    sqlite3_free(zFile);
    return TCL_ERROR;
  }
  offset = n;
  offset *= 1024*1024;
  rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
  sqlite3OsCloseFree(fd);
  sqlite3_free(zFile);
  if( rc ){
    Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}
#endif









|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|







 







|







 







|




|







 







|







 







|







 







|







 







|







 







|







 







|









|







15
16
17
18
19
20
21
22




























23
24
25
26
27
28
29
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
..
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
...
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

extern const char *sqlite3TestErrorName(int rc);





























/*
** Page size and reserved size used for testing.
*/
static int test_pagesize = 1024;

/*
................................................................................
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
  rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0,
      SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB,
      pager_test_reiniter);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3PagerSetCachesize(pPager, nPage);
  pageSize = test_pagesize;
  sqlite3PagerSetPagesize(pPager, &pageSize, -1);
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager);
  Tcl_AppendResult(interp, zBuf, 0);
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerClose(pPager);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_rollback ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerRollback(pPager);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_commit ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  rc = sqlite3PagerCommitPhaseTwo(pPager);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stmt_begin ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerOpenSavepoint(pPager, 1);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stmt_rollback ID
................................................................................
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0);
  sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stmt_commit ID
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   pager_stats ID
................................................................................
  pPager = sqlite3TestTextToPtr(argv[1]);
  if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
  rc = sqlite3PagerSharedLock(pPager);
  if( rc==SQLITE_OK ){
    rc = sqlite3PagerGet(pPager, pgno, &pPage);
  }
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " PAGE DATA\"", 0);
    return TCL_ERROR;
  }
  pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3PagerWrite(pPage);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  pData = sqlite3PagerGetData(pPage);
  strncpy(pData, argv[2], test_pagesize-1);
  pData[test_pagesize-1] = 0;
  return TCL_OK;
}
................................................................................
  if( zFile==0 ) return TCL_ERROR;
  memcpy(zFile, argv[2], nFile+1);
  zFile[nFile+1] = 0;
  rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd, 
      (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0
  );
  if( rc ){
    Tcl_AppendResult(interp, "open failed: ", sqlite3TestErrorName(rc), 0);
    sqlite3_free(zFile);
    return TCL_ERROR;
  }
  offset = n;
  offset *= 1024*1024;
  rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
  sqlite3OsCloseFree(fd);
  sqlite3_free(zFile);
  if( rc ){
    Tcl_AppendResult(interp, "write failed: ", sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}
#endif


Changes to src/test3.c.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
*/
#include "sqliteInt.h"
#include "btreeInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
** Interpret an SQLite error number
*/
static char *errorName(int rc){
  char *zName;
  switch( rc ){
    case SQLITE_OK:         zName = "SQLITE_OK";          break;
    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
    case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
    case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
    case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
    default:                zName = "SQLITE_Unknown";     break;
  }
  return zName;
}

/*
** A bogus sqlite3 connection structure for use in the btree
** tests.
*/
static sqlite3 sDb;
static int nRefSqlite3 = 0;
................................................................................
  if( zFilename==0 ) return TCL_ERROR;
  memcpy(zFilename, argv[1], n+1);
  zFilename[n+1] = 0;
  rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, 
     SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
  sqlite3_free(zFilename);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3BtreeSetCacheSize(pBt, nCache);
  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pBt = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3BtreeClose(pBt);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  nRefSqlite3--;
  if( nRefSqlite3==0 ){
    sqlite3_mutex_leave(sDb.mutex);
    sqlite3_mutex_free(sDb.mutex);
    sDb.mutex = 0;
................................................................................
    return TCL_ERROR;
  }
  pBt = sqlite3TestTextToPtr(argv[1]);
  sqlite3BtreeEnter(pBt);
  rc = sqlite3BtreeBeginTrans(pBt, 1);
  sqlite3BtreeLeave(pBt);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   btree_pager_stats ID
................................................................................
#endif
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
  }
  sqlite3BtreeLeave(pBt);
  if( rc ){
    ckfree((char *)pCur);
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}

................................................................................
  pCur = sqlite3TestTextToPtr(argv[1]);
  pBt = pCur->pBtree;
  sqlite3BtreeEnter(pBt);
  rc = sqlite3BtreeCloseCursor(pCur);
  sqlite3BtreeLeave(pBt);
  ckfree((char *)pCur);
  if( rc ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  return SQLITE_OK;
}

/*
** Usage:   btree_next ID
................................................................................
    return TCL_ERROR;
  }
  pCur = sqlite3TestTextToPtr(argv[1]);
  sqlite3BtreeEnter(pCur->pBtree);
  rc = sqlite3BtreeNext(pCur, &res);
  sqlite3BtreeLeave(pCur->pBtree);
  if( rc ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}

................................................................................
    return TCL_ERROR;
  }
  pCur = sqlite3TestTextToPtr(argv[1]);
  sqlite3BtreeEnter(pCur->pBtree);
  rc = sqlite3BtreeFirst(pCur, &res);
  sqlite3BtreeLeave(pCur->pBtree);
  if( rc ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}








|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|







 







|







 







|







 







|







 







|







 







|







15
16
17
18
19
20
21
22
























23
24
25
26
27
28
29
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
*/
#include "sqliteInt.h"
#include "btreeInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

extern const char *sqlite3TestErrorName(int rc);

























/*
** A bogus sqlite3 connection structure for use in the btree
** tests.
*/
static sqlite3 sDb;
static int nRefSqlite3 = 0;
................................................................................
  if( zFilename==0 ) return TCL_ERROR;
  memcpy(zFilename, argv[1], n+1);
  zFilename[n+1] = 0;
  rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, 
     SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
  sqlite3_free(zFilename);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3BtreeSetCacheSize(pBt, nCache);
  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}
................................................................................
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pBt = sqlite3TestTextToPtr(argv[1]);
  rc = sqlite3BtreeClose(pBt);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  nRefSqlite3--;
  if( nRefSqlite3==0 ){
    sqlite3_mutex_leave(sDb.mutex);
    sqlite3_mutex_free(sDb.mutex);
    sDb.mutex = 0;
................................................................................
    return TCL_ERROR;
  }
  pBt = sqlite3TestTextToPtr(argv[1]);
  sqlite3BtreeEnter(pBt);
  rc = sqlite3BtreeBeginTrans(pBt, 1);
  sqlite3BtreeLeave(pBt);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:   btree_pager_stats ID
................................................................................
#endif
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
  }
  sqlite3BtreeLeave(pBt);
  if( rc ){
    ckfree((char *)pCur);
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}

................................................................................
  pCur = sqlite3TestTextToPtr(argv[1]);
  pBt = pCur->pBtree;
  sqlite3BtreeEnter(pBt);
  rc = sqlite3BtreeCloseCursor(pCur);
  sqlite3BtreeLeave(pBt);
  ckfree((char *)pCur);
  if( rc ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  return SQLITE_OK;
}

/*
** Usage:   btree_next ID
................................................................................
    return TCL_ERROR;
  }
  pCur = sqlite3TestTextToPtr(argv[1]);
  sqlite3BtreeEnter(pCur->pBtree);
  rc = sqlite3BtreeNext(pCur, &res);
  sqlite3BtreeLeave(pCur->pBtree);
  if( rc ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}

................................................................................
    return TCL_ERROR;
  }
  pCur = sqlite3TestTextToPtr(argv[1]);
  sqlite3BtreeEnter(pCur->pBtree);
  rc = sqlite3BtreeFirst(pCur, &res);
  sqlite3BtreeLeave(pCur->pBtree);
  if( rc ){
    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}

Changes to src/test4.c.

16
17
18
19
20
21
22


23
24
25
26
27
28
29
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sched.h>
#include <ctype.h>



/*
** Each thread is controlled by an instance of the following
** structure.
*/
typedef struct Thread Thread;
struct Thread {
  /* The first group of fields are writable by the master and read-only
................................................................................
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  switch( threadset[i].rc ){
    case SQLITE_OK:         zName = "SQLITE_OK";          break;
    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
    case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
    case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
    case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
    case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
    case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
    case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
    case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
    case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break;
    case SQLITE_AUTH:       zName = "SQLITE_AUTH";        break;
    case SQLITE_FORMAT:     zName = "SQLITE_FORMAT";      break;
    case SQLITE_RANGE:      zName = "SQLITE_RANGE";       break;
    case SQLITE_ROW:        zName = "SQLITE_ROW";         break;
    case SQLITE_DONE:       zName = "SQLITE_DONE";        break;
    default:                zName = "SQLITE_Unknown";     break;
  }
  Tcl_AppendResult(interp, zName, 0);
  return TCL_OK;
}

/*
** Usage: thread_error  ID
**







>
>







 







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
370
371
372
373
374
375
376
377



























378
379
380
381
382
383
384
#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sched.h>
#include <ctype.h>

extern const char *sqlite3TestErrorName(int rc);

/*
** Each thread is controlled by an instance of the following
** structure.
*/
typedef struct Thread Thread;
struct Thread {
  /* The first group of fields are writable by the master and read-only
................................................................................
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  zName = sqlite3TestErrorName(threadset[i].rc);



























  Tcl_AppendResult(interp, zName, 0);
  return TCL_OK;
}

/*
** Usage: thread_error  ID
**

Changes to src/test7.c.

372
373
374
375
376
377
378


379
380
381
382
383
384
385
...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
    Tcl_AppendResult(interp, "column number out of range", 0);
    return TCL_ERROR;
  }
  Tcl_AppendResult(interp, threadset[i].colv[n], 0);
  return TCL_OK;
}



/*
** Usage: client_result  ID
**
** Wait on the most recent operation to complete, then return the
** result code from that operation.
*/
static int tcl_client_result(
................................................................................
  i = parse_client_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  client_wait(&threadset[i]);
  switch( threadset[i].rc ){
    case SQLITE_OK:         zName = "SQLITE_OK";          break;
    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
    case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
    case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
    case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
    case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
    case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
    case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
    case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
    case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break;
    case SQLITE_AUTH:       zName = "SQLITE_AUTH";        break;
    case SQLITE_FORMAT:     zName = "SQLITE_FORMAT";      break;
    case SQLITE_RANGE:      zName = "SQLITE_RANGE";       break;
    case SQLITE_ROW:        zName = "SQLITE_ROW";         break;
    case SQLITE_DONE:       zName = "SQLITE_DONE";        break;
    default:                zName = "SQLITE_Unknown";     break;
  }
  Tcl_AppendResult(interp, zName, 0);
  return TCL_OK;
}

/*
** Usage: client_error  ID
**







>
>







 







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
...
401
402
403
404
405
406
407
408



























409
410
411
412
413
414
415
    Tcl_AppendResult(interp, "column number out of range", 0);
    return TCL_ERROR;
  }
  Tcl_AppendResult(interp, threadset[i].colv[n], 0);
  return TCL_OK;
}

extern const char *sqlite3TestErrorName(int rc);

/*
** Usage: client_result  ID
**
** Wait on the most recent operation to complete, then return the
** result code from that operation.
*/
static int tcl_client_result(
................................................................................
  i = parse_client_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  client_wait(&threadset[i]);
  zName = sqlite3TestErrorName(threadset[i].rc);



























  Tcl_AppendResult(interp, zName, 0);
  return TCL_OK;
}

/*
** Usage: client_error  ID
**

Changes to src/test_autoext.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** Test extension for testing the sqlite3_auto_extension() function.
*/
#include "tcl.h"
#include "sqlite3ext.h"

#ifndef SQLITE_OMIT_LOAD_EXTENSION
static SQLITE_EXTENSION_INIT1

/*
** The sqr() SQL function returns the square of its input value.
*/
static void sqrFunc(
  sqlite3_context *context,
  int argc,







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** Test extension for testing the sqlite3_auto_extension() function.
*/
#include "tcl.h"
#include "sqlite3ext.h"

#ifndef SQLITE_OMIT_LOAD_EXTENSION
SQLITE_EXTENSION_INIT1

/*
** The sqr() SQL function returns the square of its input value.
*/
static void sqrFunc(
  sqlite3_context *context,
  int argc,

Changes to src/test_config.c.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
82
83
84
85
86
87
88






89
90
91
92
93
94
95

#ifdef SQLITE_CASE_SENSITIVE_LIKE
  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_CURDIR
  Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "curdir", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_DEBUG
  Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
................................................................................
#endif

#ifdef SQLITE_DISABLE_LFS
  Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
#endif







#if 1 /* def SQLITE_MEMDEBUG */
  Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY);
#endif








|







 







>
>
>
>
>
>







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

#ifdef SQLITE_CASE_SENSITIVE_LIKE
  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
#endif

#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
  Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "curdir", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_DEBUG
  Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
................................................................................
#endif

#ifdef SQLITE_DISABLE_LFS
  Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
#endif

#if SQLITE_MAX_MMAP_SIZE>0
  Tcl_SetVar2(interp, "sqlite_options", "mmap", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "mmap", "0", TCL_GLOBAL_ONLY);
#endif

#if 1 /* def SQLITE_MEMDEBUG */
  Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY);
#endif

Changes to src/test_sqllog.c.

9
10
11
12
13
14
15
16


17
18
19
20
21
22





23
24
25
26
27



28
29
30
31
32
33
34
35
36
37
38
..
53
54
55
56
57
58
59

60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88



89
90
91
92
93
94
95


96
97
98
99
100
101
102
103
...
384
385
386
387
388
389
390


















391
392
393
394
395
396
397
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** OVERVIEW
**
**   This file contains experimental code used to record data from live
**   SQLite applications that may be useful for offline analysis. Specifically:


**
**     1) The initial contents of all database files opened by the 
**        application, and
**
**     2) All SQL statements executed by the application.
**





** USAGE
**
**   To use this module, SQLite must be compiled with the SQLITE_ENABLE_SQLLOG
**   pre-processor symbol defined and this file linked into the application
**   somehow.



**
**   At runtime, logging is enabled by setting environment variable
**   SQLITE_SQLLOG_DIR to the name of a directory in which to store logged 
**   data. The directory must already exist.
**
**   Usually, if the application opens the same database file more than once
**   (either by attaching it or by using more than one database handle), only
**   a single copy is made. This behavior may be overridden (so that a 
**   separate copy is taken each time the database file is opened or attached)
**   by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0.
**
................................................................................
**
**   This module attempts to make a best effort to continue logging if an
**   IO or other error is encountered. For example, if a log file cannot 
**   be opened logs are not collected for that connection, but other
**   logging proceeds as expected. Errors are logged by calling sqlite3_log().
*/


#include "sqlite3.h"

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "assert.h"

#include "sys/types.h"
#include "unistd.h"
static int getProcessId(void){
#if SQLITE_OS_WIN
  return (int)_getpid();
#else
  return (int)getpid();
#endif
}


#define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR"
#define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES"

/* Assume that all database and database file names are shorted than this. */
#define SQLLOG_NAMESZ 512

/* Maximum number of simultaneous database connections the process may
** open (if any more are opened an error is logged using sqlite3_log()
** and processing is halted).
*/
#define MAX_CONNECTIONS 256




struct SLConn {
  int isErr;                      /* True if an error has occurred */
  sqlite3 *db;                    /* Connection handle */
  int iLog;                       /* First integer value used in file names */
  FILE *fd;                       /* File descriptor for log file */
};



struct SLGlobal {
  /* Protected by MUTEX_STATIC_MASTER */
  sqlite3_mutex *mutex;           /* Recursive mutex */
  int nConn;                      /* Size of aConn[] array */

  /* Protected by SLGlobal.mutex */
  int bReuse;                     /* True to avoid extra copies of db files */
  char zPrefix[SQLLOG_NAMESZ];    /* Prefix for all created files */
................................................................................
    /* This is an ATTACH statement. Copy the database. */
    sqllogCopydb(p, 0, 1);
  }
}

/*
** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog().


















*/
static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
  struct SLConn *p = 0;
  sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);

  assert( eType==0 || eType==1 || eType==2 );
  assert( (eType==2)==(zSql==0) );







|
>
>






>
>
>
>
>



|
|
>
>
>



|







 







>

>
|
|
|
|

|
|








|












>
>
>







>
>
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** OVERVIEW
**
**   This file contains experimental code used to record data from live
**   SQLite applications that may be useful for offline analysis. 
**   Specifically, this module can be used to capture the following
**   information:
**
**     1) The initial contents of all database files opened by the 
**        application, and
**
**     2) All SQL statements executed by the application.
**
**   The captured information can then be used to run (for example)
**   performance analysis looking for slow queries or to look for
**   optimization opportunities in either the application or in SQLite
**   itself.
**
** USAGE
**
**   To use this module, SQLite must be compiled with the SQLITE_ENABLE_SQLLOG
**   pre-processor symbol defined and this file linked into the application.
**   One way to link this file into the application is to append the content
**   of this file onto the end of the "sqlite3.c" amalgamation and then 
**   recompile the application as normal except with the addition  of the
**   -DSQLITE_ENABLE_SQLLOG option.
**
**   At runtime, logging is enabled by setting environment variable
**   SQLITE_SQLLOG_DIR to the name of a directory in which to store logged 
**   data. The logging directory must already exist.
**
**   Usually, if the application opens the same database file more than once
**   (either by attaching it or by using more than one database handle), only
**   a single copy is made. This behavior may be overridden (so that a 
**   separate copy is taken each time the database file is opened or attached)
**   by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0.
**
................................................................................
**
**   This module attempts to make a best effort to continue logging if an
**   IO or other error is encountered. For example, if a log file cannot 
**   be opened logs are not collected for that connection, but other
**   logging proceeds as expected. Errors are logged by calling sqlite3_log().
*/

#ifndef _SQLITE3_H_
#include "sqlite3.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <sys/types.h>
#include <unistd.h>
static int getProcessId(void){
#if SQLITE_OS_WIN
  return (int)_getpid();
#else
  return (int)getpid();
#endif
}

/* Names of environment variables to be used */
#define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR"
#define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES"

/* Assume that all database and database file names are shorted than this. */
#define SQLLOG_NAMESZ 512

/* Maximum number of simultaneous database connections the process may
** open (if any more are opened an error is logged using sqlite3_log()
** and processing is halted).
*/
#define MAX_CONNECTIONS 256

/* There is one instance of this object for each SQLite database connection
** that is being logged.
*/
struct SLConn {
  int isErr;                      /* True if an error has occurred */
  sqlite3 *db;                    /* Connection handle */
  int iLog;                       /* First integer value used in file names */
  FILE *fd;                       /* File descriptor for log file */
};

/* This object is a singleton that keeps track of all data loggers.
*/
static struct SLGlobal {
  /* Protected by MUTEX_STATIC_MASTER */
  sqlite3_mutex *mutex;           /* Recursive mutex */
  int nConn;                      /* Size of aConn[] array */

  /* Protected by SLGlobal.mutex */
  int bReuse;                     /* True to avoid extra copies of db files */
  char zPrefix[SQLLOG_NAMESZ];    /* Prefix for all created files */
................................................................................
    /* This is an ATTACH statement. Copy the database. */
    sqllogCopydb(p, 0, 1);
  }
}

/*
** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog().
**
** The eType parameter has the following values:
**
**    0:  Opening a new database connection.  zSql is the name of the
**        file being opened.  db is a pointer to the newly created database
**        connection.
**
**    1:  An SQL statement has run to completion.  zSql is the text of the
**        SQL statement with all parameters expanded to their actual values.
**
**    2:  Closing a database connection.  zSql is NULL.  The db pointer to
**        the database connection being closed has already been shut down
**        and cannot be used for any further SQL.
**
** The pCtx parameter is a copy of the pointer that was originally passed
** into the sqlite3_config(SQLITE_CONFIG_SQLLOG) statement.  In this
** particular implementation, pCtx is always a pointer to the 
** sqllogglobal global variable define above.
*/
static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
  struct SLConn *p = 0;
  sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);

  assert( eType==0 || eType==1 || eType==2 );
  assert( (eType==2)==(zSql==0) );

Changes to src/test_syscall.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
77
78
79
80
81
82
83

84
85
86
87
88
89
90
...
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
...
127
128
129
130
131
132
133


134
135
136
137
138
139
140
...
148
149
150
151
152
153
154


155
156
157
158
159
160
161
...
372
373
374
375
376
377
378

























379
380
381
382
383
384
385
**   test_syscall install LIST
**     Install wrapper functions for all system calls in argument LIST.
**     LIST must be a list consisting of zero or more of the following
**     literal values:
**
**         open        close      access   getcwd   stat      fstat    
**         ftruncate   fcntl      read     pread    pread64   write
**         pwrite      pwrite64   fchmod   fallocate
**
**   test_syscall uninstall
**     Uninstall all wrapper functions.
**
**   test_syscall fault ?COUNT PERSIST?
**     If [test_syscall fault] is invoked without the two arguments, fault
**     injection is disabled. Otherwise, fault injection is configured to
................................................................................

#include "sqliteInt.h"
#if SQLITE_OS_UNIX

/* From test1.c */
extern const char *sqlite3TestErrorName(int);


#include <sys/types.h>
#include <errno.h>

static struct TestSyscallGlobal {
  int bPersist;                   /* 1 for persistent errors, 0 for transient */
  int nCount;                     /* Fail after this many more calls */
  int nFail;                      /* Number of failures that have occurred */
................................................................................
static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off);
static int ts_write(int fd, const void *aBuf, size_t nBuf);
static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off);
static int ts_fchmod(int fd, mode_t mode);
static int ts_fallocate(int fd, off_t off, off_t len);



struct TestSyscallArray {
  const char *zName;
  sqlite3_syscall_ptr xTest;
  sqlite3_syscall_ptr xOrig;
  int default_errno;              /* Default value for errno following errors */
  int custom_errno;               /* Current value for errno if error */
................................................................................
  /*  9 */ { "pread",     (sqlite3_syscall_ptr)ts_pread,     0, 0, 0 },
  /* 10 */ { "pread64",   (sqlite3_syscall_ptr)ts_pread64,   0, 0, 0 },
  /* 11 */ { "write",     (sqlite3_syscall_ptr)ts_write,     0, 0, 0 },
  /* 12 */ { "pwrite",    (sqlite3_syscall_ptr)ts_pwrite,    0, 0, 0 },
  /* 13 */ { "pwrite64",  (sqlite3_syscall_ptr)ts_pwrite64,  0, 0, 0 },
  /* 14 */ { "fchmod",    (sqlite3_syscall_ptr)ts_fchmod,    0, 0, 0 },
  /* 15 */ { "fallocate", (sqlite3_syscall_ptr)ts_fallocate, 0, 0, 0 },


           { 0, 0, 0, 0, 0 }
};

#define orig_open      ((int(*)(const char *, int, int))aSyscall[0].xOrig)
#define orig_close     ((int(*)(int))aSyscall[1].xOrig)
#define orig_access    ((int(*)(const char*,int))aSyscall[2].xOrig)
#define orig_getcwd    ((char*(*)(char*,size_t))aSyscall[3].xOrig)
................................................................................
#define orig_write     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig)
#define orig_pwrite    ((ssize_t(*)(int,const void*,size_t,off_t))\
                       aSyscall[12].xOrig)
#define orig_pwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
                       aSyscall[13].xOrig)
#define orig_fchmod    ((int(*)(int,mode_t))aSyscall[14].xOrig)
#define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig)



/*
** This function is called exactly once from within each invocation of a
** system call wrapper in this file. It returns 1 if the function should
** fail, or 0 if it should succeed.
*/
static int tsIsFail(void){
................................................................................
*/
static int ts_fallocate(int fd, off_t off, off_t len){
  if( tsIsFail() ){
    return tsErrno("fallocate");
  }
  return orig_fallocate(fd, off, len);
}


























static int test_syscall_install(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){







|







 







>







 







|
>







 







>
>







 







>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
**   test_syscall install LIST
**     Install wrapper functions for all system calls in argument LIST.
**     LIST must be a list consisting of zero or more of the following
**     literal values:
**
**         open        close      access   getcwd   stat      fstat    
**         ftruncate   fcntl      read     pread    pread64   write
**         pwrite      pwrite64   fchmod   fallocate mmap
**
**   test_syscall uninstall
**     Uninstall all wrapper functions.
**
**   test_syscall fault ?COUNT PERSIST?
**     If [test_syscall fault] is invoked without the two arguments, fault
**     injection is disabled. Otherwise, fault injection is configured to
................................................................................

#include "sqliteInt.h"
#if SQLITE_OS_UNIX

/* From test1.c */
extern const char *sqlite3TestErrorName(int);

#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>

static struct TestSyscallGlobal {
  int bPersist;                   /* 1 for persistent errors, 0 for transient */
  int nCount;                     /* Fail after this many more calls */
  int nFail;                      /* Number of failures that have occurred */
................................................................................
static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off);
static int ts_write(int fd, const void *aBuf, size_t nBuf);
static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off);
static int ts_fchmod(int fd, mode_t mode);
static int ts_fallocate(int fd, off_t off, off_t len);
static void *ts_mmap(void *, size_t, int, int, int, off_t);
static void *ts_mremap(void*, size_t, size_t, int, ...);

struct TestSyscallArray {
  const char *zName;
  sqlite3_syscall_ptr xTest;
  sqlite3_syscall_ptr xOrig;
  int default_errno;              /* Default value for errno following errors */
  int custom_errno;               /* Current value for errno if error */
................................................................................
  /*  9 */ { "pread",     (sqlite3_syscall_ptr)ts_pread,     0, 0, 0 },
  /* 10 */ { "pread64",   (sqlite3_syscall_ptr)ts_pread64,   0, 0, 0 },
  /* 11 */ { "write",     (sqlite3_syscall_ptr)ts_write,     0, 0, 0 },
  /* 12 */ { "pwrite",    (sqlite3_syscall_ptr)ts_pwrite,    0, 0, 0 },
  /* 13 */ { "pwrite64",  (sqlite3_syscall_ptr)ts_pwrite64,  0, 0, 0 },
  /* 14 */ { "fchmod",    (sqlite3_syscall_ptr)ts_fchmod,    0, 0, 0 },
  /* 15 */ { "fallocate", (sqlite3_syscall_ptr)ts_fallocate, 0, 0, 0 },
  /* 16 */ { "mmap",      (sqlite3_syscall_ptr)ts_mmap,      0, 0, 0 },
  /* 17 */ { "mremap",    (sqlite3_syscall_ptr)ts_mremap,    0, 0, 0 },
           { 0, 0, 0, 0, 0 }
};

#define orig_open      ((int(*)(const char *, int, int))aSyscall[0].xOrig)
#define orig_close     ((int(*)(int))aSyscall[1].xOrig)
#define orig_access    ((int(*)(const char*,int))aSyscall[2].xOrig)
#define orig_getcwd    ((char*(*)(char*,size_t))aSyscall[3].xOrig)
................................................................................
#define orig_write     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig)
#define orig_pwrite    ((ssize_t(*)(int,const void*,size_t,off_t))\
                       aSyscall[12].xOrig)
#define orig_pwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
                       aSyscall[13].xOrig)
#define orig_fchmod    ((int(*)(int,mode_t))aSyscall[14].xOrig)
#define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig)
#define orig_mmap      ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[16].xOrig)
#define orig_mremap    ((void*(*)(void*,size_t,size_t,int,...))aSyscall[17].xOrig)

/*
** This function is called exactly once from within each invocation of a
** system call wrapper in this file. It returns 1 if the function should
** fail, or 0 if it should succeed.
*/
static int tsIsFail(void){
................................................................................
*/
static int ts_fallocate(int fd, off_t off, off_t len){
  if( tsIsFail() ){
    return tsErrno("fallocate");
  }
  return orig_fallocate(fd, off, len);
}

static void *ts_mmap(
  void *pAddr, 
  size_t nByte, 
  int prot, 
  int flags, 
  int fd, 
  off_t iOff
){
  if( tsIsFailErrno("mmap") ){
    return MAP_FAILED;
  }
  return orig_mmap(pAddr, nByte, prot, flags, fd, iOff);
}

static void *ts_mremap(void *a, size_t b, size_t c, int d, ...){
  va_list ap;
  void *pArg;
  if( tsIsFailErrno("mremap") ){
    return MAP_FAILED;
  }
  va_start(ap, d);
  pArg = va_arg(ap, void *);
  return orig_mremap(a, b, c, d, pArg);
}

static int test_syscall_install(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){

Changes to src/test_vfs.c.

121
122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
...
463
464
465
466
467
468
469
470




471
472
473
474
475
476
477
478
....
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
#define TESTVFS_DELETE_MASK       0x00000400
#define TESTVFS_CLOSE_MASK        0x00000800
#define TESTVFS_WRITE_MASK        0x00001000
#define TESTVFS_TRUNCATE_MASK     0x00002000
#define TESTVFS_ACCESS_MASK       0x00004000
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
#define TESTVFS_READ_MASK         0x00010000


#define TESTVFS_ALL_MASK          0x0001FFFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
** memory region opened by clients. If two clients open the same file,
................................................................................
  return sqlite3OsLock(p->pReal, eLock);
}

/*
** Unlock an tvfs-file.
*/
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
  TestvfsFd *p = tvfsGetFd(pFile);




  return sqlite3OsUnlock(p->pReal, eLock);
}

/*
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
*/
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  TestvfsFd *p = tvfsGetFd(pFile);
................................................................................
        { "xWrite",        TESTVFS_WRITE_MASK },
        { "xRead",         TESTVFS_READ_MASK },
        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
        { "xOpen",         TESTVFS_OPEN_MASK },
        { "xClose",        TESTVFS_CLOSE_MASK },
        { "xAccess",       TESTVFS_ACCESS_MASK },
        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },

      };
      Tcl_Obj **apElem = 0;
      int nElem = 0;
      int i;
      int mask = 0;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "LIST");







>

|







 







|
>
>
>
>
|







 







>







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
....
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
#define TESTVFS_DELETE_MASK       0x00000400
#define TESTVFS_CLOSE_MASK        0x00000800
#define TESTVFS_WRITE_MASK        0x00001000
#define TESTVFS_TRUNCATE_MASK     0x00002000
#define TESTVFS_ACCESS_MASK       0x00004000
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
#define TESTVFS_READ_MASK         0x00010000
#define TESTVFS_UNLOCK_MASK       0x00020000

#define TESTVFS_ALL_MASK          0x0003FFFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
** memory region opened by clients. If two clients open the same file,
................................................................................
  return sqlite3OsLock(p->pReal, eLock);
}

/*
** Unlock an tvfs-file.
*/
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
  TestvfsFd *pFd = tvfsGetFd(pFile);
  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
  if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
    return SQLITE_IOERR_UNLOCK;
  }
  return sqlite3OsUnlock(pFd->pReal, eLock);
}

/*
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
*/
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  TestvfsFd *p = tvfsGetFd(pFile);
................................................................................
        { "xWrite",        TESTVFS_WRITE_MASK },
        { "xRead",         TESTVFS_READ_MASK },
        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
        { "xOpen",         TESTVFS_OPEN_MASK },
        { "xClose",        TESTVFS_CLOSE_MASK },
        { "xAccess",       TESTVFS_ACCESS_MASK },
        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
        { "xUnlock",       TESTVFS_UNLOCK_MASK },
      };
      Tcl_Obj **apElem = 0;
      int nElem = 0;
      int i;
      int mask = 0;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "LIST");

Changes to src/vdbe.c.

3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
      /* The next line of code computes as follows, only faster:
      **   if( oc==OP_SeekGt || oc==OP_SeekLe ){
      **     r.flags = UNPACKED_INCRKEY;
      **   }else{
      **     r.flags = 0;
      **   }
      */
      r.flags = (u16)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLt)));
      assert( oc!=OP_SeekGt || r.flags==UNPACKED_INCRKEY );
      assert( oc!=OP_SeekLe || r.flags==UNPACKED_INCRKEY );
      assert( oc!=OP_SeekGe || r.flags==0 );
      assert( oc!=OP_SeekLt || r.flags==0 );

      r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG







|







3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
      /* The next line of code computes as follows, only faster:
      **   if( oc==OP_SeekGt || oc==OP_SeekLe ){
      **     r.flags = UNPACKED_INCRKEY;
      **   }else{
      **     r.flags = 0;
      **   }
      */
      r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLt)));
      assert( oc!=OP_SeekGt || r.flags==UNPACKED_INCRKEY );
      assert( oc!=OP_SeekLe || r.flags==UNPACKED_INCRKEY );
      assert( oc!=OP_SeekGe || r.flags==0 );
      assert( oc!=OP_SeekLt || r.flags==0 );

      r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG

Changes to src/vdbeInt.h.

14
15
16
17
18
19
20








21
22
23
24
25
26
27
** source code file "vdbe.c".  When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_









/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
** of the following structure.
*/
typedef struct VdbeOp Op;








>
>
>
>
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
** source code file "vdbe.c".  When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_

/*
** The maximum number of times that a statement will try to reparse
** itself before giving up and returning SQLITE_SCHEMA.
*/
#ifndef SQLITE_MAX_SCHEMA_RETRY
# define SQLITE_MAX_SCHEMA_RETRY 50
#endif

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
** of the following structure.
*/
typedef struct VdbeOp Op;

Changes to src/vdbeapi.c.

449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
    ** caller. Set the error code in the database handle to the same value.
    */ 
    rc = sqlite3VdbeTransferError(p);
  }
  return (rc&db->errMask);
}

/*
** The maximum number of times that a statement will try to reparse
** itself before giving up and returning SQLITE_SCHEMA.
*/
#ifndef SQLITE_MAX_SCHEMA_RETRY
# define SQLITE_MAX_SCHEMA_RETRY 5
#endif

/*
** This is the top-level implementation of sqlite3_step().  Call
** sqlite3Step() to do most of the work.  If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
  int rc = SQLITE_OK;      /* Result from sqlite3Step() */







<
<
<
<
<
<
<
<







449
450
451
452
453
454
455








456
457
458
459
460
461
462
    ** caller. Set the error code in the database handle to the same value.
    */ 
    rc = sqlite3VdbeTransferError(p);
  }
  return (rc&db->errMask);
}









/*
** This is the top-level implementation of sqlite3_step().  Call
** sqlite3Step() to do most of the work.  If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
  int rc = SQLITE_OK;      /* Result from sqlite3Step() */

Changes to src/vdbeblob.c.

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
    pBlob->db = db;
    sqlite3BtreeLeaveAll(db);
    if( db->mallocFailed ){
      goto blob_open_out;
    }
    sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
    rc = blobSeekToRow(pBlob, iRow, &zErr);
  } while( (++nAttempt)<5 && rc==SQLITE_SCHEMA );

blob_open_out:
  if( rc==SQLITE_OK && db->mallocFailed==0 ){
    *ppBlob = (sqlite3_blob *)pBlob;
  }else{
    if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
    sqlite3DbFree(db, pBlob);







|







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
    pBlob->db = db;
    sqlite3BtreeLeaveAll(db);
    if( db->mallocFailed ){
      goto blob_open_out;
    }
    sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
    rc = blobSeekToRow(pBlob, iRow, &zErr);
  } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );

blob_open_out:
  if( rc==SQLITE_OK && db->mallocFailed==0 ){
    *ppBlob = (sqlite3_blob *)pBlob;
  }else{
    if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
    sqlite3DbFree(db, pBlob);

Changes to src/vdbetrace.c.

48
49
50
51
52
53
54





55
56
57
58
59
60
61
...
119
120
121
122
123
124
125

126
127
128
129

130
131
132
133










134




135
136
137
138
139
140
141
142
143

144
145




146
147
148
149



150
151
152
153
154
155
156
/*
** This function returns a pointer to a nul-terminated string in memory
** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
** string contains a copy of zRawSql but with host parameters expanded to 
** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, 
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.





**
** The calling function is responsible for making sure the memory returned
** is eventually freed.
**
** ALGORITHM:  Scan the input string looking for host parameters in any of
** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
** string literals, quoted identifier names, and comments.  For text forms,
................................................................................
      if( pVar->flags & MEM_Null ){
        sqlite3StrAccumAppend(&out, "NULL", 4);
      }else if( pVar->flags & MEM_Int ){
        sqlite3XPrintf(&out, "%lld", pVar->u.i);
      }else if( pVar->flags & MEM_Real ){
        sqlite3XPrintf(&out, "%!.15g", pVar->r);
      }else if( pVar->flags & MEM_Str ){

#ifndef SQLITE_OMIT_UTF16
        u8 enc = ENC(db);
        if( enc!=SQLITE_UTF8 ){
          Mem utf8;

          memset(&utf8, 0, sizeof(utf8));
          utf8.db = db;
          sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
          sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);










          sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z);




          sqlite3VdbeMemRelease(&utf8);
        }else
#endif
        {
          sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);
        }
      }else if( pVar->flags & MEM_Zero ){
        sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
      }else{

        assert( pVar->flags & MEM_Blob );
        sqlite3StrAccumAppend(&out, "x'", 2);




        for(i=0; i<pVar->n; i++){
          sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
        }
        sqlite3StrAccumAppend(&out, "'", 1);



      }
    }
  }
  return sqlite3StrAccumFinish(&out);
}

#endif /* #ifndef SQLITE_OMIT_TRACE */







>
>
>
>
>







 







>


<
|
>




>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
<

<
<
<



>


>
>
>
>
|



>
>
>







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
** This function returns a pointer to a nul-terminated string in memory
** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
** string contains a copy of zRawSql but with host parameters expanded to 
** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, 
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.
**
** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then
** then long strings and blobs are truncated to that many bytes.  This
** can be used to prevent unreasonably large trace strings when dealing
** with large (multi-megabyte) strings and blobs.
**
** The calling function is responsible for making sure the memory returned
** is eventually freed.
**
** ALGORITHM:  Scan the input string looking for host parameters in any of
** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
** string literals, quoted identifier names, and comments.  For text forms,
................................................................................
      if( pVar->flags & MEM_Null ){
        sqlite3StrAccumAppend(&out, "NULL", 4);
      }else if( pVar->flags & MEM_Int ){
        sqlite3XPrintf(&out, "%lld", pVar->u.i);
      }else if( pVar->flags & MEM_Real ){
        sqlite3XPrintf(&out, "%!.15g", pVar->r);
      }else if( pVar->flags & MEM_Str ){
        int nOut;  /* Number of bytes of the string text to include in output */
#ifndef SQLITE_OMIT_UTF16
        u8 enc = ENC(db);

        Mem utf8;
        if( enc!=SQLITE_UTF8 ){
          memset(&utf8, 0, sizeof(utf8));
          utf8.db = db;
          sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
          sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
          pVar = &utf8;
        }
#endif
        nOut = pVar->n;
#ifdef SQLITE_TRACE_SIZE_LIMIT
        if( n>SQLITE_TRACE_SIZE_LIMIT ){
          nOut = SQLITE_TRACE_SIZE_LIMIT;
          while( nOut<pVar->n && (pVar->z[n]&0xc0)==0x80 ){ n++; }
        }
#endif    
        sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
#ifdef SQLITE_TRACE_SIZE_LIMIT
        if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-n);
#endif
#ifndef SQLITE_OMIT_UTF16
        if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);

#endif



      }else if( pVar->flags & MEM_Zero ){
        sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
      }else{
        int nOut;  /* Number of bytes of the blob to include in output */
        assert( pVar->flags & MEM_Blob );
        sqlite3StrAccumAppend(&out, "x'", 2);
        nOut = pVar->n;
#ifdef SQLITE_TRACE_SIZE_LIMIT
        if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
#endif
        for(i=0; i<nOut; i++){
          sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
        }
        sqlite3StrAccumAppend(&out, "'", 1);
#ifdef SQLITE_TRACE_SIZE_LIMIT
        if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-n);
#endif
      }
    }
  }
  return sqlite3StrAccumFinish(&out);
}

#endif /* #ifndef SQLITE_OMIT_TRACE */

Changes to src/wal.c.

1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
....
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734

1735
1736
1737
1738
1739
1740
1741
....
2283
2284
2285
2286
2287
2288
2289
2290
2291

2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
....
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
....
2382
2383
2384
2385
2386
2387
2388
2389
2390






2391
2392






2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
....
2948
2949
2950
2951
2952
2953
2954



2955
2956
2957
2958
2959
2960
2961

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.
    */
    if( pWal->hdr.nPage ){

      sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s",
          pWal->hdr.nPage, pWal->zWalName
      );
    }
  }

recovery_error:
  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, nLock);
................................................................................
    u32 nBackfill = pInfo->nBackfill;

    /* Sync the WAL to disk */
    if( sync_flags ){
      rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
    }

    /* If the database file may grow as a result of this checkpoint, hint
    ** about the eventual size of the db file to the VFS layer. 
    */
    if( rc==SQLITE_OK ){
      i64 nReq = ((i64)mxPage * szPage);
      rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
      if( rc==SQLITE_OK && nSize<nReq ){
        sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
      }
    }


    /* Iterate through the contents of the WAL, copying data to the db file. */
    while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
      i64 iOffset;
      assert( walFramePgno(pWal, iFrame)==iDbpage );
      if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
      iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
................................................................................
  if( pWal->readLock>=0 ){
    walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
    pWal->readLock = -1;
  }
}

/*
** Read a page from the WAL, if it is present in the WAL and if the 
** current read transaction is configured to use the WAL.  

**
** The *pInWal is set to 1 if the requested page is in the WAL and
** has been loaded.  Or *pInWal is set to 0 if the page was not in 
** the WAL and needs to be read out of the database.
*/
int sqlite3WalRead(
  Wal *pWal,                      /* WAL handle */
  Pgno pgno,                      /* Database page number to read data for */
  int *pInWal,                    /* OUT: True if data is read from WAL */
  int nOut,                       /* Size of buffer pOut in bytes */
  u8 *pOut                        /* Buffer to write page data to */
){
  u32 iRead = 0;                  /* If !=0, WAL frame to return data from */
  u32 iLast = pWal->hdr.mxFrame;  /* Last page in WAL for this reader */
  int iHash;                      /* Used to loop through N hash tables */

  /* This routine is only be called from within a read transaction. */
  assert( pWal->readLock>=0 || pWal->lockError );
................................................................................
  /* If the "last page" field of the wal-index header snapshot is 0, then
  ** no data will be read from the wal under any circumstances. Return early
  ** in this case as an optimization.  Likewise, if pWal->readLock==0, 
  ** then the WAL is ignored by the reader so return early, as if the 
  ** WAL were empty.
  */
  if( iLast==0 || pWal->readLock==0 ){
    *pInWal = 0;
    return SQLITE_OK;
  }

  /* Search the hash table or tables for an entry matching page number
  ** pgno. Each iteration of the following for() loop searches one
  ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
  **
................................................................................
        break;
      }
    }
    assert( iRead==iRead2 );
  }
#endif

  /* If iRead is non-zero, then it is the log frame number that contains the
  ** required page. Read and return data from the log file.






  */
  if( iRead ){






    int sz;
    i64 iOffset;
    sz = pWal->hdr.szPage;
    sz = (sz&0xfe00) + ((sz&0x0001)<<16);
    testcase( sz<=32768 );
    testcase( sz>=65536 );
    iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
    *pInWal = 1;
    /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
    return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
  }

  *pInWal = 0;
  return SQLITE_OK;
}


/* 
** Return the size of the database in pages (or zero, if unknown).
*/
Pgno sqlite3WalDbsize(Wal *pWal){
  if( pWal && ALWAYS(pWal->readLock>=0) ){
    return pWal->hdr.nPage;
................................................................................
      rc = SQLITE_OK;
    }
  }

  /* Read the wal-index header. */
  if( rc==SQLITE_OK ){
    rc = walIndexReadHdr(pWal, &isChanged);



  }

  /* Copy data from the log to the database file. */
  if( rc==SQLITE_OK ){
    if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{







>
|
|







 







|
|








>







 







|
|
>

<
|
|

|


|
<
<







 







|







 







|
|
>
>
>
>
>
>
|
<
>
>
>
>
>
>
|
|
|
|
|
|
|
<
|
|
|
<
<
<
<
<







 







>
>
>







1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
....
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
....
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295

2296
2297
2298
2299
2300
2301
2302


2303
2304
2305
2306
2307
2308
2309
....
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
....
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397

2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413





2414
2415
2416
2417
2418
2419
2420
....
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.
    */
    if( pWal->hdr.nPage ){
      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
          "recovered %d frames from WAL file %s",
          pWal->hdr.mxFrame, pWal->zWalName
      );
    }
  }

recovery_error:
  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, nLock);
................................................................................
    u32 nBackfill = pInfo->nBackfill;

    /* Sync the WAL to disk */
    if( sync_flags ){
      rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
    }

    /* If the database may grow as a result of this checkpoint, hint
    ** about the eventual size of the db file to the VFS layer.
    */
    if( rc==SQLITE_OK ){
      i64 nReq = ((i64)mxPage * szPage);
      rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
      if( rc==SQLITE_OK && nSize<nReq ){
        sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
      }
    }


    /* Iterate through the contents of the WAL, copying data to the db file. */
    while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
      i64 iOffset;
      assert( walFramePgno(pWal, iFrame)==iDbpage );
      if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
      iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
................................................................................
  if( pWal->readLock>=0 ){
    walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
    pWal->readLock = -1;
  }
}

/*
** Search the wal file for page pgno. If found, set *piRead to the frame that
** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
** to zero.
**

** Return SQLITE_OK if successful, or an error code if an error occurs. If an
** error does occur, the final value of *piRead is undefined.
*/
int sqlite3WalFindFrame(
  Wal *pWal,                      /* WAL handle */
  Pgno pgno,                      /* Database page number to read data for */
  u32 *piRead                     /* OUT: Frame number (or zero) */


){
  u32 iRead = 0;                  /* If !=0, WAL frame to return data from */
  u32 iLast = pWal->hdr.mxFrame;  /* Last page in WAL for this reader */
  int iHash;                      /* Used to loop through N hash tables */

  /* This routine is only be called from within a read transaction. */
  assert( pWal->readLock>=0 || pWal->lockError );
................................................................................
  /* If the "last page" field of the wal-index header snapshot is 0, then
  ** no data will be read from the wal under any circumstances. Return early
  ** in this case as an optimization.  Likewise, if pWal->readLock==0, 
  ** then the WAL is ignored by the reader so return early, as if the 
  ** WAL were empty.
  */
  if( iLast==0 || pWal->readLock==0 ){
    *piRead = 0;
    return SQLITE_OK;
  }

  /* Search the hash table or tables for an entry matching page number
  ** pgno. Each iteration of the following for() loop searches one
  ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
  **
................................................................................
        break;
      }
    }
    assert( iRead==iRead2 );
  }
#endif

  *piRead = iRead;
  return SQLITE_OK;
}

/*
** Read the contents of frame iRead from the wal file into buffer pOut
** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
** error code otherwise.
*/

int sqlite3WalReadFrame(
  Wal *pWal,                      /* WAL handle */
  u32 iRead,                      /* Frame to read */
  int nOut,                       /* Size of buffer pOut in bytes */
  u8 *pOut                        /* Buffer to write page data to */
){
  int sz;
  i64 iOffset;
  sz = pWal->hdr.szPage;
  sz = (sz&0xfe00) + ((sz&0x0001)<<16);
  testcase( sz<=32768 );
  testcase( sz>=65536 );
  iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;

  /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
  return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
}






/* 
** Return the size of the database in pages (or zero, if unknown).
*/
Pgno sqlite3WalDbsize(Wal *pWal){
  if( pWal && ALWAYS(pWal->readLock>=0) ){
    return pWal->hdr.nPage;
................................................................................
      rc = SQLITE_OK;
    }
  }

  /* Read the wal-index header. */
  if( rc==SQLITE_OK ){
    rc = walIndexReadHdr(pWal, &isChanged);
    if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
      sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
    }
  }

  /* Copy data from the log to the database file. */
  if( rc==SQLITE_OK ){
    if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{

Changes to src/wal.h.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81

#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z)                   0
# define sqlite3WalLimit(x,y)
# define sqlite3WalClose(w,x,y,z)                0
# define sqlite3WalBeginReadTransaction(y,z)     0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalRead(v,w,x,y,z)               0
# define sqlite3WalDbsize(y)                     0
# define sqlite3WalBeginWriteTransaction(y)      0
# define sqlite3WalEndWriteTransaction(x)        0
# define sqlite3WalUndo(x,y,z)                   0
# define sqlite3WalSavepoint(y,z)
# define sqlite3WalSavepointUndo(y,z)            0
# define sqlite3WalFrames(u,v,w,x,y,z)           0
................................................................................
** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
** transaction and releases the lock.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
void sqlite3WalEndReadTransaction(Wal *pWal);

/* Read a page from the write-ahead log, if it is present. */
int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);


/* If the WAL is not empty, return the size of the database. */
Pgno sqlite3WalDbsize(Wal *pWal);

/* Obtain or release the WRITER lock. */
int sqlite3WalBeginWriteTransaction(Wal *pWal);
int sqlite3WalEndWriteTransaction(Wal *pWal);







<







 







|
>







27
28
29
30
31
32
33

34
35
36
37
38
39
40
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z)                   0
# define sqlite3WalLimit(x,y)
# define sqlite3WalClose(w,x,y,z)                0
# define sqlite3WalBeginReadTransaction(y,z)     0
# define sqlite3WalEndReadTransaction(z)

# define sqlite3WalDbsize(y)                     0
# define sqlite3WalBeginWriteTransaction(y)      0
# define sqlite3WalEndWriteTransaction(x)        0
# define sqlite3WalUndo(x,y,z)                   0
# define sqlite3WalSavepoint(y,z)
# define sqlite3WalSavepointUndo(y,z)            0
# define sqlite3WalFrames(u,v,w,x,y,z)           0
................................................................................
** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
** transaction and releases the lock.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
void sqlite3WalEndReadTransaction(Wal *pWal);

/* Read a page from the write-ahead log, if it is present. */
int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
int sqlite3WalReadFrame(Wal *, u32, int, u8 *);

/* If the WAL is not empty, return the size of the database. */
Pgno sqlite3WalDbsize(Wal *pWal);

/* Obtain or release the WRITER lock. */
int sqlite3WalBeginWriteTransaction(Wal *pWal);
int sqlite3WalEndWriteTransaction(Wal *pWal);

Changes to src/where.c.

2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
....
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
....
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404











2405
2406
2407
2408
2409
2410
2411
....
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
....
4160
4161
4162
4163
4164
4165
4166

4167
4168
4169
4170
4171
4172
4173
4174
4175
4176

4177
4178
4179
4180
4181
4182
4183
....
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854


























4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
  WhereClause *pWC = p->pWC;      /* The WHERE clause */
  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
  Table *pTab = pSrc->pTab;
  sqlite3_index_info *pIdxInfo;
  struct sqlite3_index_constraint *pIdxCons;
  struct sqlite3_index_constraint_usage *pUsage;
  WhereTerm *pTerm;
  int i, j, k;
  int nOrderBy;
  int sortOrder;                  /* Sort order for IN clauses */
  int bAllowIN;                   /* Allow IN optimizations */
  double rCost;

  /* Make sure wsFlags is initialized to some sane value. Otherwise, if the 
  ** malloc in allocateIndexInfo() fails and this function returns leaving
  ** wsFlags in an uninitialized state, the caller may behave unpredictably.
  */
................................................................................
      pIdxInfo->nOrderBy = 0;
    }
  
    if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
      return;
    }
  
    sortOrder = SQLITE_SO_ASC;
    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
      if( pUsage[i].argvIndex>0 ){
        j = pIdxCons->iTermOffset;
        pTerm = &pWC->a[j];
        p->cost.used |= pTerm->prereqRight;
        if( (pTerm->eOperator & WO_IN)!=0 ){
................................................................................
          if( pUsage[i].omit==0 ){
            /* Do not attempt to use an IN constraint if the virtual table
            ** says that the equivalent EQ constraint cannot be safely omitted.
            ** If we do attempt to use such a constraint, some rows might be
            ** repeated in the output. */
            break;
          }
          for(k=0; k<pIdxInfo->nOrderBy; k++){
            if( pIdxInfo->aOrderBy[k].iColumn==pIdxCons->iColumn ){
              sortOrder = pIdxInfo->aOrderBy[k].desc;
              break;
            }
          }
        }
      }
    }
    if( i>=pIdxInfo->nConstraint ) break;
  }











  
  /* If there is an ORDER BY clause, and the selected virtual table index
  ** does not satisfy it, increase the cost of the scan accordingly. This
  ** matches the processing for non-virtual tables in bestBtreeIndex().
  */
  rCost = pIdxInfo->estimatedCost;
  if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
................................................................................
  if( (SQLITE_BIG_DBL/((double)2))<rCost ){
    p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
  }else{
    p->cost.rCost = rCost;
  }
  p->cost.plan.u.pVtabIdx = pIdxInfo;
  if( pIdxInfo->orderByConsumed ){
    assert( sortOrder==0 || sortOrder==1 );
    p->cost.plan.wsFlags |= WHERE_ORDERED + sortOrder*WHERE_REVERSE;
    p->cost.plan.nOBSat = nOrderBy;
  }else{
    p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
  }
  p->cost.plan.nEq = 0;
  pIdxInfo->nOrderBy = nOrderBy;

................................................................................
  Parse *pParse;                  /* Parsing context */
  Vdbe *v;                        /* The prepared stmt under constructions */
  struct SrcList_item *pTabItem;  /* FROM clause term being coded */
  int addrBrk;                    /* Jump here to break out of the loop */
  int addrCont;                   /* Jump here to continue with next cycle */
  int iRowidReg = 0;        /* Rowid is stored in this register, if not zero */
  int iReleaseReg = 0;      /* Temp register to free before returning */


  pParse = pWInfo->pParse;
  v = pParse->pVdbe;
  pWC = pWInfo->pWC;
  pLevel = &pWInfo->a[iLevel];
  pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  iCur = pTabItem->iCursor;
  bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
  omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 
           && (wctrlFlags & WHERE_FORCE_TABLE)==0;


  /* Create labels for the "break" and "continue" instructions
  ** for the current loop.  Jump to addrBrk to break out of a loop.
  ** Jump to cont to go immediately to the next iteration of the
  ** loop.
  **
  ** When there is an IN operator, we also have a "addrNxt" label that
................................................................................
    assert( bRev==0 || bRev==1 );
    assert( omitTable==0 );
    pLevel->op = aStep[bRev];
    pLevel->p1 = iCur;
    pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
    pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
  }
  notReady &= ~getMask(pWC->pMaskSet, iCur);

  /* Insert code to test every subexpression that can be completely
  ** computed using the current set of tables.
  **
  ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
  ** the use of indices become tests that are evaluated against each row of
  ** the relevant input tables.
  */
  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
    Expr *pE;
    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
    testcase( pTerm->wtFlags & TERM_CODED );
    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
    if( (pTerm->prereqAll & notReady)!=0 ){
      testcase( pWInfo->untestedTerms==0
               && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
      pWInfo->untestedTerms = 1;
      continue;
    }
    pE = pTerm->pExpr;
    assert( pE!=0 );
    if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
      continue;
    }
    sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
    pTerm->wtFlags |= TERM_CODED;
  }



























  /* For a LEFT OUTER JOIN, generate code that will record the fact that
  ** at least one row of the right table has matched the left table.  
  */
  if( pLevel->iLeftJoin ){
    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
    VdbeComment((v, "record LEFT JOIN hit"));
    sqlite3ExprCacheClear(pParse);
    for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
      testcase( pTerm->wtFlags & TERM_VIRTUAL );  /* IMP: R-30575-11662 */
      testcase( pTerm->wtFlags & TERM_CODED );
      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
      if( (pTerm->prereqAll & notReady)!=0 ){
        assert( pWInfo->untestedTerms );
        continue;
      }
      assert( pTerm->pExpr );
      sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
      pTerm->wtFlags |= TERM_CODED;
    }
  }
  sqlite3ReleaseTempReg(pParse, iReleaseReg);

  return notReady;
}

#if defined(SQLITE_TEST)
/*
** The following variable holds a text description of query plan generated
** by the most recent call to sqlite3WhereBegin().  Each call to WhereBegin
** overwrites the previous.  This information is used for testing and







|

<







 







<







 







|
|
|
|
|
|





>
>
>
>
>
>
>
>
>
>
>







 







<
|







 







>










>







 







|













|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|










|







2271
2272
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
....
2371
2372
2373
2374
2375
2376
2377

2378
2379
2380
2381
2382
2383
2384
....
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
....
2431
2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
2445
....
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
....
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
  WhereClause *pWC = p->pWC;      /* The WHERE clause */
  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
  Table *pTab = pSrc->pTab;
  sqlite3_index_info *pIdxInfo;
  struct sqlite3_index_constraint *pIdxCons;
  struct sqlite3_index_constraint_usage *pUsage;
  WhereTerm *pTerm;
  int i, j;
  int nOrderBy;

  int bAllowIN;                   /* Allow IN optimizations */
  double rCost;

  /* Make sure wsFlags is initialized to some sane value. Otherwise, if the 
  ** malloc in allocateIndexInfo() fails and this function returns leaving
  ** wsFlags in an uninitialized state, the caller may behave unpredictably.
  */
................................................................................
      pIdxInfo->nOrderBy = 0;
    }
  
    if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
      return;
    }
  

    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
      if( pUsage[i].argvIndex>0 ){
        j = pIdxCons->iTermOffset;
        pTerm = &pWC->a[j];
        p->cost.used |= pTerm->prereqRight;
        if( (pTerm->eOperator & WO_IN)!=0 ){
................................................................................
          if( pUsage[i].omit==0 ){
            /* Do not attempt to use an IN constraint if the virtual table
            ** says that the equivalent EQ constraint cannot be safely omitted.
            ** If we do attempt to use such a constraint, some rows might be
            ** repeated in the output. */
            break;
          }
          /* A virtual table that is constrained by an IN clause may not
          ** consume the ORDER BY clause because (1) the order of IN terms
          ** is not necessarily related to the order of output terms and
          ** (2) Multiple outputs from a single IN value will not merge
          ** together.  */
          pIdxInfo->orderByConsumed = 0;
        }
      }
    }
    if( i>=pIdxInfo->nConstraint ) break;
  }

  /* The orderByConsumed signal is only valid if all outer loops collectively
  ** generate just a single row of output.
  */
  if( pIdxInfo->orderByConsumed ){
    for(i=0; i<p->i; i++){
      if( (p->aLevel[i].plan.wsFlags & WHERE_UNIQUE)==0 ){
        pIdxInfo->orderByConsumed = 0;
      }
    }
  }
  
  /* If there is an ORDER BY clause, and the selected virtual table index
  ** does not satisfy it, increase the cost of the scan accordingly. This
  ** matches the processing for non-virtual tables in bestBtreeIndex().
  */
  rCost = pIdxInfo->estimatedCost;
  if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
................................................................................
  if( (SQLITE_BIG_DBL/((double)2))<rCost ){
    p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
  }else{
    p->cost.rCost = rCost;
  }
  p->cost.plan.u.pVtabIdx = pIdxInfo;
  if( pIdxInfo->orderByConsumed ){

    p->cost.plan.wsFlags |= WHERE_ORDERED;
    p->cost.plan.nOBSat = nOrderBy;
  }else{
    p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
  }
  p->cost.plan.nEq = 0;
  pIdxInfo->nOrderBy = nOrderBy;

................................................................................
  Parse *pParse;                  /* Parsing context */
  Vdbe *v;                        /* The prepared stmt under constructions */
  struct SrcList_item *pTabItem;  /* FROM clause term being coded */
  int addrBrk;                    /* Jump here to break out of the loop */
  int addrCont;                   /* Jump here to continue with next cycle */
  int iRowidReg = 0;        /* Rowid is stored in this register, if not zero */
  int iReleaseReg = 0;      /* Temp register to free before returning */
  Bitmask newNotReady;      /* Return value */

  pParse = pWInfo->pParse;
  v = pParse->pVdbe;
  pWC = pWInfo->pWC;
  pLevel = &pWInfo->a[iLevel];
  pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  iCur = pTabItem->iCursor;
  bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
  omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 
           && (wctrlFlags & WHERE_FORCE_TABLE)==0;
  VdbeNoopComment((v, "Begin Join Loop %d", iLevel));

  /* Create labels for the "break" and "continue" instructions
  ** for the current loop.  Jump to addrBrk to break out of a loop.
  ** Jump to cont to go immediately to the next iteration of the
  ** loop.
  **
  ** When there is an IN operator, we also have a "addrNxt" label that
................................................................................
    assert( bRev==0 || bRev==1 );
    assert( omitTable==0 );
    pLevel->op = aStep[bRev];
    pLevel->p1 = iCur;
    pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
    pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
  }
  newNotReady = notReady & ~getMask(pWC->pMaskSet, iCur);

  /* Insert code to test every subexpression that can be completely
  ** computed using the current set of tables.
  **
  ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
  ** the use of indices become tests that are evaluated against each row of
  ** the relevant input tables.
  */
  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
    Expr *pE;
    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
    testcase( pTerm->wtFlags & TERM_CODED );
    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
    if( (pTerm->prereqAll & newNotReady)!=0 ){
      testcase( pWInfo->untestedTerms==0
               && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
      pWInfo->untestedTerms = 1;
      continue;
    }
    pE = pTerm->pExpr;
    assert( pE!=0 );
    if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
      continue;
    }
    sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
    pTerm->wtFlags |= TERM_CODED;
  }

  /* Insert code to test for implied constraints based on transitivity
  ** of the "==" operator.
  **
  ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
  ** and we are coding the t1 loop and the t2 loop has not yet coded,
  ** then we cannot use the "t1.a=t2.b" constraint, but we can code
  ** the implied "t1.a=123" constraint.
  */
  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
    Expr *pE;
    WhereTerm *pAlt;
    Expr sEq;
    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
    if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue;
    if( pTerm->leftCursor!=iCur ) continue;
    pE = pTerm->pExpr;
    assert( !ExprHasProperty(pE, EP_FromJoin) );
    assert( (pTerm->prereqRight & newNotReady)!=0 );
    pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
    if( pAlt==0 ) continue;
    VdbeNoopComment((v, "begin transitive constraint"));
    sEq = *pAlt->pExpr;
    sEq.pLeft = pE->pLeft;
    sqlite3ExprIfFalse(pParse, &sEq, addrCont, SQLITE_JUMPIFNULL);
  }

  /* For a LEFT OUTER JOIN, generate code that will record the fact that
  ** at least one row of the right table has matched the left table.  
  */
  if( pLevel->iLeftJoin ){
    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
    VdbeComment((v, "record LEFT JOIN hit"));
    sqlite3ExprCacheClear(pParse);
    for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
      testcase( pTerm->wtFlags & TERM_VIRTUAL );  /* IMP: R-30575-11662 */
      testcase( pTerm->wtFlags & TERM_CODED );
      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
      if( (pTerm->prereqAll & newNotReady)!=0 ){
        assert( pWInfo->untestedTerms );
        continue;
      }
      assert( pTerm->pExpr );
      sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
      pTerm->wtFlags |= TERM_CODED;
    }
  }
  sqlite3ReleaseTempReg(pParse, iReleaseReg);

  return newNotReady;
}

#if defined(SQLITE_TEST)
/*
** The following variable holds a text description of query plan generated
** by the most recent call to sqlite3WhereBegin().  Each call to WhereBegin
** overwrites the previous.  This information is used for testing and

Added test/btreefault.test.





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 2013 April 02
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains fault injection tests designed to test the btree.c 
# module.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix btreefault

do_test 1-pre1 {
  execsql {
    PRAGMA auto_vacuum = incremental;
    PRAGMA journal_mode = DELETE;
    CREATE TABLE t1(a PRIMARY KEY, b);
    INSERT INTO t1 VALUES(randomblob(1000), randomblob(100));
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    DELETE FROM t1 WHERE rowid%2;
  }
  faultsim_save_and_close
} {}

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
  set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY a" -1 DUMMY]
  sqlite3_step $::STMT
  sqlite3_step $::STMT
} -body {
  execsql { PRAGMA incremental_vacuum = 10 }
} -test {
  sqlite3_finalize $::STMT
  faultsim_test_result {0 {}} 
  faultsim_integrity_check
}

finish_test

Changes to test/dbstatus2.test.

36
37
38
39
40
41
42

43
44
45
46
47
48
49
proc db_write {db {reset 0}} {
  sqlite3_db_status $db CACHE_WRITE $reset
}

do_test 1.1 {
  db close
  sqlite3 db test.db

  expr {[file size test.db] / 1024}
} 6

do_test 1.2 {
  execsql { SELECT b FROM t1 WHERE a=2 }
  db_hit_miss db
} {{0 2 0} {0 4 0}}







>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
proc db_write {db {reset 0}} {
  sqlite3_db_status $db CACHE_WRITE $reset
}

do_test 1.1 {
  db close
  sqlite3 db test.db
  execsql { PRAGMA mmap_size = 0 }
  expr {[file size test.db] / 1024}
} 6

do_test 1.2 {
  execsql { SELECT b FROM t1 WHERE a=2 }
  db_hit_miss db
} {{0 2 0} {0 4 0}}

Changes to test/exclusive2.test.

20
21
22
23
24
25
26








27
28
29
30
31
32
33
#
do_not_use_codec

ifcapable {!pager_pragmas} {
  finish_test
  return
}









# This module does not work right if the cache spills at unexpected
# moments.  So disable the soft-heap-limit.
#
sqlite3_soft_heap_limit 0

proc pagerChangeCounter {filename new {fd ""}} {







>
>
>
>
>
>
>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#
do_not_use_codec

ifcapable {!pager_pragmas} {
  finish_test
  return
}

# Tests in this file verify that locking_mode=exclusive causes SQLite to
# use cached pages even if the database is changed on disk. This doesn't
# work with mmap.
if {[permutation]=="mmap"} {
  finish_test
  return
}

# This module does not work right if the cache spills at unexpected
# moments.  So disable the soft-heap-limit.
#
sqlite3_soft_heap_limit 0

proc pagerChangeCounter {filename new {fd ""}} {

Changes to test/fts3aux1.test.

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460


461


























































462


do_execsql_test 3.1.1 {
  CREATE VIRTUAL TABLE t2 USING fts4;
}

do_catchsql_test 3.1.2 {
  CREATE VIRTUAL TABLE terms2 USING fts4aux;
} {1 {wrong number of arguments to fts4aux constructor}}
do_catchsql_test 3.1.3 {
  CREATE VIRTUAL TABLE terms2 USING fts4aux(t2, t2);
} {1 {wrong number of arguments to fts4aux constructor}}

do_execsql_test 3.2.1 {
  CREATE VIRTUAL TABLE terms3 USING fts4aux(does_not_exist)
}
do_catchsql_test 3.2.2 {
  SELECT * FROM terms3
} {1 {SQL logic error or missing database}}
................................................................................
}

#-------------------------------------------------------------------------
# The following tests check that fts4aux can handle an fts table with an
# odd name (one that requires quoting for use in SQL statements). And that
# the argument to the fts4aux constructor is properly dequoted before use.
#
#
do_execsql_test 5.1 {
  CREATE VIRTUAL TABLE "abc '!' def" USING fts4(x, y);
  INSERT INTO "abc '!' def" VALUES('XX', 'YY');

  CREATE VIRTUAL TABLE terms3 USING fts4aux("abc '!' def");
  SELECT * FROM terms3;
} {xx * 1 1 xx 0 1 1 yy * 1 1 yy 1 1 1}

do_execsql_test 5.2 {
  CREATE VIRTUAL TABLE "%%^^%%" USING fts4aux('abc ''!'' def');
  SELECT * FROM "%%^^%%";
} {xx * 1 1 xx 0 1 1 yy * 1 1 yy 1 1 1}






























































finish_test








|


|







 







<













>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
...
440
441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522

do_execsql_test 3.1.1 {
  CREATE VIRTUAL TABLE t2 USING fts4;
}

do_catchsql_test 3.1.2 {
  CREATE VIRTUAL TABLE terms2 USING fts4aux;
} {1 {invalid arguments to fts4aux constructor}}
do_catchsql_test 3.1.3 {
  CREATE VIRTUAL TABLE terms2 USING fts4aux(t2, t2);
} {1 {invalid arguments to fts4aux constructor}}

do_execsql_test 3.2.1 {
  CREATE VIRTUAL TABLE terms3 USING fts4aux(does_not_exist)
}
do_catchsql_test 3.2.2 {
  SELECT * FROM terms3
} {1 {SQL logic error or missing database}}
................................................................................
}

#-------------------------------------------------------------------------
# The following tests check that fts4aux can handle an fts table with an
# odd name (one that requires quoting for use in SQL statements). And that
# the argument to the fts4aux constructor is properly dequoted before use.
#

do_execsql_test 5.1 {
  CREATE VIRTUAL TABLE "abc '!' def" USING fts4(x, y);
  INSERT INTO "abc '!' def" VALUES('XX', 'YY');

  CREATE VIRTUAL TABLE terms3 USING fts4aux("abc '!' def");
  SELECT * FROM terms3;
} {xx * 1 1 xx 0 1 1 yy * 1 1 yy 1 1 1}

do_execsql_test 5.2 {
  CREATE VIRTUAL TABLE "%%^^%%" USING fts4aux('abc ''!'' def');
  SELECT * FROM "%%^^%%";
} {xx * 1 1 xx 0 1 1 yy * 1 1 yy 1 1 1}

#-------------------------------------------------------------------------
# Test that we can create an fts4aux table in the temp database.
#
forcedelete test.db2
do_execsql_test 6.1 {
  CREATE VIRTUAL TABLE ft1 USING fts4(x, y);
  INSERT INTO ft1 VALUES('a b', 'c d');
  INSERT INTO ft1 VALUES('e e', 'c d');
  INSERT INTO ft1 VALUES('a a', 'b b');
  CREATE VIRTUAL TABLE temp.aux1 USING fts4aux(main, ft1);
  SELECT * FROM aux1;
} {
    a * 2 3 a 0 2 3 
    b * 2 3 b 0 1 1 b 1 1 2 
    c * 2 2 c 1 2 2 
    d * 2 2 d 1 2 2 
    e * 1 2 e 0 1 2
}

do_execsql_test 6.2 {
  ATTACH 'test.db2' AS att;
  CREATE VIRTUAL TABLE att.ft1 USING fts4(x, y);
  INSERT INTO att.ft1 VALUES('v w', 'x y');
  INSERT INTO att.ft1 VALUES('z z', 'x y');
  INSERT INTO att.ft1 VALUES('v v', 'w w');
  CREATE VIRTUAL TABLE temp.aux2 USING fts4aux(att, ft1);
  SELECT * FROM aux2;
} {
    v * 2 3 v 0 2 3 
    w * 2 3 w 0 1 1 w 1 1 2 
    x * 2 2 x 1 2 2 
    y * 2 2 y 1 2 2 
    z * 1 2 z 0 1 2
}

foreach {tn q res1 res2} {
  1  { SELECT * FROM %%% WHERE term = 'a' } {a * 2 3 a 0 2 3} {}
  2  { SELECT * FROM %%% WHERE term = 'x' } {} {x * 2 2 x 1 2 2} 

  3  { SELECT * FROM %%% WHERE term >= 'y' } 
     {} {y * 2 2 y 1 2 2 z * 1 2 z 0 1 2}

  4  { SELECT * FROM %%% WHERE term <= 'c' } 
     {a * 2 3 a 0 2 3 b * 2 3 b 0 1 1 b 1 1 2 c * 2 2 c 1 2 2} {}
} {
  set sql1 [string map {%%% aux1} $q]
  set sql2 [string map {%%% aux2} $q]

  do_execsql_test 7.$tn.1 $sql1 $res1
  do_execsql_test 7.$tn.2 $sql2 $res2
}

do_test 8.1 {
  catchsql { CREATE VIRTUAL TABLE att.aux3 USING fts4aux(main, ft1) }
} {1 {invalid arguments to fts4aux constructor}}

do_test 8.2 {
  execsql {DETACH att}
  catchsql { SELECT * FROM aux2 }
} {1 {SQL logic error or missing database}}

finish_test

Added test/fts3tok1.test.



























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 2013 April 22
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the "fts3tokenize" virtual table
# that is part of the FTS3 module.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !fts3 { finish_test ; return }
set ::testprefix fts3tok1

#-------------------------------------------------------------------------
# Simple test cases. Using the default (simple) tokenizer.
#
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts3tokenize(simple);
  CREATE VIRTUAL TABLE t2 USING fts3tokenize();
  CREATE VIRTUAL TABLE t3 USING fts3tokenize(simple, '', 'xyz ');
}

foreach {tn tbl} {1 t1 2 t2 3 t3} {
  do_execsql_test 1.$tn.1 "SELECT * FROM $tbl WHERE input = 'one two three'" {
    {one two three} one   0  3 0 
    {one two three} two   4  7 1 
    {one two three} three 8 13 2
  }

  do_execsql_test 1.$tn.2 "
    SELECT token FROM $tbl WHERE input = 'OnE tWo tHrEe'
  " {
    one two three
  }
}

do_execsql_test 1.4 {
  SELECT token FROM t3 WHERE input = '1x2x3x'
} {1 2 3}

do_execsql_test 1.5 {
  SELECT token FROM t1 WHERE input = '1x2x3x'
} {1x2x3x}

do_execsql_test 1.6 {
  SELECT token FROM t3 WHERE input = '1''2x3x'
} {1'2 3}

do_execsql_test 1.7 {
  SELECT token FROM t3 WHERE input = ''
} {}

do_execsql_test 1.8 {
  SELECT token FROM t3 WHERE input = NULL
} {}

do_execsql_test 1.9 {
  SELECT * FROM t3 WHERE input = 123
} {123 123 0 3 0}

do_execsql_test 1.10 {
  SELECT * FROM t1 WHERE input = 'a b c' AND token = 'b';
} {
  {a b c} b 2 3 1
}

do_execsql_test 1.11 {
  SELECT * FROM t1 WHERE token = 'b' AND input = 'a b c';
} {
  {a b c} b 2 3 1
}

do_execsql_test 1.12 {
  SELECT * FROM t1 WHERE input < 'b' AND input = 'a b c';
} {
  {a b c} a 0 1 0 
  {a b c} b 2 3 1 
  {a b c} c 4 5 2
}

do_execsql_test 1.13.1 {
  CREATE TABLE c1(x);
  INSERT INTO c1(x) VALUES('a b c');
  INSERT INTO c1(x) VALUES('d e f');
}
breakpoint
do_execsql_test 1.13.2 {
  SELECT * FROM c1, t1 WHERE input = x AND c1.rowid=t1.rowid;
} {
  {a b c} {a b c} a 0 1 0 
  {d e f} {d e f} e 2 3 1 
}


#-------------------------------------------------------------------------
# Error cases.
#
do_catchsql_test 2.0 {
  CREATE VIRTUAL TABLE tX USING fts3tokenize(nosuchtokenizer);
} {1 {unknown tokenizer: nosuchtokenizer}}

proc fts3_tokenizer {args} { return 1 }
db function fts3_tokenizer -argcount 1 fts3_tokenizer
do_catchsql_test 2.1 {
  CREATE VIRTUAL TABLE tX USING fts3tokenize(simple);
} {1 {vtable constructor failed: tX}}

db close
sqlite3 db test.db
do_catchsql_test 2.2 {
  CREATE VIRTUAL TABLE t4 USING fts3tokenize;
  SELECT * FROM t4;
} {1 {SQL logic error or missing database}}


finish_test


Added test/fts3tok_err.test.



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 2013 April 22
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the "fts3tokenize" virtual table
# that is part of the FTS3 module.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !fts3 { finish_test ; return }
set ::testprefix fts3tok_err


faultsim_save_and_close
do_faultsim_test fts3tok_err-1 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { CREATE VIRTUAL TABLE t1 USING fts3tokenize("simple"); }
} -test {
  faultsim_test_result {0 {}} 
}

do_test fts3tok_err-2.prep {
  faultsim_delete_and_reopen 
  execsql { CREATE VIRTUAL TABLE t1 USING fts3tokenize("simple"); }
  faultsim_save_and_close
} {}

do_faultsim_test fts3tok_err-2 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { SELECT token FROM t1 WHERE input = 'A galaxy far, far away' } 
} -test {
  faultsim_test_result {0 {a galaxy far far away}} 
}


finish_test


Changes to test/func.test.

1269
1270
1271
1272
1273
1274
1275

1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
} {1}
do_test func-29.3 {
  db close
  sqlite3 db test.db
  sqlite3_db_status db CACHE_MISS 1
  db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
} {integer null real blob text}

do_test func-29.4 {
  set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
  if {$x>100} {set x many}
  set x
} {many}

do_test func-29.5 {
  db close
  sqlite3 db test.db
  sqlite3_db_status db CACHE_MISS 1
  db eval {SELECT sum(length(x)) FROM t29}
} {1000009}
do_test func-29.6 {







>
|
|
|
|
|
>







1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
} {1}
do_test func-29.3 {
  db close
  sqlite3 db test.db
  sqlite3_db_status db CACHE_MISS 1
  db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
} {integer null real blob text}
if {[permutation] != "mmap"} {
  do_test func-29.4 {
    set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
    if {$x>100} {set x many}
    set x
  } {many}
}
do_test func-29.5 {
  db close
  sqlite3 db test.db
  sqlite3_db_status db CACHE_MISS 1
  db eval {SELECT sum(length(x)) FROM t29}
} {1000009}
do_test func-29.6 {

Changes to test/incrblob.test.

119
120
121
122
123
124
125

126
127
128
129
130
131
132
...
145
146
147
148
149
150
151

152
153
154
155
156
157
158
...
167
168
169
170
171
172
173

174
175
176
177
178
179
180
...
196
197
198
199
200
201
202

203
204
205
206
207
208
209
    }
  }

  db close
  forcedelete test.db test.db-journal

  sqlite3 db test.db

  execsql "PRAGMA auto_vacuum = $AutoVacuumMode"

  do_test incrblob-2.$AutoVacuumMode.1 {
    set ::str [string repeat abcdefghij 2900]
    execsql {
      BEGIN;
      CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER);
................................................................................
    } $AutoVacuumMode
  }

  do_test incrblob-2.$AutoVacuumMode.3 {
    # Open and close the db to make sure the page cache is empty.
    db close
    sqlite3 db test.db

  
    # Read the last 20 bytes of the blob via a blob handle.
    set ::blob [db incrblob blobs v 1]
    seek $::blob -20 end
    set ::fragment [read $::blob]
    close $::blob
  
................................................................................
    string range [db one {SELECT v FROM blobs}] end-19 end
  } $::fragment

  do_test incrblob-2.$AutoVacuumMode.5 {
    # Open and close the db to make sure the page cache is empty.
    db close
    sqlite3 db test.db

  
    # Write the second-to-last 20 bytes of the blob via a blob handle.
    #
    set ::blob [db incrblob blobs v 1]
    seek $::blob -40 end
    puts -nonewline $::blob "1234567890abcdefghij"
    flush $::blob
................................................................................
    string range [db one {SELECT v FROM blobs}] end-39 end-20
  } "1234567890abcdefghij"

  do_test incrblob-2.$AutoVacuumMode.8 {
    # Open and close the db to make sure the page cache is empty.
    db close
    sqlite3 db test.db


    execsql { SELECT i FROM blobs } 
  } {45}

  do_test incrblob-2.$AutoVacuumMode.9 {
    nRead db
  } [expr $AutoVacuumMode ? 4 : 30]







>







 







>







 







>







 







>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
    }
  }

  db close
  forcedelete test.db test.db-journal

  sqlite3 db test.db
  execsql "PRAGMA mmap_size = 0"
  execsql "PRAGMA auto_vacuum = $AutoVacuumMode"

  do_test incrblob-2.$AutoVacuumMode.1 {
    set ::str [string repeat abcdefghij 2900]
    execsql {
      BEGIN;
      CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER);
................................................................................
    } $AutoVacuumMode
  }

  do_test incrblob-2.$AutoVacuumMode.3 {
    # Open and close the db to make sure the page cache is empty.
    db close
    sqlite3 db test.db
    execsql "PRAGMA mmap_size = 0"
  
    # Read the last 20 bytes of the blob via a blob handle.
    set ::blob [db incrblob blobs v 1]
    seek $::blob -20 end
    set ::fragment [read $::blob]
    close $::blob
  
................................................................................
    string range [db one {SELECT v FROM blobs}] end-19 end
  } $::fragment

  do_test incrblob-2.$AutoVacuumMode.5 {
    # Open and close the db to make sure the page cache is empty.
    db close
    sqlite3 db test.db
    execsql "PRAGMA mmap_size = 0"
  
    # Write the second-to-last 20 bytes of the blob via a blob handle.
    #
    set ::blob [db incrblob blobs v 1]
    seek $::blob -40 end
    puts -nonewline $::blob "1234567890abcdefghij"
    flush $::blob
................................................................................
    string range [db one {SELECT v FROM blobs}] end-39 end-20
  } "1234567890abcdefghij"

  do_test incrblob-2.$AutoVacuumMode.8 {
    # Open and close the db to make sure the page cache is empty.
    db close
    sqlite3 db test.db
    execsql { PRAGMA mmap_size = 0 }

    execsql { SELECT i FROM blobs } 
  } {45}

  do_test incrblob-2.$AutoVacuumMode.9 {
    nRead db
  } [expr $AutoVacuumMode ? 4 : 30]

Changes to test/loadext.test.

135
136
137
138
139
140
141
142
143
144
145
146
147



148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#
do_test loadext-2.1 {
  forcedelete ${testextension}xx
  set rc [catch {
    sqlite3_load_extension db "${testextension}xx"
  } msg]
  list $rc $msg
} [list 1 [format $dlerror_nosuchfile ${testextension}xx]]

# Try to load an extension for which the file is not a shared object
#
do_test loadext-2.2 {
  set fd [open "${testextension}xx" w]



  puts $fd blah
  close $fd
  set rc [catch {
    sqlite3_load_extension db "${testextension}xx"
  } msg]
  set expected_error_pattern [format $dlerror_notadll ${testextension}xx]
  list $rc [string match $expected_error_pattern $msg]
} [list 1 1]


# Try to load an extension for which the file is present but the
# entry point is not.
#
do_test loadext-2.3 {
  set rc [catch {
    sqlite3_load_extension db $testextension icecream
................................................................................
  set res [catchsql {
    SELECT load_extension($::testextension)
  }]
  if {$::tcl_platform(os) eq "Darwin"} {
    regsub {0x[1234567890abcdefABCDEF]*} $res XXX res
  }
  set res
} [list 1 [format $dlerror_nosymbol $testextension sqlite3_extension_init]]
do_test loadext-3.3 {
  catchsql {
    SELECT load_extension($::testextension,'testloadext_init')
  }
} {0 {{}}}
do_test loadext-3.4 {
  catchsql {







|




|
>
>
>



|

<
<
|
>







 







|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155


156
157
158
159
160
161
162
163
164
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#
do_test loadext-2.1 {
  forcedelete ${testextension}xx
  set rc [catch {
    sqlite3_load_extension db "${testextension}xx"
  } msg]
  list $rc $msg
} /[list 1 [format $dlerror_nosuchfile ${testextension}xx.*]]/

# Try to load an extension for which the file is not a shared object
#
do_test loadext-2.2 {
  set fd [open "./notasharedlib.so" w]
  puts $fd blah
  close $fd
  set fd [open "./notasharedlib.dll" w]
  puts $fd blah
  close $fd
  set rc [catch {
    sqlite3_load_extension db "./notasharedlib"
  } msg]


  list $rc $msg
} /[list 1 [format $dlerror_notadll ./notasharedlib.*]]/

# Try to load an extension for which the file is present but the
# entry point is not.
#
do_test loadext-2.3 {
  set rc [catch {
    sqlite3_load_extension db $testextension icecream
................................................................................
  set res [catchsql {
    SELECT load_extension($::testextension)
  }]
  if {$::tcl_platform(os) eq "Darwin"} {
    regsub {0x[1234567890abcdefABCDEF]*} $res XXX res
  }
  set res
} /[list 1 [format $dlerror_nosymbol $testextension sqlite3_.*_init]]/
do_test loadext-3.3 {
  catchsql {
    SELECT load_extension($::testextension,'testloadext_init')
  }
} {0 {{}}}
do_test loadext-3.4 {
  catchsql {

Changes to test/malloc_common.tcl.

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# by -test scripts.
#
proc faultsim_test_result_int {args} {
  upvar testrc testrc testresult testresult testnfail testnfail
  set t [list $testrc $testresult]
  set r $args
  if { ($testnfail==0 && $t != [lindex $r 0]) || [lsearch $r $t]<0 } {
    error "nfail=$testnfail rc=$testrc result=$testresult"
  }
}

#--------------------------------------------------------------------------
# Usage do_one_faultsim_test NAME ?OPTIONS...? 
#
# The first argument, <test number>, is used as a prefix of the test names







|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# by -test scripts.
#
proc faultsim_test_result_int {args} {
  upvar testrc testrc testresult testresult testnfail testnfail
  set t [list $testrc $testresult]
  set r $args
  if { ($testnfail==0 && $t != [lindex $r 0]) || [lsearch $r $t]<0 } {
    error "nfail=$testnfail rc=$testrc result=$testresult list=$r"
  }
}

#--------------------------------------------------------------------------
# Usage do_one_faultsim_test NAME ?OPTIONS...? 
#
# The first argument, <test number>, is used as a prefix of the test names

Added test/mmap1.test.



























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# 2013 March 20
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !mmap {
  finish_test
  return
}
source $testdir/lock_common.tcl
set testprefix mmap1

proc nRead {db} {
  set bt [btree_from_db $db]
  db_enter $db
  array set stats [btree_pager_stats $bt]
  db_leave $db
  # puts [array get stats]
  return $stats(read)
}

proc register_rblob_code {dbname seed} {
  return [subst -nocommands {
    set ::rcnt $seed
    proc rblob {n} {
      set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF]
      set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]] 
      string range [string repeat [set str] [expr [set n]/4]] 1 [set n]
    }
    $dbname func rblob rblob
  }]
}

foreach {t mmap_size nRead c2init} {
  1.1 { PRAGMA mmap_size = 67108864 }   4 {PRAGMA mmap_size = 0}
  1.2 { PRAGMA mmap_size =    53248 } 150 {PRAGMA mmap_size = 0}
  1.3 { PRAGMA mmap_size =        0 } 344 {PRAGMA mmap_size = 0}
  1.4 { PRAGMA mmap_size = 67108864 }   4 {PRAGMA mmap_size = 67108864 }
  1.5 { PRAGMA mmap_size =    53248 } 150 {PRAGMA mmap_size = 67108864 }
  1.6 { PRAGMA mmap_size =        0 } 344 {PRAGMA mmap_size = 67108864 }
} {
  do_multiclient_test tn {
    sql1 {PRAGMA page_size=1024}
    sql1 $mmap_size
    sql2 $c2init

    code2 [register_rblob_code db2 0]

    sql2 {
      PRAGMA page_size=1024;
      PRAGMA auto_vacuum = 1;
      CREATE TABLE t1(a, b, UNIQUE(a, b));
      INSERT INTO t1 VALUES(rblob(500), rblob(500));
      INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    2
      INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    4
      INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    8
      INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   16
      INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   32
    }
    do_test $t.$tn.1 {
      sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
    } {32 ok 77}

    # Have connection 2 shrink the file. Check connection 1 can still read it.
    sql2 { DELETE FROM t1 WHERE rowid%2; }
    do_test $t.$tn.2 {
      sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
    } {16 ok 42}

    # Have connection 2 grow the file. Check connection 1 can still read it.
    sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
    do_test $t.$tn.3 {
      sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
    } {32 ok 79}

    # Have connection 2 grow the file again. Check connection 1 is still ok.
    sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
    do_test $t.$tn.4 {
      sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
    } {64 ok 149}

    # Check that the number of pages read by connection 1 indicates that the
    # "PRAGMA mmap_size" command worked.
    do_test $t.$tn.5 { nRead db } $nRead
  }
}

set ::rcnt 0
proc rblob {n} {
  set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF]
  set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]] 
  string range [string repeat $str [expr $n/4]] 1 $n
}

reset_db
db func rblob rblob

do_execsql_test 2.1 {
  PRAGMA auto_vacuum = 1;
  PRAGMA mmap_size = 67108864;
  PRAGMA journal_mode = wal;
  CREATE TABLE t1(a, b, UNIQUE(a, b));
  INSERT INTO t1 VALUES(rblob(500), rblob(500));
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    2
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    4
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    8
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   16
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --   32
  PRAGMA wal_checkpoint;
} {67108864 wal 0 103 103}

do_execsql_test 2.2 {
  PRAGMA auto_vacuum;
  SELECT count(*) FROM t1;
} {1 32}

do_test 2.3 {
  sqlite3 db2 test.db
  db2 func rblob rblob
  db2 eval { 
    DELETE FROM t1 WHERE (rowid%4);
    PRAGMA wal_checkpoint;
  }
  db2 eval { 
    INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    16
    SELECT count(*) FROM t1;
  }
} {16}

do_execsql_test 2.4 {
  PRAGMA wal_checkpoint;
} {0 24 24}

db2 close
reset_db
db func rblob rblob
do_execsql_test 3.1 {
  PRAGMA auto_vacuum = 1;

  CREATE TABLE t1(a, b, UNIQUE(a, b));
  INSERT INTO t1 VALUES(rblob(500), rblob(500));
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    2
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    4
  INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; --    8

  CREATE TABLE t2(a, b, UNIQUE(a, b));
  INSERT INTO t2 SELECT * FROM t1;
} {}

do_test 3.2 {
  set nRow 0
  db eval {SELECT * FROM t2 ORDER BY a, b} {
    if {$nRow==4} { db eval { DELETE FROM t1 } }
    incr nRow
  }
  set nRow
} {8}

#-------------------------------------------------------------------------
# Ensure that existing cursors using xFetch() pages see changes made
# to rows using the incrblob API.
#
reset_db
set aaa [string repeat a 400]
set bbb [string repeat b 400]
set ccc [string repeat c 400]
set ddd [string repeat d 400]
set eee [string repeat e 400]

do_execsql_test 4.1 {
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES($aaa);
  INSERT INTO t1 VALUES($bbb);
  INSERT INTO t1 VALUES($ccc);
  INSERT INTO t1 VALUES($ddd);
  SELECT * FROM t1;
  BEGIN;
} [list $aaa $bbb $ccc $ddd]

do_test 4.2 {
  set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy]
  sqlite3_step $::STMT
  sqlite3_column_text $::STMT 0
} $aaa

do_test 4.3 {
  foreach r {2 3 4} {
    set fd [db incrblob t1 x $r]
    puts -nonewline $fd $eee
    close $fd
  }

  set res [list]
  while {"SQLITE_ROW" == [sqlite3_step $::STMT]} {
    lappend res [sqlite3_column_text $::STMT 0]
  }
  set res
} [list $eee $eee $eee]

do_test 4.4 {
  sqlite3_finalize $::STMT
} SQLITE_OK

do_execsql_test 4.5 { COMMIT }

#-------------------------------------------------------------------------
# Ensure that existing cursors holding xFetch() references are not 
# confused if those pages are moved to make way for the root page of a
# new table or index.
#
reset_db
do_execsql_test 5.1 {
  PRAGMA auto_vacuum = 2;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES($aaa);
  INSERT INTO t1 VALUES($bbb);
  INSERT INTO t1 VALUES($ccc);
  INSERT INTO t1 VALUES($ddd);

  PRAGMA auto_vacuum;
  SELECT * FROM t1;
} [list 2 $aaa $bbb $ccc $ddd]

do_test 5.2 {
  set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy]
  sqlite3_step $::STMT
  sqlite3_column_text $::STMT 0
} $aaa

do_execsql_test 5.3 {
  CREATE TABLE t2(x);
  INSERT INTO t2 VALUES('tricked you!');
  INSERT INTO t2 VALUES('tricked you!');
}

do_test 5.4 {
  sqlite3_step $::STMT
  sqlite3_column_text $::STMT 0
} $bbb

do_test 5.5 {
  sqlite3_finalize $::STMT
} SQLITE_OK

#-------------------------------------------------------------------------
# Test various mmap_size settings.
#
foreach {tn1 mmap1 mmap2} {
     1 6144       167773
     2 18432      140399
     3 43008      401302
     4 92160      253899
     5 190464          2
     6 387072     752431
     7 780288     291143
     8 1566720    594306
     9 3139584    829137
     10 6285312   793963
     11 12576768 1015590
} {
  do_multiclient_test tn {
    sql1 {
      CREATE TABLE t1(a PRIMARY KEY);
      CREATE TABLE t2(x);
      INSERT INTO t2 VALUES('');
    }

    code1 [register_rblob_code db  0]
    code2 [register_rblob_code db2 444]

    sql1 "PRAGMA mmap_size = $mmap1"
    sql2 "PRAGMA mmap_size = $mmap2"

    do_test $tn1.$tn { 
      for {set i 1} {$i <= 100} {incr i} {
        if {$i % 2} {
          set c1 sql1
            set c2 sql2
        } else {
          set c1 sql2
            set c2 sql1
        }

        $c1 {
          INSERT INTO t1 VALUES( rblob(5000) );
          UPDATE t2 SET x = (SELECT md5sum(a) FROM t1);
        }

        set res [$c2 { 
            SELECT count(*) FROM t1;
            SELECT x == (SELECT md5sum(a) FROM t1) FROM t2;
            PRAGMA integrity_check;
        }]
        if {$res != [list $i 1 ok]} {
          do_test $tn1.$tn.$i {
            set ::res
          } [list $i 1 ok]
        }
      }
      set res 1
    } {1}
  }
}


finish_test

Added test/mmap2.test.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 2013 March 20
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file tests the effect of the mmap() or mremap() system calls 
# returning an error on the library. 
#
# If either mmap() or mremap() fails, SQLite should log an error 
# message, then continue accessing the database using read() and 
# write() exclusively.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix mmap2

if {$::tcl_platform(platform)!="unix" || [test_syscall defaultvfs] != "unix"} {
  finish_test
  return
}
ifcapable !mmap {
  finish_test
  return
}

db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
  if {[string match os_unix.c* $msg]} {
    lappend ::log $msg 
  }
}

foreach syscall {mmap mremap} {
  test_syscall uninstall 
  if {[catch {test_syscall install $syscall}]} continue

  for {set i 1} {$i < 20} {incr i} {
    reset_db

    test_syscall fault $i 1
    test_syscall errno $syscall ENOMEM
    set ::log ""

    do_execsql_test 1.$syscall.$i.1 {
      CREATE TABLE t1(a, b, UNIQUE(a, b));
      INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000));
      INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
      INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
      INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
      INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
      INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
      INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    }

    set nFail [test_syscall fault 0 0]

    do_execsql_test 1.$syscall.$i.2 {
      SELECT count(*) FROM t1;
      PRAGMA integrity_check;
    } {64 ok}

    do_test 1.$syscall.$i.3 {
      expr {$nFail==0 || $nFail==1}
    } {1}

    do_test 1.$syscall.$i.4.nFail=$nFail {
      regexp ".*${syscall}.*" $::log
    } [expr $nFail>0]
  }
}

db close
test_syscall uninstall 
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize
finish_test

Changes to test/pager1.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
....
1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
....
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
....
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
....
2518
2519
2520
2521
2522
2523
2524
2525


































































































































































































































































































2526

#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl


# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec

#
................................................................................

#-------------------------------------------------------------------------
# Test that regardless of the value returned by xSectorSize(), the
# minimum effective sector-size is 512 and the maximum 65536 bytes.
#
testvfs tv -default 1
foreach sectorsize {

    32   64   128   256   512   1024   2048 
    4096 8192 16384 32768 65536 131072 262144
} {
  tv sectorsize $sectorsize
  tv devchar {}
  set eff $sectorsize
  if {$sectorsize < 512}   { set eff 512 }
................................................................................
      BEGIN;
        CREATE TABLE t1(a, b);
        CREATE TABLE t2(a, b);
        CREATE TABLE t3(a, b);
      COMMIT;
    }
    file size test.db-journal
  } [expr $sectorsize > 65536 ? 65536 : $sectorsize]

  do_test pager1-10.$sectorsize.2 {
    execsql { 
      INSERT INTO t3 VALUES(a_string(300), a_string(300));
      INSERT INTO t3 SELECT * FROM t3;        /*  2 */
      INSERT INTO t3 SELECT * FROM t3;        /*  4 */
      INSERT INTO t3 SELECT * FROM t3;        /*  8 */
................................................................................
      SAVEPOINT abc;
        CREATE TABLE t1(a, b);
      ROLLBACK TO abc;
    COMMIT;
  }
  db close
} {}
breakpoint
do_test pager1-25-2 {
  faultsim_delete_and_reopen
  execsql {
    SAVEPOINT abc;
      CREATE TABLE t1(a, b);
    ROLLBACK TO abc;
    COMMIT;
................................................................................
  } {1 {disk I/O error}}

  do_test pager1-33.2 {
    file rename bak-journal test.db-journal
    execsql { SELECT * FROM t1 }
  } {one two}
}



































































































































































































































































































finish_test








>







 







>







 







|







 







<







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
....
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
....
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
....
2241
2242
2243
2244
2245
2246
2247

2248
2249
2250
2251
2252
2253
2254
....
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl
set testprefix pager1

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec

#
................................................................................

#-------------------------------------------------------------------------
# Test that regardless of the value returned by xSectorSize(), the
# minimum effective sector-size is 512 and the maximum 65536 bytes.
#
testvfs tv -default 1
foreach sectorsize {
    16
    32   64   128   256   512   1024   2048 
    4096 8192 16384 32768 65536 131072 262144
} {
  tv sectorsize $sectorsize
  tv devchar {}
  set eff $sectorsize
  if {$sectorsize < 512}   { set eff 512 }
................................................................................
      BEGIN;
        CREATE TABLE t1(a, b);
        CREATE TABLE t2(a, b);
        CREATE TABLE t3(a, b);
      COMMIT;
    }
    file size test.db-journal
  } [expr $sectorsize > 65536 ? 65536 : ($sectorsize<32 ? 512 : $sectorsize)]

  do_test pager1-10.$sectorsize.2 {
    execsql { 
      INSERT INTO t3 VALUES(a_string(300), a_string(300));
      INSERT INTO t3 SELECT * FROM t3;        /*  2 */
      INSERT INTO t3 SELECT * FROM t3;        /*  4 */
      INSERT INTO t3 SELECT * FROM t3;        /*  8 */
................................................................................
      SAVEPOINT abc;
        CREATE TABLE t1(a, b);
      ROLLBACK TO abc;
    COMMIT;
  }
  db close
} {}

do_test pager1-25-2 {
  faultsim_delete_and_reopen
  execsql {
    SAVEPOINT abc;
      CREATE TABLE t1(a, b);
    ROLLBACK TO abc;
    COMMIT;
................................................................................
  } {1 {disk I/O error}}

  do_test pager1-33.2 {
    file rename bak-journal test.db-journal
    execsql { SELECT * FROM t1 }
  } {one two}
}

#-------------------------------------------------------------------------
# Test that appending pages to the database file then moving those pages
# to the free-list before the transaction is committed does not cause
# an error.
#
foreach {tn pragma strsize} {
  1 { PRAGMA mmap_size = 0 } 2400
  2 { }                       2400
  3 { PRAGMA mmap_size = 0 } 4400
  4 { }                       4400
} {
  reset_db
  db func a_string a_string
  db eval $pragma
  do_execsql_test 34.$tn.1 {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
  do_execsql_test 34.$tn.2 {
    BEGIN;
    INSERT INTO t1 VALUES(2, a_string($strsize));
    DELETE FROM t1 WHERE oid=2;
    COMMIT;
    PRAGMA integrity_check;
  } {ok}
}

#-------------------------------------------------------------------------
#
reset_db
do_test 35 {
  sqlite3 db test.db

  execsql {
    CREATE TABLE t1(x, y);
    PRAGMA journal_mode = WAL;
    INSERT INTO t1 VALUES(1, 2);
  }

  execsql {
    BEGIN;
      CREATE TABLE t2(a, b);
  }

  hexio_write test.db-shm [expr 16*1024] [string repeat 0055 8192]
  catchsql ROLLBACK
} {0 {}}

do_multiclient_test tn {
  sql1 {
    PRAGMA auto_vacuum = 0;
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
  }

  do_test 36.$tn.1 { 
    sql2 { PRAGMA max_page_count = 2 }
    list [catch { sql2 { CREATE TABLE t2(x) } } msg] $msg
  } {1 {database or disk is full}}

  sql1 { PRAGMA checkpoint_fullfsync = 1 }
  sql1 { CREATE TABLE t2(x) }

  do_test 36.$tn.2 { 
    sql2 { INSERT INTO t2 VALUES('xyz') }
    list [catch { sql2 { CREATE TABLE t3(x) } } msg] $msg
  } {1 {database or disk is full}}
}

forcedelete test1 test2
foreach {tn uri} {
  1   {file:?mode=memory&cache=shared}
  2   {file:one?mode=memory&cache=shared}
  3   {file:test1?cache=shared}
  4   {file:test2?another=parameter&yet=anotherone}
} {
  do_test 37.$tn {
    catch { db close }
    sqlite3_shutdown
    sqlite3_config_uri 1
    sqlite3 db $uri

    db eval {
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES(1);
      SELECT * FROM t1;
    }
  } {1}

  do_execsql_test 37.$tn.2 {
    VACUUM;
    SELECT * FROM t1;
  } {1}

  db close
  sqlite3_shutdown
  sqlite3_config_uri 0
}

do_test 38.1 {
  catch { db close }
  forcedelete test.db
  set fd [open test.db w]
  puts $fd "hello world"
  close $fd
  sqlite3 db test.db
  catchsql { CREATE TABLE t1(x) }
} {1 {file is encrypted or is not a database}}
do_test 38.2 {
  catch { db close }
  forcedelete test.db
} {}

do_test 39.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum = 1;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES('xxx');
    INSERT INTO t1 VALUES('two');
    INSERT INTO t1 VALUES(randomblob(400));
    INSERT INTO t1 VALUES(randomblob(400));
    INSERT INTO t1 VALUES(randomblob(400));
    INSERT INTO t1 VALUES(randomblob(400));
    BEGIN;
    UPDATE t1 SET x = 'one' WHERE rowid=1;
  }
  set ::stmt [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy]
  sqlite3_step $::stmt
  sqlite3_column_text $::stmt 0
} {one}
do_test 39.2 {
  execsql { CREATE TABLE t2(x) }
  sqlite3_step $::stmt
  sqlite3_column_text $::stmt 0
} {two}
do_test 39.3 {
  sqlite3_finalize $::stmt
  execsql COMMIT
} {}

do_execsql_test 39.4 {
  PRAGMA auto_vacuum = 2;
  CREATE TABLE t3(x);
  CREATE TABLE t4(x);

  DROP TABLE t2;
  DROP TABLE t3;
  DROP TABLE t4;
}
do_test 39.5 {
  db close
  sqlite3 db test.db
  execsql {
    PRAGMA cache_size = 1;
    PRAGMA incremental_vacuum;
    PRAGMA integrity_check;
  }
} {ok}

do_test 40.1 {
  reset_db
  execsql {
    PRAGMA auto_vacuum = 1;
    CREATE TABLE t1(x PRIMARY KEY);
    INSERT INTO t1 VALUES(randomblob(1200));
    PRAGMA page_count;
  }
} {6}
do_test 40.2 {
  execsql {
    INSERT INTO t1 VALUES(randomblob(1200));
    INSERT INTO t1 VALUES(randomblob(1200));
    INSERT INTO t1 VALUES(randomblob(1200));
  }
} {}
do_test 40.3 {
  db close
  sqlite3 db test.db
  execsql {
    PRAGMA cache_size = 1;
    CREATE TABLE t2(x);
    PRAGMA integrity_check;
  }
} {ok}

do_test 41.1 {
  reset_db
  execsql {
    CREATE TABLE t1(x PRIMARY KEY);
    INSERT INTO t1 VALUES(randomblob(200));
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
  }
} {}
do_test 41.2 {
  testvfs tv -default 1
  tv sectorsize 16384;
  tv devchar [list]
  db close
  sqlite3 db test.db
  execsql {
    PRAGMA cache_size = 1;
    DELETE FROM t1 WHERE rowid%4;
    PRAGMA integrity_check;
  }
} {ok}
db close
tv delete

set pending_prev [sqlite3_test_control_pending_byte 0x1000000]
do_test 42.1 {
  reset_db
  execsql {
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  }
  db close
  sqlite3_test_control_pending_byte 0x0010000
  sqlite3 db test.db
  db eval { PRAGMA mmap_size = 0 }
  catchsql { SELECT sum(length(y)) FROM t1 }
} {1 {database disk image is malformed}}
do_test 42.2 {
  reset_db
  execsql {
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  }
  db close

  testvfs tv -default 1
  tv sectorsize 16384;
  tv devchar [list]
  sqlite3 db test.db -vfs tv
  execsql { UPDATE t1 SET x = randomblob(200) }
} {}
db close
tv delete
sqlite3_test_control_pending_byte $pending_prev

do_test 43.1 {
  reset_db
  execsql {
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
    CREATE TABLE t2(x, y);
    INSERT INTO t2 VALUES(1, 2);
    CREATE TABLE t3(x, y);
    INSERT INTO t3 VALUES(1, 2);
  }
  db close
  sqlite3 db test.db

  db eval { PRAGMA mmap_size = 0 }
  db eval { SELECT * FROM t1 }
  sqlite3_db_status db CACHE_MISS 0
} {0 2 0}

do_test 43.2 {
  db eval { SELECT * FROM t2 }
  sqlite3_db_status db CACHE_MISS 1
} {0 3 0}

do_test 43.3 {
  db eval { SELECT * FROM t3 }
  sqlite3_db_status db CACHE_MISS 0
} {0 1 0}

finish_test

Changes to test/pager2.test.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
143
144
145
146
147
148
149
150


















151
  }
}
db close
tv delete


#-------------------------------------------------------------------------
#
# pager2-2.1: Test a ROLLBACK with journal_mode=off.
# pager2-2.2: Test shrinking the database (auto-vacuum) with 
#             journal_mode=off
#
do_test pager2-2.1 {
  faultsim_delete_and_reopen
  execsql {
................................................................................
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(zeroblob(5000), zeroblob(5000));
    DELETE FROM t1;
    PRAGMA incremental_vacuum;
  }
  file size test.db
} {3072}



















finish_test







<







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

114
115
116
117
118
119
120

121
122
123
124
125
126
127
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  }
}
db close
tv delete


#-------------------------------------------------------------------------

# pager2-2.1: Test a ROLLBACK with journal_mode=off.
# pager2-2.2: Test shrinking the database (auto-vacuum) with 
#             journal_mode=off
#
do_test pager2-2.1 {
  faultsim_delete_and_reopen
  execsql {
................................................................................
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(zeroblob(5000), zeroblob(5000));
    DELETE FROM t1;
    PRAGMA incremental_vacuum;
  }
  file size test.db
} {3072}

#-------------------------------------------------------------------------
# Test that shared in-memory databases seem to work.
#
db close
do_test pager2-3.1 {
  forcedelete test.db
  sqlite3_shutdown
  sqlite3_config_uri 1

  sqlite3 db1 {file:test.db?mode=memory&cache=shared}
  sqlite3 db2 {file:test.db?mode=memory&cache=shared}
  sqlite3 db3 test.db

  db1 eval { CREATE TABLE t1(a, b) }
  db2 eval { INSERT INTO t1 VALUES(1, 2) }
  list [catch { db3 eval { INSERT INTO t1 VALUES(3, 4) } } msg] $msg
} {1 {no such table: t1}}

finish_test

Changes to test/pagerfault.test.

1242
1243
1244
1245
1246
1247
1248











































































































































































































































































































1249
1250
} -test {
  catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) }
  catch { close $::channel }
  catchsql { ROLLBACK }
  faultsim_integrity_check
}












































































































































































































































































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
} -test {
  catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) }
  catch { close $::channel }
  catchsql { ROLLBACK }
  faultsim_integrity_check
}


#-------------------------------------------------------------------------
#
do_test pagerfault-28-pre {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    PRAGMA page_size = 512;

    PRAGMA journal_mode = wal;
    PRAGMA wal_autocheckpoint = 0;
    PRAGMA cache_size = 100000;

    BEGIN;
      CREATE TABLE t2(a UNIQUE, b UNIQUE);
      INSERT INTO t2 VALUES( a_string(800), a_string(800) );
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
    COMMIT;
    CREATE TABLE t1(a PRIMARY KEY, b);
  }
  expr {[file size test.db-shm] >= 96*1024}
} {1}
faultsim_save_and_close

do_faultsim_test pagerfault-28a -faults oom* -prep {
  faultsim_restore_and_reopen
  execsql { PRAGMA mmap_size=0 }

  sqlite3 db2 test.db
  db2 eval { SELECT count(*) FROM t2 }

  db func a_string a_string
  execsql { 
    BEGIN;
      INSERT INTO t1 VALUES(a_string(2000), a_string(2000));
      INSERT INTO t1 VALUES(a_string(2000), a_string(2000));
  }
  set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY a" -1 DUMMY]
  sqlite3_step $::STMT
} -body {
  execsql { ROLLBACK }
} -test {
  db2 close
  sqlite3_finalize $::STMT
  catchsql { ROLLBACK }
  faultsim_integrity_check
}

faultsim_restore_and_reopen
sqlite3 db2 test.db
db2 eval {SELECT count(*) FROM t2}
db close

do_faultsim_test pagerfault-28b -faults oom* -prep {
  sqlite3 db test.db
} -body {
  execsql { SELECT count(*) FROM t2 }
} -test {
  faultsim_test_result {0 2048}
  db close
}

db2 close

#-------------------------------------------------------------------------
# Try this:
#
#    1) Put the pager in ERROR state (error during rollback)
#
#    2) Next time the connection is used inject errors into all xWrite() and
#       xUnlock() calls. This causes the hot-journal rollback to fail and
#       the pager to declare its locking state UNKNOWN.
#
#    3) Same again.
#
#    4a) Stop injecting errors. Allow the rollback to succeed. Check that
#        the database is Ok. Or, 
#
#    4b) Close and reopen the db. Check that the db is Ok.
#
proc custom_injectinstall {} {
  testvfs custom -default true
  custom filter {xWrite xUnlock}
}
proc custom_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  custom delete
}
proc custom_injectstart {iFail} {
  custom ioerr $iFail 1
}
proc custom_injectstop {} {
  custom ioerr
}
set ::FAULTSIM(custom)          [list      \
  -injectinstall   custom_injectinstall    \
  -injectstart     custom_injectstart      \
  -injectstop      custom_injectstop       \
  -injecterrlist   {{1 {disk I/O error}}}  \
  -injectuninstall custom_injectuninstall  \
]

do_test pagerfault-29-pre {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA cache_size = 5;

    BEGIN;
      CREATE TABLE t2(a UNIQUE, b UNIQUE);
      INSERT INTO t2 VALUES( a_string(800), a_string(800) );
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
      INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
    COMMIT;
  }
  expr {[file size test.db] >= 50*1024}
} {1}
faultsim_save_and_close
foreach {tn tt} {
  29 { catchsql ROLLBACK }
  30 { db close ; sqlite3 db test.db }
} {
  do_faultsim_test pagerfault-$tn -faults custom -prep {
    faultsim_restore_and_reopen
      db func a_string a_string
      execsql {
        PRAGMA cache_size = 5;
        BEGIN;
        UPDATE t2 SET a = a_string(799);
      }
  } -body {
    catchsql ROLLBACK
    catchsql ROLLBACK
    catchsql ROLLBACK
  } -test {
    eval $::tt
    if {"ok" != [db one {PRAGMA integrity_check}]} {
      error "integrity check failed"
    }
  }
}

do_test pagerfault-31-pre {
  sqlite3_shutdown
  sqlite3_config_uri 1
} {SQLITE_OK}
do_faultsim_test pagerfault-31 -faults oom* -body {
  sqlite3 db {file:one?mode=memory&cache=shared}
  db eval {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    SELECT * FROM t1;
  }
} -test {
  faultsim_test_result {0 1} {1 {}}
  catch { db close }
}
sqlite3_shutdown
sqlite3_config_uri 0

do_test pagerfault-32-pre {
  reset_db
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES('one');
  }
} {}
faultsim_save_and_close

do_faultsim_test pagerfault-32 -prep {
  faultsim_restore_and_reopen
  db eval { SELECT * FROM t1; }
} -body {
  execsql { SELECT * FROM t1; }
} -test {
  faultsim_test_result {0 one}
}
sqlite3_shutdown
sqlite3_config_uri 0

do_faultsim_test pagerfault-33a -prep {
  sqlite3 db :memory:
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
} -body {
  execsql { VACUUM }
} -test {
  faultsim_test_result {0 {}}
} 
do_faultsim_test pagerfault-33b -prep {
  sqlite3 db ""
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
} -body {
  execsql { VACUUM }
} -test {
  faultsim_test_result {0 {}}
} 

do_test pagerfault-34-pre {
  reset_db
  execsql {
    CREATE TABLE t1(x PRIMARY KEY);
  }
} {}
faultsim_save_and_close
do_faultsim_test pagerfault-34 -prep {
  faultsim_restore_and_reopen
  execsql {
    BEGIN;
      INSERT INTO t1 VALUES( randomblob(4000) );
      DELETE FROM t1;
  }
} -body {
  execsql COMMIT
} -test {
  faultsim_test_result {0 {}}
} 

do_test pagerfault-35-pre {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t1(x PRIMARY KEY, y);
    INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  }
  faultsim_save_and_close
} {}
testvfs tv -default 1
tv sectorsize 8192;
tv devchar [list]
do_faultsim_test pagerfault-35 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { UPDATE t1 SET x=randomblob(200) }
} -test {
  faultsim_test_result {0 {}}
}
catch {db close}
tv delete

sqlite3_shutdown
sqlite3_config_uri 1
do_test pagerfault-36-pre {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t1(x PRIMARY KEY, y);
    INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
  }
  faultsim_save_and_close
} {}
do_faultsim_test pagerfault-36 -prep {
  faultsim_restore
  sqlite3 db file:test.db?cache=shared
  sqlite3 db2 file:test.db?cache=shared
  db2 eval {
    BEGIN;
    SELECT count(*) FROM sqlite_master;
  }
  db eval {
    PRAGMA cache_size = 1;
    BEGIN;
      UPDATE t1 SET x = randomblob(200);
  }
} -body {
  execsql ROLLBACK db
} -test {
  catch { db eval {UPDATE t1 SET x = randomblob(200)} }
  faultsim_test_result {0 {}}
  catch { db close }
  catch { db2 close }
}

sqlite3_shutdown
sqlite3_config_uri 0

finish_test

Changes to test/pageropt.test.

83
84
85
86
87
88
89





90
91
92
93
94
95
96
97
98
99
100
101
102
    SELECT hex(x) FROM t1
  }
} [list 0 0 0 $blobcontent]

# But if the other thread modifies the database, then the cache
# must refill.
#





do_test pageropt-1.5 {
  db2 eval {CREATE TABLE t2(y)}
  pagercount_sql {
    SELECT hex(x) FROM t1
  }
} [list 6 0 0 $blobcontent]
do_test pageropt-1.6 {
  pagercount_sql {
    SELECT hex(x) FROM t1
  }
} [list 0 0 0 $blobcontent]

# Verify that the last page of an overflow chain is not read from







>
>
>
>
>





|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    SELECT hex(x) FROM t1
  }
} [list 0 0 0 $blobcontent]

# But if the other thread modifies the database, then the cache
# must refill.
#
ifcapable mmap {
  set x [expr {[permutation]=="mmap" ? 1 : 6}]
} else {
  set x 6
}
do_test pageropt-1.5 {
  db2 eval {CREATE TABLE t2(y)}
  pagercount_sql {
    SELECT hex(x) FROM t1
  }
} [list $x 0 0 $blobcontent]
do_test pageropt-1.6 {
  pagercount_sql {
    SELECT hex(x) FROM t1
  }
} [list 0 0 0 $blobcontent]

# Verify that the last page of an overflow chain is not read from

Changes to test/permutations.test.

136
137
138
139
140
141
142








143
144
145
146
147
148
149
test_suite "veryquick" -prefix "" -description {
  "Very" quick test suite. Runs in less than 5 minutes on a workstation. 
  This test suite is the same as the "quick" tests, except that some files
  that test malloc and IO errors are omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault*
]









test_suite "valgrind" -prefix "" -description {
  Run the "veryquick" test suite with a couple of multi-process tests (that
  fail under valgrind) omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
] -initialize {







>
>
>
>
>
>
>
>







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
test_suite "veryquick" -prefix "" -description {
  "Very" quick test suite. Runs in less than 5 minutes on a workstation. 
  This test suite is the same as the "quick" tests, except that some files
  that test malloc and IO errors are omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault*
]

test_suite "mmap" -prefix "mm-" -description {
  Similar to veryquick. Except with memory mapping disabled.
} -presql {
  pragma mmap_size = 268435456;
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* -include malloc.test
]

test_suite "valgrind" -prefix "" -description {
  Run the "veryquick" test suite with a couple of multi-process tests (that
  fail under valgrind) omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
] -initialize {

Added test/resolver01.test.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 2013-04-13
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file tests features of the name resolver (the component that
# figures out what identifiers in the SQL statement refer to) that
# were fixed by ticket [2500cdb9be]
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test resolver01-1.1 {
  catchsql {
    CREATE TABLE t1(x, y); INSERT INTO t1 VALUES(11,22);
    CREATE TABLE t2(y, z); INSERT INTO t2 VALUES(33,44);
    SELECT 1 AS y FROM t1, t2 ORDER BY y;
  }
} {0 1}
do_test resolver01-1.2 {
  catchsql {
    SELECT 2 AS y FROM t1, t2 ORDER BY y COLLATE nocase;
  }
} {0 2}
do_test resolver01-1.3 {
  catchsql {
    SELECT 3 AS y FROM t1, t2 ORDER BY +y;
  }
} {0 3}


finish_test

Changes to test/speed1p.test.

20
21
22
23
24
25
26


27
28
29
30
31
32
33
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#sqlite3_config_scratch 29000 1
set old_lookaside [sqlite3_config_lookaside 2048 300]
#sqlite3_config_pagecache 1024 11000
set testdir [file dirname $argv0]
source $testdir/tester.tcl
speed_trial_init speed1



# Set a uniform random seed
expr srand(0)

# The number_name procedure below converts its argment (an integer)
# into a string which is the English-language name for that number.
#
# Example:
................................................................................
    CREATE INDEX i2a ON t2(a);
    CREATE INDEX i2b ON t2(b);
  }
  execsql {
    SELECT name FROM sqlite_master ORDER BY 1;
  }
} {i2a i2b t1 t2}


# 50000 INSERTs on an unindexed table
#
set list {}
for {set i 1} {$i<=50000} {incr i} {
  set r [expr {int(rand()*500000)}]
  set x [number_name $r]







>
>







 







<







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
75
76
77
78
79
80
81

82
83
84
85
86
87
88
#sqlite3_config_scratch 29000 1
set old_lookaside [sqlite3_config_lookaside 2048 300]
#sqlite3_config_pagecache 1024 11000
set testdir [file dirname $argv0]
source $testdir/tester.tcl
speed_trial_init speed1

sqlite3_memdebug_vfs_oom_test 0

# Set a uniform random seed
expr srand(0)

# The number_name procedure below converts its argment (an integer)
# into a string which is the English-language name for that number.
#
# Example:
................................................................................
    CREATE INDEX i2a ON t2(a);
    CREATE INDEX i2b ON t2(b);
  }
  execsql {
    SELECT name FROM sqlite_master ORDER BY 1;
  }
} {i2a i2b t1 t2}


# 50000 INSERTs on an unindexed table
#
set list {}
for {set i 1} {$i<=50000} {incr i} {
  set r [expr {int(rand()*500000)}]
  set x [number_name $r]

Changes to test/syscall.test.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#-------------------------------------------------------------------------
# Tests for the xNextSystemCall method.
#
foreach s {
    open close access getcwd stat fstat ftruncate
    fcntl read pread write pwrite fchmod fallocate
    pread64 pwrite64 unlink openDirectory mkdir rmdir 
    statvfs fchown umask
} {
  if {[test_syscall exists $s]} {lappend syscall_list $s}
}
do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list]

#-------------------------------------------------------------------------
# This test verifies that if a call to open() fails and errno is set to







|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#-------------------------------------------------------------------------
# Tests for the xNextSystemCall method.
#
foreach s {
    open close access getcwd stat fstat ftruncate
    fcntl read pread write pwrite fchmod fallocate
    pread64 pwrite64 unlink openDirectory mkdir rmdir 
    statvfs fchown umask mmap munmap mremap
} {
  if {[test_syscall exists $s]} {lappend syscall_list $s}
}
do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list]

#-------------------------------------------------------------------------
# This test verifies that if a call to open() fails and errno is set to

Changes to test/sysfault.test.

239
240
241
242
243
244
245



























246

247


    SELECT length(a) + length(b) FROM t1;
    COMMIT;
  }
} -test {
  faultsim_test_result {0 20000}
}




























finish_test











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    SELECT length(a) + length(b) FROM t1;
    COMMIT;
  }
} -test {
  faultsim_test_result {0 20000}
}

#-------------------------------------------------------------------------
# Test errors in mmap().
#
proc vfsfault_install {} { 
  test_syscall reset
  test_syscall install {mmap}
}

faultsim_delete_and_reopen
execsql {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
}
faultsim_save_and_close

do_faultsim_test 4 -faults vfsfault-* -prep {
  faultsim_restore_and_reopen
  file_control_chunksize_test db main 8192
  execsql { 
    PRAGMA mmap_size = 1000000;
  }
} -body {
  test_syscall errno mmap     EACCES

  execsql {
    SELECT * FROM t1;
  }
} -test {
  faultsim_test_result {0 {1 2}} {1 {disk I/O error}}
}

finish_test

Changes to test/tester.tcl.

458
459
460
461
462
463
464

465
466
467
468
469
470
471
...
491
492
493
494
495
496
497












498
499
500
501
502
503
504
...
785
786
787
788
789
790
791



792
793
794
795
796
797
798
# counters in the parent interpreter.
#
if {0==[info exists ::SLAVE]} {
  set TC(errors)    0
  set TC(count)     0
  set TC(fail_list) [list]
  set TC(omit_list) [list]


  proc set_test_counter {counter args} {
    if {[llength $args]} {
      set ::TC($counter) [lindex $args 0]
    }
    set ::TC($counter)
  }
................................................................................

  set nFail [set_test_counter errors]
  if {$nFail>=$::cmdlinearg(maxerror)} {
    puts "*** Giving up..."
    finalize_testing
  }
}













# Increment the number of tests run
#
proc incr_ntest {} {
  set_test_counter count [expr [set_test_counter count] + 1]
}

................................................................................
  sqlite3_soft_heap_limit 0
  set nTest [incr_ntest]
  set nErr [set_test_counter errors]

  puts "$nErr errors out of $nTest tests"
  if {$nErr>0} {
    puts "Failures on these tests: [set_test_counter fail_list]"



  }
  run_thread_tests 1
  if {[llength $omitList]>0} {
    puts "Omitted test cases:"
    set prec {}
    foreach {rec} [lsort $omitList] {
      if {$rec==$prec} continue







>







 







>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
...
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
...
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
# counters in the parent interpreter.
#
if {0==[info exists ::SLAVE]} {
  set TC(errors)    0
  set TC(count)     0
  set TC(fail_list) [list]
  set TC(omit_list) [list]
  set TC(warn_list) [list]

  proc set_test_counter {counter args} {
    if {[llength $args]} {
      set ::TC($counter) [lindex $args 0]
    }
    set ::TC($counter)
  }
................................................................................

  set nFail [set_test_counter errors]
  if {$nFail>=$::cmdlinearg(maxerror)} {
    puts "*** Giving up..."
    finalize_testing
  }
}

# Remember a warning message to be displayed at the conclusion of all testing
#
proc warning {msg {append 1}} {
  puts "Warning: $msg"
  set warnList [set_test_counter warn_list]
  if {$append} {
    lappend warnList $msg
  }
  set_test_counter warn_list $warnList
}


# Increment the number of tests run
#
proc incr_ntest {} {
  set_test_counter count [expr [set_test_counter count] + 1]
}

................................................................................
  sqlite3_soft_heap_limit 0
  set nTest [incr_ntest]
  set nErr [set_test_counter errors]

  puts "$nErr errors out of $nTest tests"
  if {$nErr>0} {
    puts "Failures on these tests: [set_test_counter fail_list]"
  }
  foreach warning [set_test_counter warn_list] {
    puts "Warning: $warning"
  }
  run_thread_tests 1
  if {[llength $omitList]>0} {
    puts "Omitted test cases:"
    set prec {}
    foreach {rec} [lsort $omitList] {
      if {$rec==$prec} continue

Changes to test/tkt2822.test.

204
205
206
207
208
209
210



211
212
213
214
215
216
217
218
219
220
221
222
223
  execsql {
    SELECT a AS "b" FROM t3 ORDER BY [B];
  }
} {1 9}

# In "ORDER BY +b" the term is now an expression rather than
# a label.  It therefore matches by rule (3) instead of rule (2).



# 
do_test tkt2822-5.5 {
  execsql {
    SELECT a AS b FROM t3 ORDER BY +b;
  }
} {9 1}

# Tests for rule 2 in compound queries
#
do_test tkt2822-6.1 {
  execsql {
    CREATE TABLE t6a(p,q);
    INSERT INTO t6a VALUES(1,8);







>
>
>





|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  execsql {
    SELECT a AS "b" FROM t3 ORDER BY [B];
  }
} {1 9}

# In "ORDER BY +b" the term is now an expression rather than
# a label.  It therefore matches by rule (3) instead of rule (2).
#
# 2013-04-13:  This is busted.  Changed to conform to PostgreSQL and
# MySQL and Oracle behavior.
# 
do_test tkt2822-5.5 {
  execsql {
    SELECT a AS b FROM t3 ORDER BY +b;
  }
} {1 9}

# Tests for rule 2 in compound queries
#
do_test tkt2822-6.1 {
  execsql {
    CREATE TABLE t6a(p,q);
    INSERT INTO t6a VALUES(1,8);

Changes to test/wal.test.

723
724
725
726
727
728
729



730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
....
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size 41 1024]]
do_test wal-11.9 {
  db close
  list [expr [file size test.db]/1024] [log_deleted test.db-wal]
} {37 1}
sqlite3_wal db test.db



do_test wal-11.10 {
  execsql {
    PRAGMA cache_size = 10;
    BEGIN;
      INSERT INTO t1 SELECT blob(900) FROM t1;   -- 32
      SELECT count(*) FROM t1;
  }
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size 37 1024]]
do_test wal-11.11 {
  execsql {
      SELECT count(*) FROM t1;
    ROLLBACK;
    SELECT count(*) FROM t1;
  }
} {32 16}
do_test wal-11.12 {
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size 37 1024]]
do_test wal-11.13 {
  execsql {
    INSERT INTO t1 VALUES( blob(900) );
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {17 ok}
do_test wal-11.14 {
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size 37 1024]]


#-------------------------------------------------------------------------
# This block of tests, wal-12.*, tests the fix for a problem that 
# could occur if a log that is a prefix of an older log is written 
# into a reused log file.
#
................................................................................
  set ::log [list]
  faultsim_restore_and_reopen
  execsql { SELECT * FROM t1 }
} {1 2 3 4}
set nPage [expr 2+$AUTOVACUUM]
do_test wal-23.4 { 
  set ::log 
} [list SQLITE_OK "Recovered $nPage frames from WAL file $walfile"]


ifcapable autovacuum {
  # This block tests that if the size of a database is reduced by a 
  # transaction (because of an incremental or auto-vacuum), that no
  # data is written to the WAL file for the truncated pages as part
  # of the commit. e.g. if a transaction reduces the size of a database







>
>
>








|









|









|







 







|







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
....
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size 41 1024]]
do_test wal-11.9 {
  db close
  list [expr [file size test.db]/1024] [log_deleted test.db-wal]
} {37 1}
sqlite3_wal db test.db
set nWal 39
if {[permutation]!="mmap"} {set nWal 37}
ifcapable !mmap {set nWal 37}
do_test wal-11.10 {
  execsql {
    PRAGMA cache_size = 10;
    BEGIN;
      INSERT INTO t1 SELECT blob(900) FROM t1;   -- 32
      SELECT count(*) FROM t1;
  }
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size $nWal 1024]]
do_test wal-11.11 {
  execsql {
      SELECT count(*) FROM t1;
    ROLLBACK;
    SELECT count(*) FROM t1;
  }
} {32 16}
do_test wal-11.12 {
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size $nWal 1024]]
do_test wal-11.13 {
  execsql {
    INSERT INTO t1 VALUES( blob(900) );
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {17 ok}
do_test wal-11.14 {
  list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size $nWal 1024]]


#-------------------------------------------------------------------------
# This block of tests, wal-12.*, tests the fix for a problem that 
# could occur if a log that is a prefix of an older log is written 
# into a reused log file.
#
................................................................................
  set ::log [list]
  faultsim_restore_and_reopen
  execsql { SELECT * FROM t1 }
} {1 2 3 4}
set nPage [expr 2+$AUTOVACUUM]
do_test wal-23.4 { 
  set ::log 
} [list SQLITE_NOTICE "recovered $nPage frames from WAL file $walfile"]


ifcapable autovacuum {
  # This block tests that if the size of a database is reduced by a 
  # transaction (because of an incremental or auto-vacuum), that no
  # data is written to the WAL file for the truncated pages as part
  # of the commit. e.g. if a transaction reduces the size of a database

Changes to test/wal5.test.

231
232
233
234
235
236
237









238
239
240
241
242
243
244
245
...
339
340
341
342
343
344
345
346
    } {}
    do_test 2.3.$tn.2 { file_page_counts } {1 3 1 3}
    do_test 2.3.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2}
    do_test 2.3.$tn.4 { sql1 { INSERT INTO t1 VALUES(3, 4) } } {}
    do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {}
    do_test 2.3.$tn.6 { file_page_counts } {1 4 1 4}
    do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 4 3}









    do_test 2.3.$tn.8 { file_page_counts } {1 4 2 4}
  }

  # Check that checkpoints block on the correct locks. And respond correctly
  # if they cannot obtain those locks. There are three locks that a checkpoint
  # may block on (in the following order):
  #
  #   1. The writer lock: FULL and RESTART checkpoints block until any writer
................................................................................

    do_test 3.$tn.6 { code3 { do_wal_checkpoint db3 } } {0 0 0}
  }
}


finish_test








>
>
>
>
>
>
>
>
>
|







 







<
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
...
348
349
350
351
352
353
354

    } {}
    do_test 2.3.$tn.2 { file_page_counts } {1 3 1 3}
    do_test 2.3.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2}
    do_test 2.3.$tn.4 { sql1 { INSERT INTO t1 VALUES(3, 4) } } {}
    do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {}
    do_test 2.3.$tn.6 { file_page_counts } {1 4 1 4}
    do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 4 3}

    # The checkpoint above only writes page 1 of the db file. The other
    # page (page 2) is locked by the read-transaction opened by the
    # [sql2] commmand above. So normally, the db is 1 page in size here.
    # However, in mmap() mode, the db is pre-allocated to 2 pages at the
    # start of the checkpoint, even though page 2 cannot be written.
    set nDb 2
    if {[permutation]!="mmap"} {set nDb 1}
    ifcapable !mmap {set nDb 1}
    do_test 2.3.$tn.8 { file_page_counts } [list $nDb 4 2 4]
  }

  # Check that checkpoints block on the correct locks. And respond correctly
  # if they cannot obtain those locks. There are three locks that a checkpoint
  # may block on (in the following order):
  #
  #   1. The writer lock: FULL and RESTART checkpoints block until any writer
................................................................................

    do_test 3.$tn.6 { code3 { do_wal_checkpoint db3 } } {0 0 0}
  }
}


finish_test

Changes to test/walfault.test.

544
545
546
547
548
549
550


































551



552

553
  }
} -test {
  faultsim_test_result {0 {0 9 9}}
  faultsim_integrity_check
  set nRow [db eval {SELECT count(*) FROM abc}]
  if {!(($nRow==2 && $testrc) || $nRow==3)} { error "Bad db content" }
}


































finish_test





finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>

544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  }
} -test {
  faultsim_test_result {0 {0 9 9}}
  faultsim_integrity_check
  set nRow [db eval {SELECT count(*) FROM abc}]
  if {!(($nRow==2 && $testrc) || $nRow==3)} { error "Bad db content" }
}

#-------------------------------------------------------------------------
# Test fault-handling when switching out of exclusive-locking mode.
#
do_test walfault-14-pre {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA auto_vacuum = 0;
    PRAGMA journal_mode = WAL;
    BEGIN;
      CREATE TABLE abc(a PRIMARY KEY);
      INSERT INTO abc VALUES(randomblob(1500));
      INSERT INTO abc VALUES(randomblob(1500));
    COMMIT;
  }
  faultsim_save_and_close
} {}
do_faultsim_test walfault-14 -prep {
  faultsim_restore_and_reopen
  breakpoint
  execsql {
    SELECT count(*) FROM abc;
    PRAGMA locking_mode = exclusive;
    BEGIN;
      INSERT INTO abc VALUES(randomblob(1500));
    COMMIT;
  }
} -body {
  db eval { 
    PRAGMA locking_mode = normal;
    BEGIN;
      INSERT INTO abc VALUES(randomblob(1500));
    COMMIT;
  }
} -test {
  faultsim_integrity_check
  set nRow [db eval {SELECT count(*) FROM abc}]
  if {$nRow!=3 && $nRow!=4} { error "Bad db content" }
}

finish_test

Changes to test/win32lock.test.

23
24
25
26
27
28
29

30
31
32
33
34
35
36
db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
  lappend ::log $msg 
}
sqlite3 db test.db


do_test win32lock-1.1 {
  db eval {
    PRAGMA cache_size=10;
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES(1,randomblob(100000));
    INSERT INTO t1 VALUES(2,randomblob(50000));







>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
  lappend ::log $msg 
}
sqlite3 db test.db
db eval {PRAGMA mmap_size=0}

do_test win32lock-1.1 {
  db eval {
    PRAGMA cache_size=10;
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES(1,randomblob(100000));
    INSERT INTO t1 VALUES(2,randomblob(50000));

Changes to tool/mksqlite3c.tcl.

309
310
311
312
313
314
315

316
317
318
319
320
321
322
   fts3.c
   fts3_aux.c
   fts3_expr.c
   fts3_hash.c
   fts3_porter.c
   fts3_tokenizer.c
   fts3_tokenizer1.c

   fts3_write.c
   fts3_snippet.c
   fts3_unicode.c
   fts3_unicode2.c

   rtree.c
   icu.c







>







309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
   fts3.c
   fts3_aux.c
   fts3_expr.c
   fts3_hash.c
   fts3_porter.c
   fts3_tokenizer.c
   fts3_tokenizer1.c
   fts3_tokenize_vtab.c
   fts3_write.c
   fts3_snippet.c
   fts3_unicode.c
   fts3_unicode2.c

   rtree.c
   icu.c