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

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

Overview
Comment:Merge the latest changes from trunk into the apple-osx branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1: df3cdf9f0690f2724c7e4e0adb2e3bd4b1a4dd26
User & Date: drh 2015-01-02 19:17:44
Context
2015-01-08
19:55
Merge the testing enhancements and the unlimited VALUES enhancement from trunk. check-in: cc780842 user: drh tags: apple-osx
2015-01-02
19:17
Merge the latest changes from trunk into the apple-osx branch. check-in: df3cdf9f user: drh tags: apple-osx
15:55
Add the SQLITE_CONFIG_PMASZ start-time option. check-in: acb0d1e8 user: drh tags: trunk
2014-12-16
00:29
Merge latest fixes and enhancements from trunk into apple-osx. check-in: 2c1d8dda user: drh tags: apple-osx
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

18
19
20
21
22
23
24
25
26
27


28


29
30
31
32
33
34
35
36
...
539
540
541
542
543
544
545





546
547
548
549
550
551
552
...
977
978
979
980
981
982
983




























984
985
986
987
988
989
990
TOP = @srcdir@

# C Compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
BCC = @BUILD_CC@ @BUILD_CFLAGS@

# C Compile and options for use in building executables that 
# will run on the target platform.  (BCC and TCC are usually the
# same unless your are cross-compiling.)


#


TCC = @CC@ @CPPFLAGS@ @CFLAGS@ -I. -I${TOP}/src -I${TOP}/ext/rtree

# Define this for the autoconf-based build, so that the code knows it can
# include the generated config.h
# 
TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
................................................................................
		-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.
#
................................................................................
	$(LTLINK) -I. -o $@ $(TOP)/tool/logest.c

wordcount$(TEXE):	$(TOP)/test/wordcount.c sqlite3.c
	$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.c $(TLIBS)

speedtest1$(TEXE):	$(TOP)/test/wordcount.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)





























# Standard install and cleanup targets
#
lib_install:	libsqlite3.la
	$(INSTALL) -d $(DESTDIR)$(libdir)
	$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
	







|

|
>
>

>
>
|







 







>
>
>
>
>







 







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







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
...
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
TOP = @srcdir@

# C Compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
BCC = @BUILD_CC@ @BUILD_CFLAGS@

# TCC is the C Compile and options for use in building executables that 
# will run on the target platform.  (BCC and TCC are usually the
# same unless your are cross-compiling.)  Separate CC and CFLAGS macros
# are provide so that these aspects of the build process can be changed
# on the "make" command-line.  Ex:  "make CC=clang CFLAGS=-fsanitize=undefined"
#
CC = @CC@
CFLAGS = @CPPFLAGS@ @CFLAGS@
TCC = $(CC) $(CFLAGS) -I. -I${TOP}/src -I${TOP}/ext/rtree

# Define this for the autoconf-based build, so that the code knows it can
# include the generated config.h
# 
TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
................................................................................
		-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)"

mptest:	mptester$(EXE)
	rm -f mptest1.db
	./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test
	rm -f mptest2.db
	./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test

# 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.
#
................................................................................
	$(LTLINK) -I. -o $@ $(TOP)/tool/logest.c

wordcount$(TEXE):	$(TOP)/test/wordcount.c sqlite3.c
	$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.c $(TLIBS)

speedtest1$(TEXE):	$(TOP)/test/wordcount.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)

# This target will fail if the SQLite amalgamation contains any exported
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
#
checksymbols: sqlite3.lo
	nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0
	echo '0 errors out of 1 tests'

# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script.
# 
THREADTEST3_SRC = $(TOP)/test/threadtest3.c    \
                  $(TOP)/test/tt3_checkpoint.c \
                  $(TOP)/test/tt3_index.c      \
                  $(TOP)/test/tt3_vacuum.c      \
                  $(TOP)/test/tt3_stress.c      \
                  $(TOP)/test/tt3_lookaside1.c

threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
	$(LTLINK) $(TOP)/test/threadtest3.c sqlite3.lo -o $@ $(TLIBS)

threadtest: threadtest3$(TEXE)
	./threadtest3$(TEXE)

releasetest:	
	$(TCLSH_CMD) $(TOP)/test/releasetest.tcl

# Standard install and cleanup targets
#
lib_install:	libsqlite3.la
	$(INSTALL) -d $(DESTDIR)$(libdir)
	$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
	

Changes to Makefile.msc.

104
105
106
107
108
109
110

111
112
113
114
115
116
117
118
119
120
121
122
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
...
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
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
...
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
!ENDIF

# Set this to one of the following values to enable various debugging
# features.  Each level includes the debugging options from the previous
# levels.  Currently, the recognized values for DEBUG are:
#
# 0 == NDEBUG: Disables assert() and other runtime diagnostics.

# 1 == Disables NDEBUG and all optimizations and then enables PDBs.
# 2 == SQLITE_DEBUG: Enables various diagnostics messages and code.
# 3 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
# 4 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
# 5 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
#
!IFNDEF DEBUG
DEBUG = 0
!ENDIF

# Enable use of available compiler optimizations?  Normally, this should be
# non-zero.  Setting this to zero, thus disabling all compiler optimizations,
................................................................................

# Also, we need to dynamically link to the correct MSVC runtime
# when compiling for WinRT (e.g. debug or release) OR if the
# USE_CRT_DLL option is set to force dynamically linking to the
# MSVC runtime library.
#
!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0
!IF $(DEBUG)>0
TCC = $(TCC) -MDd
BCC = $(BCC) -MDd
!ELSE
TCC = $(TCC) -MD
BCC = $(BCC) -MD
!ENDIF
!ELSE
!IF $(DEBUG)>0
TCC = $(TCC) -MTd
BCC = $(BCC) -MTd
!ELSE
TCC = $(TCC) -MT
BCC = $(BCC) -MT
!ENDIF
!ENDIF
................................................................................
!ENDIF

# The mksqlite3c.tcl script accepts some options on the command
# line.  When compiling with debugging enabled, some of these
# options are necessary in order to allow debugging symbols to
# work correctly with Visual Studio when using the amalgamation.
#
!IF $(DEBUG)>0
MKSQLITE3C_ARGS = --linemacros
!ELSE
MKSQLITE3C_ARGS =
!ENDIF

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
................................................................................
#
!IF $(DEBUG)==0
TCC = $(TCC) -DNDEBUG
BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG
!ENDIF

!IF $(DEBUG)>1





TCC = $(TCC) -DSQLITE_DEBUG
RCC = $(RCC) -DSQLITE_DEBUG
!ENDIF

!IF $(DEBUG)>3
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF

!IF $(DEBUG)>4
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
!ENDIF

# Prevent warnings about "insecure" MSVC runtime library functions
# being used.
#
................................................................................
#
!ELSEIF $(WIN32HEAP)!=0
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1

# Validate the heap on every call into the native Win32 heap subsystem?
#
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF
!ENDIF

# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
................................................................................
# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
#
TCC = $(TCC) $(OPTS)
RCC = $(RCC) $(OPTS)

# If compiling for debugging, add some defines.
#
!IF $(DEBUG)>0
TCC = $(TCC) -D_DEBUG
BCC = $(BCC) -D_DEBUG
RCC = $(RCC) -D_DEBUG
!ENDIF

# If optimizations are enabled or disabled (either implicitly or
# explicitly), add the necessary flags.
#
!IF $(DEBUG)>0 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
!ELSEIF $(OPTIMIZATIONS)>=3
TCC = $(TCC) -Ox
BCC = $(BCC) -Ox
!ELSEIF $(OPTIMIZATIONS)==2
TCC = $(TCC) -O2
................................................................................
!ELSEIF $(OPTIMIZATIONS)==1
TCC = $(TCC) -O1
BCC = $(BCC) -O1
!ENDIF

# If symbols are enabled (or compiling for debugging), enable PDBs.
#
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
TCC = $(TCC) -Zi
BCC = $(BCC) -Zi
!ENDIF

# If ICU support is enabled, add the compiler options for it.
#
!IF $(USE_ICU)!=0
................................................................................
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
!ENDIF

# If either debugging or symbols are enabled, enable PDBs.
#
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
LDFLAGS = /DEBUG
!ENDIF

# Start with the Tcl related linker options.
#
!IF $(NO_TCL)==0
LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)







>
|
|
|
|
|







 







|







|







 







|







 







|
>
>
>
>
>




|




|







 







|







 







|








|







 







|







 







|







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
...
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
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
...
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
!ENDIF

# Set this to one of the following values to enable various debugging
# features.  Each level includes the debugging options from the previous
# levels.  Currently, the recognized values for DEBUG are:
#
# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
# 1 == SQLITE_ENABLE_API_ARMOR: extra attempts to detect misuse of the API.
# 2 == Disables NDEBUG and all optimizations and then enables PDBs.
# 3 == SQLITE_DEBUG: Enables various diagnostics messages and code.
# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
#
!IFNDEF DEBUG
DEBUG = 0
!ENDIF

# Enable use of available compiler optimizations?  Normally, this should be
# non-zero.  Setting this to zero, thus disabling all compiler optimizations,
................................................................................

# Also, we need to dynamically link to the correct MSVC runtime
# when compiling for WinRT (e.g. debug or release) OR if the
# USE_CRT_DLL option is set to force dynamically linking to the
# MSVC runtime library.
#
!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0
!IF $(DEBUG)>1
TCC = $(TCC) -MDd
BCC = $(BCC) -MDd
!ELSE
TCC = $(TCC) -MD
BCC = $(BCC) -MD
!ENDIF
!ELSE
!IF $(DEBUG)>1
TCC = $(TCC) -MTd
BCC = $(BCC) -MTd
!ELSE
TCC = $(TCC) -MT
BCC = $(BCC) -MT
!ENDIF
!ENDIF
................................................................................
!ENDIF

# The mksqlite3c.tcl script accepts some options on the command
# line.  When compiling with debugging enabled, some of these
# options are necessary in order to allow debugging symbols to
# work correctly with Visual Studio when using the amalgamation.
#
!IF $(DEBUG)>1
MKSQLITE3C_ARGS = --linemacros
!ELSE
MKSQLITE3C_ARGS =
!ENDIF

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
................................................................................
#
!IF $(DEBUG)==0
TCC = $(TCC) -DNDEBUG
BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG
!ENDIF

!IF $(DEBUG)>0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR
!ENDIF

!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG
RCC = $(RCC) -DSQLITE_DEBUG
!ENDIF

!IF $(DEBUG)>4
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF

!IF $(DEBUG)>5
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
!ENDIF

# Prevent warnings about "insecure" MSVC runtime library functions
# being used.
#
................................................................................
#
!ELSEIF $(WIN32HEAP)!=0
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1

# Validate the heap on every call into the native Win32 heap subsystem?
#
!IF $(DEBUG)>3
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF
!ENDIF

# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
................................................................................
# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
#
TCC = $(TCC) $(OPTS)
RCC = $(RCC) $(OPTS)

# If compiling for debugging, add some defines.
#
!IF $(DEBUG)>1
TCC = $(TCC) -D_DEBUG
BCC = $(BCC) -D_DEBUG
RCC = $(RCC) -D_DEBUG
!ENDIF

# If optimizations are enabled or disabled (either implicitly or
# explicitly), add the necessary flags.
#
!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
!ELSEIF $(OPTIMIZATIONS)>=3
TCC = $(TCC) -Ox
BCC = $(BCC) -Ox
!ELSEIF $(OPTIMIZATIONS)==2
TCC = $(TCC) -O2
................................................................................
!ELSEIF $(OPTIMIZATIONS)==1
TCC = $(TCC) -O1
BCC = $(BCC) -O1
!ENDIF

# If symbols are enabled (or compiling for debugging), enable PDBs.
#
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
TCC = $(TCC) -Zi
BCC = $(BCC) -Zi
!ENDIF

# If ICU support is enabled, add the compiler options for it.
#
!IF $(USE_ICU)!=0
................................................................................
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
!ENDIF

# If either debugging or symbols are enabled, enable PDBs.
#
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
LDFLAGS = /DEBUG
!ENDIF

# Start with the Tcl related linker options.
#
!IF $(NO_TCL)==0
LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)

Changes to README.md.

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

There are several build options that can be set via the NMAKE command
line.  For example, to build for WinRT, simply add "FOR_WINRT=1" argument
to the "sqlite3.dll" command line above.  When debugging into the SQLite
code, adding the "DEBUG=1" argument to one of the above command lines is
recommended.

SQLite does not require Tcl to run, but a Tcl installation is required
by the makefiles (including those for MSVC).  SQLite contains a lot of
generated code and Tcl is used to do much of that code generation.  The
makefiles also require AWK.

## Source Code Tour

Most of the core source files are in the **src/** subdirectory.  But
src/ also contains files used to build the "testfixture" test harness;
those file all begin with "test".  And src/ contains the "shell.c" file
which is the main program for the "sqlite3.exe" command-line shell and
................................................................................
of the automatically-generated files, simply run "make target_source".
The "target_source" make target will create a subdirectory "tsrc/" and
fill it with all the source files needed to build SQLite, both
manually-edited files and automatically-generated files.

The SQLite interface is defined by the **sqlite3.h** header file, which is
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION.  The
Tcl script at tool/mksqlite3h.tcl does the conversion.  The manifest.uuid
file contains the SHA1 hash of the particular check-in and is used to generate
the SQLITE_SOURCE_ID macro.  The VERSION file contains the current SQLite
version number.  The sqlite3.h header is really just a copy of src/sqlite.h.in
with the source-id and version number inserted at just the right spots.
Note that comment text in the sqlite3.h file is used to generate much of
the SQLite API documentation.  The Tcl scripts used to generate that
documentation are in a separate source repository.

The SQL language parser is **parse.c** which is generate from a grammar in
the src/parse.y file.  The conversion of "parse.y" into "parse.c" is done
by the [lemon](./doc/lemon.html) LALR(1) parser generator.  The source code
for lemon is at tool/lemon.c.  Lemon uses a
template for generating its parser.  A generic template is in tool/lempar.c,
but SQLite uses a slightly modified template found in src/lempar.c.







|
|
|
|







 







|
|
|
|
|
|
|
|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

There are several build options that can be set via the NMAKE command
line.  For example, to build for WinRT, simply add "FOR_WINRT=1" argument
to the "sqlite3.dll" command line above.  When debugging into the SQLite
code, adding the "DEBUG=1" argument to one of the above command lines is
recommended.

SQLite does not require [Tcl](http://www.tcl.tk/) to run, but a Tcl installation
is required by the makefiles (including those for MSVC).  SQLite contains
a lot of generated code and Tcl is used to do much of that code generation.
The makefiles also require AWK.

## Source Code Tour

Most of the core source files are in the **src/** subdirectory.  But
src/ also contains files used to build the "testfixture" test harness;
those file all begin with "test".  And src/ contains the "shell.c" file
which is the main program for the "sqlite3.exe" command-line shell and
................................................................................
of the automatically-generated files, simply run "make target_source".
The "target_source" make target will create a subdirectory "tsrc/" and
fill it with all the source files needed to build SQLite, both
manually-edited files and automatically-generated files.

The SQLite interface is defined by the **sqlite3.h** header file, which is
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION.  The
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
The manifest.uuid file contains the SHA1 hash of the particular check-in
and is used to generate the SQLITE\_SOURCE\_ID macro.  The VERSION file
contains the current SQLite version number.  The sqlite3.h header is really
just a copy of src/sqlite.h.in with the source-id and version number inserted
at just the right spots. Note that comment text in the sqlite3.h file is
used to generate much of the SQLite API documentation.  The Tcl scripts
used to generate that documentation are in a separate source repository.

The SQL language parser is **parse.c** which is generate from a grammar in
the src/parse.y file.  The conversion of "parse.y" into "parse.c" is done
by the [lemon](./doc/lemon.html) LALR(1) parser generator.  The source code
for lemon is at tool/lemon.c.  Lemon uses a
template for generating its parser.  A generic template is in tool/lempar.c,
but SQLite uses a slightly modified template found in src/lempar.c.

Changes to ext/misc/fuzzer.c.

338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
  }else{

    pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
    if( pRule==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pRule, 0, sizeof(*pRule));
      pRule->zFrom = &pRule->zTo[nTo+1];

      pRule->nFrom = nFrom;
      memcpy(pRule->zFrom, zFrom, nFrom+1);
      memcpy(pRule->zTo, zTo, nTo+1);
      pRule->nTo = nTo;
      pRule->rCost = nCost;
      pRule->iRuleset = (int)iRuleset;
    }







|
>







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  }else{

    pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
    if( pRule==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pRule, 0, sizeof(*pRule));
      pRule->zFrom = pRule->zTo;
      pRule->zFrom += nTo + 1;
      pRule->nFrom = nFrom;
      memcpy(pRule->zFrom, zFrom, nFrom+1);
      memcpy(pRule->zTo, zTo, nTo+1);
      pRule->nTo = nTo;
      pRule->rCost = nCost;
      pRule->iRuleset = (int)iRuleset;
    }

Changes to ext/rtree/rtree.c.

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
    pCur->aPoint = pNew;
    pCur->nPointAlloc = nNew;
  }
  i = pCur->nPoint++;
  pNew = pCur->aPoint + i;
  pNew->rScore = rScore;
  pNew->iLevel = iLevel;
  assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH );
  while( i>0 ){
    RtreeSearchPoint *pParent;
    j = (i-1)/2;
    pParent = pCur->aPoint + j;
    if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
    rtreeSearchPointSwap(pCur, j, i);
    i = j;







|







1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
    pCur->aPoint = pNew;
    pCur->nPointAlloc = nNew;
  }
  i = pCur->nPoint++;
  pNew = pCur->aPoint + i;
  pNew->rScore = rScore;
  pNew->iLevel = iLevel;
  assert( iLevel<=RTREE_MAX_DEPTH );
  while( i>0 ){
    RtreeSearchPoint *pParent;
    j = (i-1)/2;
    pParent = pCur->aPoint + j;
    if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
    rtreeSearchPointSwap(pCur, j, i);
    i = j;

Changes to mptest/mptest.c.

1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
    }
    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;
}







|



1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
    }
    sqlite3_finalize(pStmt);
  }
  sqlite3_close(g.db);  
  maybeClose(g.pLog);
  maybeClose(g.pErrLog);
  if( iClient==0 ){
    printf("Summary: %d errors out of %d tests\n", g.nError, g.nTest);
  }
  return g.nError>0;
}

Changes to src/analyze.c.

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
    u8 *pSpace;                     /* Allocated space not yet assigned */
    int i;                          /* Used to iterate through p->aSample[] */

    p->iGet = -1;
    p->mxSample = mxSample;
    p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
    p->current.anLt = &p->current.anEq[nColUp];
    p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565;
  
    /* Set up the Stat4Accum.a[] and aBest[] arrays */
    p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
    p->aBest = &p->a[mxSample];
    pSpace = (u8*)(&p->a[mxSample+nCol]);
    for(i=0; i<(mxSample+nCol); i++){
      p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);







|







444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
    u8 *pSpace;                     /* Allocated space not yet assigned */
    int i;                          /* Used to iterate through p->aSample[] */

    p->iGet = -1;
    p->mxSample = mxSample;
    p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
    p->current.anLt = &p->current.anEq[nColUp];
    p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
  
    /* Set up the Stat4Accum.a[] and aBest[] arrays */
    p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
    p->aBest = &p->a[mxSample];
    pSpace = (u8*)(&p->a[mxSample+nCol]);
    for(i=0; i<(mxSample+nCol); i++){
      p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);

Changes to src/btree.c.

3573
3574
3575
3576
3577
3578
3579

3580
3581
3582
3583
3584
3585
3586
....
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
....
8200
8201
8202
8203
8204
8205
8206







8207
8208
8209
8210
8211
8212
8213
8214
8215
8216



8217

8218
8219
8220
8221
8222
8223
8224
....
9157
9158
9159
9160
9161
9162
9163
9164
    assert( pBt->inTransaction==TRANS_WRITE );
    assert( pBt->nTransaction>0 );
    rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
    if( rc!=SQLITE_OK && bCleanup==0 ){
      sqlite3BtreeLeave(p);
      return rc;
    }

    pBt->inTransaction = TRANS_READ;
    btreeClearHasContent(pBt);
  }

  btreeEndTransaction(p);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
................................................................................
        memcpy(apCell[nCell], &pOld->aData[8], 4);
      }else{
        assert( leafCorrection==4 );
        if( szCell[nCell]<4 ){
          /* Do not allow any cells smaller than 4 bytes. If a smaller cell
          ** does exist, pad it with 0x00 bytes. */
          assert( szCell[nCell]==3 );
          assert( apCell[nCell]==&pTemp[iSpace1-3] );
          pTemp[iSpace1++] = 0x00;
          szCell[nCell] = 4;
        }
      }
      nCell++;
    }
  }

................................................................................
** is the number of free pages currently in the database.  Meta[1]
** through meta[15] are available for use by higher layers.  Meta[0]
** is read-only, the others are read/write.
** 
** The schema layer numbers meta values differently.  At the schema
** layer (and the SetCookie and ReadCookie opcodes) the number of
** free pages is not visible.  So Cookie[0] is the same as Meta[1].







*/
void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
  BtShared *pBt = p->pBt;

  sqlite3BtreeEnter(p);
  assert( p->inTrans>TRANS_NONE );
  assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
  assert( pBt->pPage1 );
  assert( idx>=0 && idx<=15 );




  *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);


  /* If auto-vacuum is disabled in this build and this is an auto-vacuum
  ** database, mark the database as read-only.  */
#ifdef SQLITE_OMIT_AUTOVACUUM
  if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
    pBt->btsFlags |= BTS_READ_ONLY;
  }
................................................................................
int sqlite3BtreeIsReadonly(Btree *p){
  return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
}

/*
** Return the size of the header added to each page by this module.
*/
int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); }







>







 







|
|







 







>
>
>
>
>
>
>










>
>
>
|
>







 







|
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
....
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
....
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
....
9169
9170
9171
9172
9173
9174
9175
9176
    assert( pBt->inTransaction==TRANS_WRITE );
    assert( pBt->nTransaction>0 );
    rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
    if( rc!=SQLITE_OK && bCleanup==0 ){
      sqlite3BtreeLeave(p);
      return rc;
    }
    p->iDataVersion--;  /* Compensate for pPager->iDataVersion++; */
    pBt->inTransaction = TRANS_READ;
    btreeClearHasContent(pBt);
  }

  btreeEndTransaction(p);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
................................................................................
        memcpy(apCell[nCell], &pOld->aData[8], 4);
      }else{
        assert( leafCorrection==4 );
        if( szCell[nCell]<4 ){
          /* Do not allow any cells smaller than 4 bytes. If a smaller cell
          ** does exist, pad it with 0x00 bytes. */
          assert( szCell[nCell]==3 );
          assert( apCell[nCell]==&aSpace1[iSpace1-3] );
          aSpace1[iSpace1++] = 0x00;
          szCell[nCell] = 4;
        }
      }
      nCell++;
    }
  }

................................................................................
** is the number of free pages currently in the database.  Meta[1]
** through meta[15] are available for use by higher layers.  Meta[0]
** is read-only, the others are read/write.
** 
** The schema layer numbers meta values differently.  At the schema
** layer (and the SetCookie and ReadCookie opcodes) the number of
** free pages is not visible.  So Cookie[0] is the same as Meta[1].
**
** This routine treats Meta[BTREE_DATA_VERSION] as a special case.  Instead
** of reading the value out of the header, it instead loads the "DataVersion"
** from the pager.  The BTREE_DATA_VERSION value is not actually stored in the
** database file.  It is a number computed by the pager.  But its access
** pattern is the same as header meta values, and so it is convenient to
** read it from this routine.
*/
void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
  BtShared *pBt = p->pBt;

  sqlite3BtreeEnter(p);
  assert( p->inTrans>TRANS_NONE );
  assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
  assert( pBt->pPage1 );
  assert( idx>=0 && idx<=15 );

  if( idx==BTREE_DATA_VERSION ){
    *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
  }else{
    *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
  }

  /* If auto-vacuum is disabled in this build and this is an auto-vacuum
  ** database, mark the database as read-only.  */
#ifdef SQLITE_OMIT_AUTOVACUUM
  if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
    pBt->btsFlags |= BTS_READ_ONLY;
  }
................................................................................
int sqlite3BtreeIsReadonly(Btree *p){
  return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
}

/*
** Return the size of the header added to each page by this module.
*/
int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }

Changes to src/btree.h.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
130
131
132
133
134
135
136





137
138
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
*/
#ifndef _BTREE_H_
#define _BTREE_H_

/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
#define SQLITE_N_BTREE_META 10

/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
*/
#ifndef SQLITE_DEFAULT_AUTOVACUUM
  #define SQLITE_DEFAULT_AUTOVACUUM 0
................................................................................
** SQLite database header may be found using the following formula:
**
**   offset = 36 + (idx * 4)
**
** For example, the free-page-count field is located at byte offset 36 of
** the database file header. The incr-vacuum-flag field is located at
** byte offset 64 (== 36+4*7).





*/
#define BTREE_FREE_PAGE_COUNT     0
#define BTREE_SCHEMA_VERSION      1
#define BTREE_FILE_FORMAT         2
#define BTREE_DEFAULT_CACHE_SIZE  3
#define BTREE_LARGEST_ROOT_PAGE   4
#define BTREE_TEXT_ENCODING       5
#define BTREE_USER_VERSION        6
#define BTREE_INCR_VACUUM         7
#define BTREE_APPLICATION_ID      8


/*
** Values that may be OR'd together to form the second argument of an
** sqlite3BtreeCursorHints() call.
*/
#define BTREE_BULKLOAD 0x00000001








|







 







>
>
>
>
>










>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
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
*/
#ifndef _BTREE_H_
#define _BTREE_H_

/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
#define SQLITE_N_BTREE_META 16

/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
*/
#ifndef SQLITE_DEFAULT_AUTOVACUUM
  #define SQLITE_DEFAULT_AUTOVACUUM 0
................................................................................
** SQLite database header may be found using the following formula:
**
**   offset = 36 + (idx * 4)
**
** For example, the free-page-count field is located at byte offset 36 of
** the database file header. The incr-vacuum-flag field is located at
** byte offset 64 (== 36+4*7).
**
** The BTREE_DATA_VERSION value is not really a value stored in the header.
** It is a read-only number computed by the pager.  But we merge it with
** the header value access routines since its access pattern is the same.
** Call it a "virtual meta value".
*/
#define BTREE_FREE_PAGE_COUNT     0
#define BTREE_SCHEMA_VERSION      1
#define BTREE_FILE_FORMAT         2
#define BTREE_DEFAULT_CACHE_SIZE  3
#define BTREE_LARGEST_ROOT_PAGE   4
#define BTREE_TEXT_ENCODING       5
#define BTREE_USER_VERSION        6
#define BTREE_INCR_VACUUM         7
#define BTREE_APPLICATION_ID      8
#define BTREE_DATA_VERSION        15  /* A virtual meta-value */

/*
** Values that may be OR'd together to form the second argument of an
** sqlite3BtreeCursorHints() call.
*/
#define BTREE_BULKLOAD 0x00000001

Changes to src/btreeInt.h.

347
348
349
350
351
352
353

354
355
356
357
358
359
360
  sqlite3 *db;       /* The database connection holding this btree */
  BtShared *pBt;     /* Sharable content of this btree */
  u8 inTrans;        /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
  u8 sharable;       /* True if we can share pBt with another db */
  u8 locked;         /* True if db currently has pBt locked */
  int wantToLock;    /* Number of nested calls to sqlite3BtreeEnter() */
  int nBackup;       /* Number of backup operations reading this btree */

  Btree *pNext;      /* List of other sharable Btrees from the same db */
  Btree *pPrev;      /* Back pointer of the same list */
#ifndef SQLITE_OMIT_SHARED_CACHE
  BtLock lock;       /* Object used to lock page 1 */
#endif
};








>







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  sqlite3 *db;       /* The database connection holding this btree */
  BtShared *pBt;     /* Sharable content of this btree */
  u8 inTrans;        /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
  u8 sharable;       /* True if we can share pBt with another db */
  u8 locked;         /* True if db currently has pBt locked */
  int wantToLock;    /* Number of nested calls to sqlite3BtreeEnter() */
  int nBackup;       /* Number of backup operations reading this btree */
  u32 iDataVersion;  /* Combines with pBt->pPager->iDataVersion */
  Btree *pNext;      /* List of other sharable Btrees from the same db */
  Btree *pPrev;      /* Back pointer of the same list */
#ifndef SQLITE_OMIT_SHARED_CACHE
  BtLock lock;       /* Object used to lock page 1 */
#endif
};

Changes to src/build.c.

1709
1710
1711
1712
1713
1714
1715













1716
1717
1718
1719
1720
1721
1722
    assert( pParse->pNewTable==pTab );
    pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
    if( pPk==0 ) return;
    pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
    pTab->iPKey = -1;
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);













  }
  pPk->isCovering = 1;
  assert( pPk!=0 );
  nPk = pPk->nKeyCol;

  /* Make sure every column of the PRIMARY KEY is NOT NULL */
  for(i=0; i<nPk; i++){







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







1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
    assert( pParse->pNewTable==pTab );
    pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
    if( pPk==0 ) return;
    pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
    pTab->iPKey = -1;
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);
    /*
    ** Remove all redundant columns from the PRIMARY KEY.  For example, change
    ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)".  Later
    ** code assumes the PRIMARY KEY contains no repeated columns.
    */
    for(i=j=1; i<pPk->nKeyCol; i++){
      if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){
        pPk->nColumn--;
      }else{
        pPk->aiColumn[j++] = pPk->aiColumn[i];
      }
    }
    pPk->nKeyCol = j;
  }
  pPk->isCovering = 1;
  assert( pPk!=0 );
  nPk = pPk->nKeyCol;

  /* Make sure every column of the PRIMARY KEY is NOT NULL */
  for(i=0; i<nPk; i++){

Changes to src/complete.c.

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
136
137
138
139
140
141
142







143
144
145
146
147
148
149
** to recognize the end of a trigger can be omitted.  All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
  u8 state = 0;   /* Current state, using numbers defined in header comment */
  u8 token;       /* Value of the next token */

#ifdef SQLITE_ENABLE_API_ARMOR
  if( zSql==0 ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif

#ifndef SQLITE_OMIT_TRIGGER
  /* A complex statement machine used to detect the end of a CREATE TRIGGER
  ** statement.  This is the normal case.
  */
  static const u8 trans[8][8] = {
                     /* Token:                                                */
     /* State:       **  SEMI  WS  OTHER  EXPLAIN  CREATE  TEMP  TRIGGER  END */
................................................................................
                     /* Token:           */
     /* State:       **  SEMI  WS  OTHER */
     /* 0 INVALID: */ {    1,  0,     2, },
     /* 1   START: */ {    1,  1,     2, },
     /* 2  NORMAL: */ {    1,  2,     2, },
  };
#endif /* SQLITE_OMIT_TRIGGER */








  while( *zSql ){
    switch( *zSql ){
      case ';': {  /* A semicolon */
        token = tkSEMI;
        break;
      }







<
<
<
<
<
<
<







 







>
>
>
>
>
>
>







101
102
103
104
105
106
107







108
109
110
111
112
113
114
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
** to recognize the end of a trigger can be omitted.  All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
  u8 state = 0;   /* Current state, using numbers defined in header comment */
  u8 token;       /* Value of the next token */








#ifndef SQLITE_OMIT_TRIGGER
  /* A complex statement machine used to detect the end of a CREATE TRIGGER
  ** statement.  This is the normal case.
  */
  static const u8 trans[8][8] = {
                     /* Token:                                                */
     /* State:       **  SEMI  WS  OTHER  EXPLAIN  CREATE  TEMP  TRIGGER  END */
................................................................................
                     /* Token:           */
     /* State:       **  SEMI  WS  OTHER */
     /* 0 INVALID: */ {    1,  0,     2, },
     /* 1   START: */ {    1,  1,     2, },
     /* 2  NORMAL: */ {    1,  2,     2, },
  };
#endif /* SQLITE_OMIT_TRIGGER */

#ifdef SQLITE_ENABLE_API_ARMOR
  if( zSql==0 ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif

  while( *zSql ){
    switch( *zSql ){
      case ';': {  /* A semicolon */
        token = tkSEMI;
        break;
      }

Changes to src/fkey.c.

433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
504
505
506
507
508
509
510




511
512
513
514
515
516
517
...
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
...
805
806
807
808
809
810
811


















812
813
814
815
816
817
818
...
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
...
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
...
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
...
983
984
985
986
987
988
989
990
991
992
993
994
995
996




















997
998
999
1000
1001
1002
1003
    ** incrementing a counter. This is necessary as the VM code is being
    ** generated for will not open a statement transaction.  */
    assert( nIncr==1 );
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
        OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
  }else{
    if( nIncr>0 && pFKey->isDeferred==0 ){
      sqlite3ParseToplevel(pParse)->mayAbort = 1;
    }
    sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  }

  sqlite3VdbeResolveLabel(v, iOk);
  sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
................................................................................

/*
** This function is called to generate code executed when a row is deleted
** from the parent table of foreign key constraint pFKey and, if pFKey is 
** deferred, when a row is inserted into the same table. When generating
** code for an SQL UPDATE operation, this function may be called twice -
** once to "delete" the old row and once to "insert" the new row.




**
** The code generated by this function scans through the rows in the child
** table that correspond to the parent table row being deleted or inserted.
** For each child row found, one of the following actions is taken:
**
**   Operation | FK type   | Action taken
**   --------------------------------------------------------------------------
................................................................................
  /* Resolve the references in the WHERE clause. */
  memset(&sNameContext, 0, sizeof(NameContext));
  sNameContext.pSrcList = pSrc;
  sNameContext.pParse = pParse;
  sqlite3ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. If the constraint is not deferred, throw an exception for
  ** each row found. Otherwise, for deferred constraints, increment the
  ** deferred constraint counter by nIncr for each row selected.  */
  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
  if( nIncr>0 && pFKey->isDeferred==0 ){
    sqlite3ParseToplevel(pParse)->mayAbort = 1;
  }
  sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  if( pWInfo ){
    sqlite3WhereEnd(pWInfo);
  }

  /* Clean up the WHERE clause constructed above. */
  sqlite3ExprDelete(db, pWhere);
................................................................................
          return 1;
        }
      }
    }
  }
  return 0;
}



















/*
** This function is called when inserting, deleting or updating a row of
** table pTab to generate VDBE code to perform foreign key constraint 
** processing for the operation.
**
** For a DELETE operation, parameter regOld is passed the index of the
................................................................................
  for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
    Table *pTo;                   /* Parent table of foreign key pFKey */
    Index *pIdx = 0;              /* Index on key columns in pTo */
    int *aiFree = 0;
    int *aiCol;
    int iCol;
    int i;
    int isIgnore = 0;

    if( aChange 
     && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
     && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 
    ){
      continue;
    }
................................................................................
      /* Request permission to read the parent key columns. If the 
      ** authorization callback returns SQLITE_IGNORE, behave as if any
      ** values read from the parent table are NULL. */
      if( db->xAuth ){
        int rcauth;
        char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
        rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
        isIgnore = (rcauth==SQLITE_IGNORE);
      }
#endif
    }

    /* Take a shared-cache advisory read-lock on the parent table. Allocate 
    ** a cursor to use to search the unique index on the parent key columns 
    ** in the parent table.  */
................................................................................
    sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName);
    pParse->nTab++;

    if( regOld!=0 ){
      /* A row is being removed from the child table. Search for the parent.
      ** If the parent does not exist, removing the child row resolves an 
      ** outstanding foreign key constraint violation. */
      fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
    }
    if( regNew!=0 ){
      /* A row is being added to the child table. If a parent row cannot
      ** be found, adding the child row has violated the FK constraint. */ 






      fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
    }

    sqlite3DbFree(db, aiFree);
  }

  /* Loop through all the foreign key constraints that refer to this table.
  ** (the "child" constraints) */
................................................................................
      continue;
    }

    if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) 
     && !pParse->pToplevel && !pParse->isMultiWrite 
    ){
      assert( regOld==0 && regNew!=0 );
      /* Inserting a single row into a parent table cannot cause an immediate
      ** foreign key violation. So do nothing in this case.  */
      continue;
    }

    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
      if( !isIgnoreErrors || db->mallocFailed ) return;
      continue;
    }
................................................................................
      pItem->pTab->nRef++;
      pItem->iCursor = pParse->nTab++;
  
      if( regNew!=0 ){
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
      }
      if( regOld!=0 ){
        /* If there is a RESTRICT action configured for the current operation
        ** on the parent table of this FK, then throw an exception 
        ** immediately if the FK constraint is violated, even if this is a
        ** deferred trigger. That's what RESTRICT means. To defer checking
        ** the constraint, the FK should specify NO ACTION (represented
        ** using OE_None). NO ACTION is the default.  */
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);




















      }
      pItem->zName = 0;
      sqlite3SrcListDelete(db, pSrc);
    }
    sqlite3DbFree(db, aiCol);
  }
}







|







 







>
>
>
>







 







|
|
<

<
<
<







 







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







 







|







 







|







 







|

|

|
>
>
>
>
>
>
|







 







|
|







 







|
<
<
<
<
<

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







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
...
625
626
627
628
629
630
631
632
633

634



635
636
637
638
639
640
641
...
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
...
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
...
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
...
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
....
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
    ** incrementing a counter. This is necessary as the VM code is being
    ** generated for will not open a statement transaction.  */
    assert( nIncr==1 );
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
        OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
  }else{
    if( nIncr>0 && pFKey->isDeferred==0 ){
      sqlite3MayAbort(pParse);
    }
    sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  }

  sqlite3VdbeResolveLabel(v, iOk);
  sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
................................................................................

/*
** This function is called to generate code executed when a row is deleted
** from the parent table of foreign key constraint pFKey and, if pFKey is 
** deferred, when a row is inserted into the same table. When generating
** code for an SQL UPDATE operation, this function may be called twice -
** once to "delete" the old row and once to "insert" the new row.
**
** Parameter nIncr is passed -1 when inserting a row (as this may decrease
** the number of FK violations in the db) or +1 when deleting one (as this
** may increase the number of FK constraint problems).
**
** The code generated by this function scans through the rows in the child
** table that correspond to the parent table row being deleted or inserted.
** For each child row found, one of the following actions is taken:
**
**   Operation | FK type   | Action taken
**   --------------------------------------------------------------------------
................................................................................
  /* Resolve the references in the WHERE clause. */
  memset(&sNameContext, 0, sizeof(NameContext));
  sNameContext.pSrcList = pSrc;
  sNameContext.pParse = pParse;
  sqlite3ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. For each row found, increment either the deferred or immediate
  ** foreign key constraint counter. */

  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);



  sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  if( pWInfo ){
    sqlite3WhereEnd(pWInfo);
  }

  /* Clean up the WHERE clause constructed above. */
  sqlite3ExprDelete(db, pWhere);
................................................................................
          return 1;
        }
      }
    }
  }
  return 0;
}

/*
** Return true if the parser passed as the first argument is being
** used to code a trigger that is really a "SET NULL" action belonging
** to trigger pFKey.
*/
static int isSetNullAction(Parse *pParse, FKey *pFKey){
  Parse *pTop = sqlite3ParseToplevel(pParse);
  if( pTop->pTriggerPrg ){
    Trigger *p = pTop->pTriggerPrg->pTrigger;
    if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull)
     || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull)
    ){
      return 1;
    }
  }
  return 0;
}

/*
** This function is called when inserting, deleting or updating a row of
** table pTab to generate VDBE code to perform foreign key constraint 
** processing for the operation.
**
** For a DELETE operation, parameter regOld is passed the index of the
................................................................................
  for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
    Table *pTo;                   /* Parent table of foreign key pFKey */
    Index *pIdx = 0;              /* Index on key columns in pTo */
    int *aiFree = 0;
    int *aiCol;
    int iCol;
    int i;
    int bIgnore = 0;

    if( aChange 
     && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
     && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 
    ){
      continue;
    }
................................................................................
      /* Request permission to read the parent key columns. If the 
      ** authorization callback returns SQLITE_IGNORE, behave as if any
      ** values read from the parent table are NULL. */
      if( db->xAuth ){
        int rcauth;
        char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
        rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
        bIgnore = (rcauth==SQLITE_IGNORE);
      }
#endif
    }

    /* Take a shared-cache advisory read-lock on the parent table. Allocate 
    ** a cursor to use to search the unique index on the parent key columns 
    ** in the parent table.  */
................................................................................
    sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName);
    pParse->nTab++;

    if( regOld!=0 ){
      /* A row is being removed from the child table. Search for the parent.
      ** If the parent does not exist, removing the child row resolves an 
      ** outstanding foreign key constraint violation. */
      fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore);
    }
    if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){
      /* A row is being added to the child table. If a parent row cannot
      ** be found, adding the child row has violated the FK constraint. 
      **
      ** If this operation is being performed as part of a trigger program
      ** that is actually a "SET NULL" action belonging to this very 
      ** foreign key, then omit this scan altogether. As all child key
      ** values are guaranteed to be NULL, it is not possible for adding
      ** this row to cause an FK violation.  */
      fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore);
    }

    sqlite3DbFree(db, aiFree);
  }

  /* Loop through all the foreign key constraints that refer to this table.
  ** (the "child" constraints) */
................................................................................
      continue;
    }

    if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) 
     && !pParse->pToplevel && !pParse->isMultiWrite 
    ){
      assert( regOld==0 && regNew!=0 );
      /* Inserting a single row into a parent table cannot cause (or fix)
      ** an immediate foreign key violation. So do nothing in this case.  */
      continue;
    }

    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
      if( !isIgnoreErrors || db->mallocFailed ) return;
      continue;
    }
................................................................................
      pItem->pTab->nRef++;
      pItem->iCursor = pParse->nTab++;
  
      if( regNew!=0 ){
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
      }
      if( regOld!=0 ){
        int eAction = pFKey->aAction[aChange!=0];





        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
        /* If this is a deferred FK constraint, or a CASCADE or SET NULL
        ** action applies, then any foreign key violations caused by
        ** removing the parent key will be rectified by the action trigger.
        ** So do not set the "may-abort" flag in this case.
        **
        ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the
        ** may-abort flag will eventually be set on this statement anyway
        ** (when this function is called as part of processing the UPDATE
        ** within the action trigger).
        **
        ** Note 2: At first glance it may seem like SQLite could simply omit
        ** all OP_FkCounter related scans when either CASCADE or SET NULL
        ** applies. The trouble starts if the CASCADE or SET NULL action 
        ** trigger causes other triggers or action rules attached to the 
        ** child table to fire. In these cases the fk constraint counters
        ** might be set incorrectly if any OP_FkCounter related scans are 
        ** omitted.  */
        if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){
          sqlite3MayAbort(pParse);
        }
      }
      pItem->zName = 0;
      sqlite3SrcListDelete(db, pSrc);
    }
    sqlite3DbFree(db, aiCol);
  }
}

Changes to src/global.c.

148
149
150
151
152
153
154







155
156
157
158
159
160
161
...
178
179
180
181
182
183
184

185
186
187
188
189
190
191
** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
** that compile-time option is omitted.
*/
#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
#endif








/*
** The following singleton contains the global configuration for
** the SQLite library.
*/
SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
................................................................................
   0,                         /* szScratch */
   0,                         /* nScratch */
   (void*)0,                  /* pPage */
   0,                         /* szPage */
   0,                         /* nPage */
   0,                         /* mxParserStack */
   0,                         /* sharedCacheEnabled */

   /* All the rest should always be initialized to zero */
   0,                         /* isInit */
   0,                         /* inProgress */
   0,                         /* isMutexInit */
   0,                         /* isMallocInit */
   0,                         /* isPCacheInit */
   0,                         /* nRefInitMutex */







>
>
>
>
>
>
>







 







>







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
** that compile-time option is omitted.
*/
#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
#endif

/* The minimum PMA size is set to this value multiplied by the database
** page size in bytes.
*/
#ifndef SQLITE_SORTER_PMASZ
# define SQLITE_SORTER_PMASZ 250
#endif

/*
** The following singleton contains the global configuration for
** the SQLite library.
*/
SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
................................................................................
   0,                         /* szScratch */
   0,                         /* nScratch */
   (void*)0,                  /* pPage */
   0,                         /* szPage */
   0,                         /* nPage */
   0,                         /* mxParserStack */
   0,                         /* sharedCacheEnabled */
   SQLITE_SORTER_PMASZ,       /* szPma */
   /* All the rest should always be initialized to zero */
   0,                         /* isInit */
   0,                         /* inProgress */
   0,                         /* isMutexInit */
   0,                         /* isMallocInit */
   0,                         /* isPCacheInit */
   0,                         /* nRefInitMutex */

Changes to src/main.c.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
...
270
271
272
273
274
275
276







277
278
279
280
281
282
283
...
585
586
587
588
589
590
591





592
593
594
595
596
597
598
....
3786
3787
3788
3789
3790
3791
3792

3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807

3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
** If the following function pointer is not NULL and if
** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
** I/O active are written using this function.  These messages
** are intended for debugging activity only.
*/
void (*sqlite3IoTrace)(const char*, ...) = 0;
#endif

/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
**
................................................................................
** there are outstanding database connections or memory allocations or
** while any part of SQLite is otherwise in use in any thread.  This
** routine is not threadsafe.  But it is safe to invoke this routine
** on when SQLite is already shut down.  If SQLite is already shut down
** when this routine is invoked, then this routine is a harmless no-op.
*/
int sqlite3_shutdown(void){







  if( sqlite3GlobalConfig.isInit ){
#ifdef SQLITE_EXTRA_SHUTDOWN
    void SQLITE_EXTRA_SHUTDOWN(void);
    SQLITE_EXTRA_SHUTDOWN();
#endif
    sqlite3_os_end();
    sqlite3_reset_auto_extension();
................................................................................
      /* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit
      ** unsigned integer value that specifies the maximum size of the created
      ** heap. */
      sqlite3GlobalConfig.nHeap = va_arg(ap, int);
      break;
    }
#endif






    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
................................................................................
}

/*
** Return the filename of the database associated with a database
** connection.
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
  return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
}

/*
** Return 1 if database is read-only or 0 if read/write.  Return -1 if
** no such database exists.
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return -1;
  }
#endif
  Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
  return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
}

#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)

#include "sqlite3_private.h"








|







 







>
>
>
>
>
>
>







 







>
>
>
>
>







 







>






|








>






|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
....
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
** If the following function pointer is not NULL and if
** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
** I/O active are written using this function.  These messages
** are intended for debugging activity only.
*/
/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
#endif

/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
**
................................................................................
** there are outstanding database connections or memory allocations or
** while any part of SQLite is otherwise in use in any thread.  This
** routine is not threadsafe.  But it is safe to invoke this routine
** on when SQLite is already shut down.  If SQLite is already shut down
** when this routine is invoked, then this routine is a harmless no-op.
*/
int sqlite3_shutdown(void){
#ifdef SQLITE_OMIT_WSD
  int rc = sqlite3_wsd_init(4096, 24);
  if( rc!=SQLITE_OK ){
    return rc;
  }
#endif

  if( sqlite3GlobalConfig.isInit ){
#ifdef SQLITE_EXTRA_SHUTDOWN
    void SQLITE_EXTRA_SHUTDOWN(void);
    SQLITE_EXTRA_SHUTDOWN();
#endif
    sqlite3_os_end();
    sqlite3_reset_auto_extension();
................................................................................
      /* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit
      ** unsigned integer value that specifies the maximum size of the created
      ** heap. */
      sqlite3GlobalConfig.nHeap = va_arg(ap, int);
      break;
    }
#endif

    case SQLITE_CONFIG_PMASZ: {
      sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int);
      break;
    }

    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
................................................................................
}

/*
** Return the filename of the database associated with a database
** connection.
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
  Btree *pBt;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  pBt = sqlite3DbNameToBtree(db, zDbName);
  return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
}

/*
** Return 1 if database is read-only or 0 if read/write.  Return -1 if
** no such database exists.
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
  Btree *pBt;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return -1;
  }
#endif
  pBt = sqlite3DbNameToBtree(db, zDbName);
  return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
}

#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)

#include "sqlite3_private.h"

Changes to src/mutex_w32.c.

205
206
207
208
209
210
211






212
213
214
215
216
217
218
#else
        InitializeCriticalSection(&p->mutex);
#endif
      }
      break;
    }
    default: {






      assert( iType-2 >= 0 );
      assert( iType-2 < ArraySize(winMutex_staticMutexes) );
      assert( winMutex_isInit==1 );
      p = &winMutex_staticMutexes[iType-2];
#ifdef SQLITE_DEBUG
      p->id = iType;
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC







>
>
>
>
>
>







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#else
        InitializeCriticalSection(&p->mutex);
#endif
      }
      break;
    }
    default: {
#ifdef SQLITE_ENABLE_API_ARMOR
      if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
        (void)SQLITE_MISUSE_BKPT;
        return 0;
      }
#endif
      assert( iType-2 >= 0 );
      assert( iType-2 < ArraySize(winMutex_staticMutexes) );
      assert( winMutex_isInit==1 );
      p = &winMutex_staticMutexes[iType-2];
#ifdef SQLITE_DEBUG
      p->id = iType;
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC

Changes to src/os_unix.c.

4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128

4129
4130
4131
4132
4133
4134
4135
4136
4137
4138



4139
4140
4141
4142




4143
4144
4145
4146
4147
4148
4149
      ** or an error number on  failure". See the manpage for details. */
      int err;
      do{
        err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
      }while( err==EINTR );
      if( err ) return SQLITE_IOERR_WRITE;
#else
      /* If the OS does not have posix_fallocate(), fake it. First use
      ** ftruncate() to set the file size, then write a single byte to
      ** the last byte in each block within the extended region. This
      ** is the same technique used by glibc to implement posix_fallocate()

      ** on systems that do not have a real fallocate() system call.
      */
      int nBlk = buf.st_blksize;  /* File-system block size */
      i64 iWrite;                 /* Next offset to write to */

      if( robust_ftruncate(pFile->h, nSize) ){
        storeLastErrno(pFile, errno);
        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
      }
      iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;



      while( iWrite<nSize ){
        int nWrite = seekAndWrite(pFile, iWrite, "", 1);
        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
        iWrite += nBlk;




      }
#endif
    }
  }

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){







|
|
|
|
>
|









>
>
>
|


<
>
>
>
>







4118
4119
4120
4121
4122
4123
4124
4125
4126
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
4156
      ** or an error number on  failure". See the manpage for details. */
      int err;
      do{
        err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
      }while( err==EINTR );
      if( err ) return SQLITE_IOERR_WRITE;
#else
      /* If the OS does not have posix_fallocate(), fake it. Write a 
      ** single byte to the last byte in each block that falls entirely
      ** within the extended region. Then, if required, a single byte
      ** at offset (nSize-1), to set the size of the file correctly.
      ** This is a similar technique to that used by glibc on systems
      ** that do not have a real fallocate() call.
      */
      int nBlk = buf.st_blksize;  /* File-system block size */
      i64 iWrite;                 /* Next offset to write to */

      if( robust_ftruncate(pFile->h, nSize) ){
        storeLastErrno(pFile, errno);
        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
      }
      iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
      assert( iWrite>=buf.st_size );
      assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) );
      assert( ((iWrite+1)%nBlk)==0 );
      for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){
        int nWrite = seekAndWrite(pFile, iWrite, "", 1);
        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;

      }
      if( nSize%nBlk ){
        int nWrite = seekAndWrite(pFile, nSize-1, "", 1);
        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
      }
#endif
    }
  }

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){

Changes to src/os_win.c.

2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
....
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
....
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
*/
static int winRead(
  sqlite3_file *id,          /* File to read from */
  void *pBuf,                /* Write content into this buffer */
  int amt,                   /* Number of bytes to read */
  sqlite3_int64 offset       /* Begin reading at this offset */
){
#if !SQLITE_OS_WINCE
  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 );
................................................................................
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE
  if( winSeekFile(pFile, offset) ){
    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
    return SQLITE_FULL;
  }
  while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
#else
  memset(&overlapped, 0, sizeof(OVERLAPPED));
................................................................................
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE
  rc = winSeekFile(pFile, offset);
  if( rc==0 ){
#else
  {
#endif
#if !SQLITE_OS_WINCE
    OVERLAPPED overlapped;        /* The offset for WriteFile. */
#endif
    u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
    int nRem = amt;               /* Number of bytes yet to be written */
    DWORD nWrite;                 /* Bytes written by each WriteFile() call */
    DWORD lastErrno = NO_ERROR;   /* Value returned by GetLastError() */

#if !SQLITE_OS_WINCE
    memset(&overlapped, 0, sizeof(OVERLAPPED));
    overlapped.Offset = (LONG)(offset & 0xffffffff);
    overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
#endif

    while( nRem>0 ){
#if SQLITE_OS_WINCE
      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
#else
      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
#endif
        if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
        break;
      }
      assert( nWrite==0 || nWrite<=(DWORD)nRem );
      if( nWrite==0 || nWrite>(DWORD)nRem ){
        lastErrno = osGetLastError();
        break;
      }
#if !SQLITE_OS_WINCE
      offset += nWrite;
      overlapped.Offset = (LONG)(offset & 0xffffffff);
      overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
#endif
      aRem += nWrite;
      nRem -= nWrite;
    }







|







 







|







 







|





|







|






|












|







2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
....
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
....
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
*/
static int winRead(
  sqlite3_file *id,          /* File to read from */
  void *pBuf,                /* Write content into this buffer */
  int amt,                   /* Number of bytes to read */
  sqlite3_int64 offset       /* Begin reading at this offset */
){
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
  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 );
................................................................................
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
  if( winSeekFile(pFile, offset) ){
    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
    return SQLITE_FULL;
  }
  while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
#else
  memset(&overlapped, 0, sizeof(OVERLAPPED));
................................................................................
      pBuf = &((u8 *)pBuf)[nCopy];
      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
  rc = winSeekFile(pFile, offset);
  if( rc==0 ){
#else
  {
#endif
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
    OVERLAPPED overlapped;        /* The offset for WriteFile. */
#endif
    u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
    int nRem = amt;               /* Number of bytes yet to be written */
    DWORD nWrite;                 /* Bytes written by each WriteFile() call */
    DWORD lastErrno = NO_ERROR;   /* Value returned by GetLastError() */

#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
    memset(&overlapped, 0, sizeof(OVERLAPPED));
    overlapped.Offset = (LONG)(offset & 0xffffffff);
    overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
#endif

    while( nRem>0 ){
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
#else
      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
#endif
        if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
        break;
      }
      assert( nWrite==0 || nWrite<=(DWORD)nRem );
      if( nWrite==0 || nWrite>(DWORD)nRem ){
        lastErrno = osGetLastError();
        break;
      }
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
      offset += nWrite;
      overlapped.Offset = (LONG)(offset & 0xffffffff);
      overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
#endif
      aRem += nWrite;
      nRem -= nWrite;
    }

Changes to src/pager.c.

642
643
644
645
646
647
648


649
650
651
652
653
654
655
...
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673
674
675
....
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686








1687
1688
1689
1690
1691
1692
1693
....
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
....
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
....
5311
5312
5313
5314
5315
5316
5317

5318
5319
5320
5321
5322
5323
5324
....
5460
5461
5462
5463
5464
5465
5466

5467
5468
5469
5470
5471
5472
5473
....
6329
6330
6331
6332
6333
6334
6335

6336
6337
6338
6339
6340
6341
6342
  */
  u8 eState;                  /* Pager state (OPEN, READER, WRITER_LOCKED..) */
  u8 eLock;                   /* Current lock held on database file */
  u8 changeCountDone;         /* Set after incrementing the change-counter */
  u8 setMaster;               /* True if a m-j name has been written to jrnl */
  u8 doNotSpill;              /* Do not spill the cache when non-zero */
  u8 subjInMemory;            /* True to use in-memory sub-journals */


  Pgno dbSize;                /* Number of pages in the database */
  Pgno dbOrigSize;            /* dbSize before the current transaction */
  Pgno dbFileSize;            /* Number of pages in the database file */
  Pgno dbHintSize;            /* Value passed to FCNTL_SIZE_HINT call */
  int errCode;                /* One of several kinds of errors */
  int nRec;                   /* Pages journalled since last j-header written */
  u32 cksumInit;              /* Quasi-random value added to every checksum */
................................................................................
  sqlite3_file *jfd;          /* File descriptor for main journal */
  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
  ***************************************************************************/

................................................................................
  return rc;
}

/*
** Discard the entire contents of the in-memory page-cache.
*/
static void pager_reset(Pager *pPager){

  sqlite3BackupRestart(pPager->pBackup);
  sqlite3PcacheClear(pPager->pPCache);
}









/*
** Free all structures in the Pager.aSavepoint[] array and set both
** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
** if it is open and the pager is not in exclusive mode.
*/
static void releaseAllSavepoints(Pager *pPager){
................................................................................
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);
................................................................................

      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
      ** at offset 24 into the file.  The first 4 of these 16 bytes are
      ** a 32-bit counter that is incremented with each change.  The
      ** other bytes change randomly with each file change when
      ** a codec is in use.
      ** 
................................................................................
  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) ){
................................................................................
*/
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
  sqlite3_pcache_page *pPage;
  assert( pPager!=0 );
  assert( pgno!=0 );
  assert( pPager->pPCache!=0 );
  pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);

  return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
}

/*
** Release a page reference.
**
** If the number of references to the page drop to zero, then the
................................................................................
  ){
    assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
    pPager->eState = PAGER_READER;
    return SQLITE_OK;
  }

  PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));

  rc = pager_end_transaction(pPager, pPager->setMaster, 1);
  return pager_error(pPager, rc);
}

/*
** If a write transaction is open, then all changes made within the 
** transaction are reverted and the current write-transaction is closed.







>
>







 







>


<







 







>



>
>
>
>
>
>
>
>







 







|







 







|
|
|
|
|
|
<
<
<
<







 







>







 







>







 







>







642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
...
661
662
663
664
665
666
667
668
669
670

671
672
673
674
675
676
677
....
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
....
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
....
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160




5161
5162
5163
5164
5165
5166
5167
....
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
....
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
....
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
  */
  u8 eState;                  /* Pager state (OPEN, READER, WRITER_LOCKED..) */
  u8 eLock;                   /* Current lock held on database file */
  u8 changeCountDone;         /* Set after incrementing the change-counter */
  u8 setMaster;               /* True if a m-j name has been written to jrnl */
  u8 doNotSpill;              /* Do not spill the cache when non-zero */
  u8 subjInMemory;            /* True to use in-memory sub-journals */
  u8 bUseFetch;               /* True to use xFetch() */
  u8 hasBeenUsed;             /* True if any content previously read from this pager*/
  Pgno dbSize;                /* Number of pages in the database */
  Pgno dbOrigSize;            /* dbSize before the current transaction */
  Pgno dbFileSize;            /* Number of pages in the database file */
  Pgno dbHintSize;            /* Value passed to FCNTL_SIZE_HINT call */
  int errCode;                /* One of several kinds of errors */
  int nRec;                   /* Pages journalled since last j-header written */
  u32 cksumInit;              /* Quasi-random value added to every checksum */
................................................................................
  sqlite3_file *jfd;          /* File descriptor for main journal */
  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[] */
  u32 iDataVersion;           /* Changes whenever database content changes */
  char dbFileVers[16];        /* Changes whenever database file changes */


  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
  ***************************************************************************/

................................................................................
  return rc;
}

/*
** Discard the entire contents of the in-memory page-cache.
*/
static void pager_reset(Pager *pPager){
  pPager->iDataVersion++;
  sqlite3BackupRestart(pPager->pBackup);
  sqlite3PcacheClear(pPager->pPCache);
}

/*
** Return the pPager->iDataVersion value
*/
u32 sqlite3PagerDataVersion(Pager *pPager){
  assert( pPager->eState>PAGER_OPEN );
  return pPager->iDataVersion;
}

/*
** Free all structures in the Pager.aSavepoint[] array and set both
** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
** if it is open and the pager is not in exclusive mode.
*/
static void releaseAllSavepoints(Pager *pPager){
................................................................................
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);
................................................................................

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

    if( !pPager->tempFile && pPager->hasBeenUsed ){
      /* The shared-lock has just been acquired then check to
      ** see if the database has been modified.  If the database has changed,
      ** flush the cache.  The pPager->hasBeenUsed flag prevents this from
      ** occurring on the very first access to a file, in order to save a
      ** single unnecessary sqlite3OsRead() call at the start-up.




      **
      ** Database changes is detected by looking at 15 bytes beginning
      ** at offset 24 into the file.  The first 4 of these 16 bytes are
      ** a 32-bit counter that is incremented with each change.  The
      ** other bytes change randomly with each file change when
      ** a codec is in use.
      ** 
................................................................................
  assert( pPager->eState>=PAGER_READER );
  assert( assert_pager_state(pPager) );
  assert( noContent==0 || bMmapOk==0 );

  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  pPager->hasBeenUsed = 1;

  /* 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) ){
................................................................................
*/
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
  sqlite3_pcache_page *pPage;
  assert( pPager!=0 );
  assert( pgno!=0 );
  assert( pPager->pPCache!=0 );
  pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
  assert( pPage==0 || pPager->hasBeenUsed );
  return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
}

/*
** Release a page reference.
**
** If the number of references to the page drop to zero, then the
................................................................................
  ){
    assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
    pPager->eState = PAGER_READER;
    return SQLITE_OK;
  }

  PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
  pPager->iDataVersion++;
  rc = pager_end_transaction(pPager, pPager->setMaster, 1);
  return pager_error(pPager, rc);
}

/*
** If a write transaction is open, then all changes made within the 
** transaction are reverted and the current write-transaction is closed.

Changes to src/pager.h.

168
169
170
171
172
173
174

175
176
177
178
179
180
181

#ifdef SQLITE_ENABLE_ZIPVFS
  int sqlite3PagerWalFramesize(Pager *pPager);
#endif

/* Functions used to query pager state and configuration. */
u8 sqlite3PagerIsreadonly(Pager*);

int sqlite3PagerRefcount(Pager*);
int sqlite3PagerMemUsed(Pager*);
const char *sqlite3PagerFilename(Pager*, int);
const sqlite3_vfs *sqlite3PagerVfs(Pager*);
sqlite3_file *sqlite3PagerFile(Pager*);
sqlite3_file *sqlite3PagerWalFile(Pager *pPager);
const char *sqlite3PagerJournalname(Pager*);







>







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

#ifdef SQLITE_ENABLE_ZIPVFS
  int sqlite3PagerWalFramesize(Pager *pPager);
#endif

/* Functions used to query pager state and configuration. */
u8 sqlite3PagerIsreadonly(Pager*);
u32 sqlite3PagerDataVersion(Pager*);
int sqlite3PagerRefcount(Pager*);
int sqlite3PagerMemUsed(Pager*);
const char *sqlite3PagerFilename(Pager*, int);
const sqlite3_vfs *sqlite3PagerVfs(Pager*);
sqlite3_file *sqlite3PagerFile(Pager*);
sqlite3_file *sqlite3PagerWalFile(Pager *pPager);
const char *sqlite3PagerJournalname(Pager*);

Changes to src/pcache.c.

192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
...
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
** are no outstanding page references when this function is called.
*/
int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
  assert( pCache->nRef==0 && pCache->pDirty==0 );
  if( pCache->szPage ){
    sqlite3_pcache *pNew;
    pNew = sqlite3GlobalConfig.pcache2.xCreate(
                szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable

    );
    if( pNew==0 ) return SQLITE_NOMEM;
    sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
    if( pCache->pCache ){
      sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
    }
    pCache->pCache = pNew;
................................................................................
  sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
}

/*
** Return the size of the header added by this middleware layer
** in the page-cache hierarchy.
*/
int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); }


#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/*
** For all dirty pages currently in the cache, invoke the specified
** callback. This is only used if the SQLITE_CHECK_PAGES macro is
** defined.







|
>







 







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
** are no outstanding page references when this function is called.
*/
int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
  assert( pCache->nRef==0 && pCache->pDirty==0 );
  if( pCache->szPage ){
    sqlite3_pcache *pNew;
    pNew = sqlite3GlobalConfig.pcache2.xCreate(
                szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
                pCache->bPurgeable
    );
    if( pNew==0 ) return SQLITE_NOMEM;
    sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
    if( pCache->pCache ){
      sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
    }
    pCache->pCache = pNew;
................................................................................
  sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
}

/*
** Return the size of the header added by this middleware layer
** in the page-cache hierarchy.
*/
int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }


#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/*
** For all dirty pages currently in the cache, invoke the specified
** callback. This is only used if the SQLITE_CHECK_PAGES macro is
** defined.

Changes to src/pcache1.c.

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
  p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
  if( !pPg || !p ){
    pcache1Free(pPg);
    sqlite3_free(p);
    pPg = 0;
  }
#else
  pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
  p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
  pcache1EnterMutex(pCache->pGroup);

  if( pPg ){
    p->page.pBuf = pPg;
    p->page.pExtra = &p[1];
................................................................................
  };
  sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
}

/*
** Return the size of the header on each page of this PCACHE implementation.
*/
int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); }

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** This function is called to free superfluous dynamically allocated memory
** held by the pager system. Memory in use by any SQLite pager allocated
** by the current thread may be sqlite3_free()ed.
**







|







 







|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
  p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
  if( !pPg || !p ){
    pcache1Free(pPg);
    sqlite3_free(p);
    pPg = 0;
  }
#else
  pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra);
  p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
  pcache1EnterMutex(pCache->pGroup);

  if( pPg ){
    p->page.pBuf = pPg;
    p->page.pExtra = &p[1];
................................................................................
  };
  sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
}

/*
** Return the size of the header on each page of this PCACHE implementation.
*/
int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** This function is called to free superfluous dynamically allocated memory
** held by the pager system. Memory in use by any SQLite pager allocated
** by the current thread may be sqlite3_free()ed.
**

Changes to src/pragma.c.

67
68
69
70
71
72
73

74
75
76
77
78
79
80
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
149
150
151
152
153
154
155






156
157
158
159
160
161
162
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
....
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
2165
2166
2167
2168
2169
#define PragTyp_ACTIVATE_EXTENSIONS           36
#define PragTyp_HEXKEY                        37
#define PragTyp_KEY                           38
#define PragTyp_REKEY                         39
#define PragTyp_LOCK_STATUS                   40
#define PragTyp_PARSER_TRACE                  41
#define PragFlag_NeedSchema           0x01

static const struct sPragmaNames {
  const char *const zName;  /* Name of pragma */
  u8 ePragTyp;              /* PragTyp_XXX value */
  u8 mPragFlag;             /* Zero or more PragFlag_XXX values */
  u32 iArg;                 /* Extra argument */
} aPragmaNames[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
................................................................................
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "application_id",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
  { /* zName:     */ "auto_vacuum",
    /* ePragTyp:  */ PragTyp_AUTO_VACUUM,
    /* ePragFlag: */ PragFlag_NeedSchema,
    /* iArg:      */ 0 },
#endif
................................................................................
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
  { /* zName:     */ "data_store_directory",
    /* ePragTyp:  */ PragTyp_DATA_STORE_DIRECTORY,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif






#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
  { /* zName:     */ "database_list",
    /* ePragTyp:  */ PragTyp_DATABASE_LIST,
    /* ePragFlag: */ PragFlag_NeedSchema,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
................................................................................
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_ForeignKeys },
#endif
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "freelist_count",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  { /* zName:     */ "full_column_names",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_FullColNames },
  { /* zName:     */ "fullfsync",
................................................................................
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_ReverseOrder },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "schema_version",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
  { /* zName:     */ "secure_delete",
    /* ePragTyp:  */ PragTyp_SECURE_DELETE,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
................................................................................
    /* ePragTyp:  */ PragTyp_THREADS,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "user_version",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if defined(SQLITE_DEBUG)
  { /* zName:     */ "vdbe_addoptrace",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_VdbeAddopTrace },
................................................................................
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  { /* zName:     */ "writable_schema",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 57 on by default, 70 total. */
/* End of the automatically generated pragma table.
***************************************************************************/

/*
** Interpret the given string as a safety level.  Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
** unrecognized string argument.  The FULL option is disallowed
................................................................................
  ** the schema-version is potentially dangerous and may lead to program
  ** crashes or database corruption. Use with caution!
  **
  ** The user-version is not used internally by SQLite. It may be used by
  ** applications for any purpose.
  */
  case PragTyp_HEADER_VALUE: {
    int iCookie;   /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
    sqlite3VdbeUsesBtree(v, iDb);
    switch( zLeft[0] ){
      case 'a': case 'A':
        iCookie = BTREE_APPLICATION_ID;
        break;
      case 'f': case 'F':
        iCookie = BTREE_FREE_PAGE_COUNT;
        break;
      case 's': case 'S':
        iCookie = BTREE_SCHEMA_VERSION;
        break;
      default:
        iCookie = BTREE_USER_VERSION;
        break;
    }

    if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){
      /* Write the specified cookie value */
      static const VdbeOpList setCookie[] = {
        { OP_Transaction,    0,  1,  0},    /* 0 */
        { OP_Integer,        0,  1,  0},    /* 1 */
        { OP_SetCookie,      0,  0,  1},    /* 2 */
      };
      int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);







>







 







|







 







>
>
>
>
>
>







 







|
|







 







|







 







|







 







|







 







|

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
....
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154















2155
2156
2157
2158
2159
2160
2161
#define PragTyp_ACTIVATE_EXTENSIONS           36
#define PragTyp_HEXKEY                        37
#define PragTyp_KEY                           38
#define PragTyp_REKEY                         39
#define PragTyp_LOCK_STATUS                   40
#define PragTyp_PARSER_TRACE                  41
#define PragFlag_NeedSchema           0x01
#define PragFlag_ReadOnly             0x02
static const struct sPragmaNames {
  const char *const zName;  /* Name of pragma */
  u8 ePragTyp;              /* PragTyp_XXX value */
  u8 mPragFlag;             /* Zero or more PragFlag_XXX values */
  u32 iArg;                 /* Extra argument */
} aPragmaNames[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
................................................................................
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "application_id",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ 0,
    /* iArg:      */ BTREE_APPLICATION_ID },
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
  { /* zName:     */ "auto_vacuum",
    /* ePragTyp:  */ PragTyp_AUTO_VACUUM,
    /* ePragFlag: */ PragFlag_NeedSchema,
    /* iArg:      */ 0 },
#endif
................................................................................
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
  { /* zName:     */ "data_store_directory",
    /* ePragTyp:  */ PragTyp_DATA_STORE_DIRECTORY,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "data_version",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ PragFlag_ReadOnly,
    /* iArg:      */ BTREE_DATA_VERSION },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
  { /* zName:     */ "database_list",
    /* ePragTyp:  */ PragTyp_DATABASE_LIST,
    /* ePragFlag: */ PragFlag_NeedSchema,
    /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
................................................................................
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_ForeignKeys },
#endif
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "freelist_count",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ PragFlag_ReadOnly,
    /* iArg:      */ BTREE_FREE_PAGE_COUNT },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  { /* zName:     */ "full_column_names",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_FullColNames },
  { /* zName:     */ "fullfsync",
................................................................................
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_ReverseOrder },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "schema_version",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ 0,
    /* iArg:      */ BTREE_SCHEMA_VERSION },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
  { /* zName:     */ "secure_delete",
    /* ePragTyp:  */ PragTyp_SECURE_DELETE,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#endif
................................................................................
    /* ePragTyp:  */ PragTyp_THREADS,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
  { /* zName:     */ "user_version",
    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
    /* ePragFlag: */ 0,
    /* iArg:      */ BTREE_USER_VERSION },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if defined(SQLITE_DEBUG)
  { /* zName:     */ "vdbe_addoptrace",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_VdbeAddopTrace },
................................................................................
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  { /* zName:     */ "writable_schema",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 58 on by default, 71 total. */
/* End of the automatically generated pragma table.
***************************************************************************/

/*
** Interpret the given string as a safety level.  Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
** unrecognized string argument.  The FULL option is disallowed
................................................................................
  ** the schema-version is potentially dangerous and may lead to program
  ** crashes or database corruption. Use with caution!
  **
  ** The user-version is not used internally by SQLite. It may be used by
  ** applications for any purpose.
  */
  case PragTyp_HEADER_VALUE: {
    int iCookie = aPragmaNames[mid].iArg;  /* Which cookie to read or write */
    sqlite3VdbeUsesBtree(v, iDb);
    if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){















      /* Write the specified cookie value */
      static const VdbeOpList setCookie[] = {
        { OP_Transaction,    0,  1,  0},    /* 0 */
        { OP_Integer,        0,  1,  0},    /* 1 */
        { OP_SetCookie,      0,  0,  1},    /* 2 */
      };
      int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);

Changes to src/sqlite.h.in.

1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
....
1746
1747
1748
1749
1750
1751
1752











1753
1754
1755
1756
1757
1758
1759
....
1772
1773
1774
1775
1776
1777
1778

1779
1780
1781
1782
1783
1784
1785
** This configuration should not be used if an application-define page
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]
** configuration option.
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
** 8-byte aligned
** memory, the size of each page buffer (sz), and the number of pages (N).
** The sz argument should be the size of the largest database page
** (a power of two between 512 and 32768) plus some extra bytes for each
** page header.  ^The number of extra bytes needed by the page header
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option 
** to [sqlite3_config()].
** ^It is harmless, apart from the wasted memory,
** for the sz parameter to be larger than necessary.  The first
** argument should pointer to an 8-byte aligned block of memory that
** is at least sz*N bytes of memory, otherwise subsequent behavior is
................................................................................
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
** is a pointer to an integer and writes into that integer the number of extra
** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
** The amount of extra space required can change depending on the compiler,
** target platform, and SQLite version.











** </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_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 */
#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ        24  /* int *psz */


/*
** 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.
**







|







 







>
>
>
>
>
>
>
>
>
>
>







 







>







1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
....
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
....
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
** This configuration should not be used if an application-define page
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]
** configuration option.
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
** 8-byte aligned
** memory, the size of each page buffer (sz), and the number of pages (N).
** The sz argument should be the size of the largest database page
** (a power of two between 512 and 65536) plus some extra bytes for each
** page header.  ^The number of extra bytes needed by the page header
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option 
** to [sqlite3_config()].
** ^It is harmless, apart from the wasted memory,
** for the sz parameter to be larger than necessary.  The first
** argument should pointer to an 8-byte aligned block of memory that
** is at least sz*N bytes of memory, otherwise subsequent behavior is
................................................................................
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
** is a pointer to an integer and writes into that integer the number of extra
** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
** The amount of extra space required can change depending on the compiler,
** target platform, and SQLite version.
**
** [[SQLITE_CONFIG_PMASZ]]
** <dt>SQLITE_CONFIG_PMASZ
** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
** sorter to that integer.  The default minimum PMA Size is set by the
** [SQLITE_SORTER_PMASZ] compile-time option.  New threads are launched
** to help with sort operations when multithreaded sorting
** is enabled (using the [PRAGMA threads] command) and the amount of content
** to be sorted exceeds the page size times the minimum of the
** [PRAGMA cache_size] setting and this value.
** </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_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 */
#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ        24  /* int *psz */
#define SQLITE_CONFIG_PMASZ               25  /* unsigned int szPma */

/*
** 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.
**

Changes to src/sqliteInt.h.

2845
2846
2847
2848
2849
2850
2851

2852
2853
2854
2855
2856
2857
2858
  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 */
  int sharedCacheEnabled;           /* true if shared-cache mode enabled */

  /* The above might be initialized to non-zero.  The following need to always
  ** initially be zero, however. */
  int isInit;                       /* True after initialization has finished */
  int inProgress;                   /* True while initialization in progress */
  int isMutexInit;                  /* True after mutexes are initialized */
  int isMallocInit;                 /* True after malloc is initialized */
  int isPCacheInit;                 /* True after malloc is initialized */







>







2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
  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 */
  int sharedCacheEnabled;           /* true if shared-cache mode enabled */
  u32 szPma;                        /* Maximum Sorter PMA size */
  /* The above might be initialized to non-zero.  The following need to always
  ** initially be zero, however. */
  int isInit;                       /* True after initialization has finished */
  int inProgress;                   /* True while initialization in progress */
  int isMutexInit;                  /* True after mutexes are initialized */
  int isMallocInit;                 /* True after malloc is initialized */
  int isPCacheInit;                 /* True after malloc is initialized */

Changes to src/table.c.

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  int *pnColumn,              /* Write the number of columns of result here */
  char **pzErrMsg             /* Write error messages here */
){
  int rc;
  TabResult res;

#ifdef SQLITE_ENABLE_API_ARMOR
  if( pazResult==0 ) return SQLITE_MISUSE_BKPT;
#endif
  *pazResult = 0;
  if( pnColumn ) *pnColumn = 0;
  if( pnRow ) *pnRow = 0;
  if( pzErrMsg ) *pzErrMsg = 0;
  res.zErrMsg = 0;
  res.nRow = 0;







|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  int *pnColumn,              /* Write the number of columns of result here */
  char **pzErrMsg             /* Write error messages here */
){
  int rc;
  TabResult res;

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT;
#endif
  *pazResult = 0;
  if( pnColumn ) *pnColumn = 0;
  if( pnRow ) *pnRow = 0;
  if( pzErrMsg ) *pzErrMsg = 0;
  res.zErrMsg = 0;
  res.nRow = 0;

Changes to src/test1.c.

3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
  rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
  free(zCopy);
  zTail = &zSql[(zTail - zCopy)];

  assert(rc==SQLITE_OK || pStmt==0);
  Tcl_ResetResult(interp);
  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  if( zTail && objc>=5 ){
    if( bytes>=0 ){
      bytes = bytes - (int)(zTail-zSql);
    }
    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
  }
  if( rc!=SQLITE_OK ){
    assert( pStmt==0 );







|







3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
  rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
  free(zCopy);
  zTail = &zSql[(zTail - zCopy)];

  assert(rc==SQLITE_OK || pStmt==0);
  Tcl_ResetResult(interp);
  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  if( rc==SQLITE_OK && zTail && objc>=5 ){
    if( bytes>=0 ){
      bytes = bytes - (int)(zTail-zSql);
    }
    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
  }
  if( rc!=SQLITE_OK ){
    assert( pStmt==0 );

Changes to src/test8.c.

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
** This module uses only sqlite3_index_info.idxStr, not 
** sqlite3_index_info.idxNum. So to test idxNum, when idxStr is set
** in echoBestIndex(), idxNum is set to the corresponding hash value.
** In echoFilter(), code assert()s that the supplied idxNum value is
** indeed the hash of the supplied idxStr.
*/
static int hashString(const char *zString){
  int val = 0;
  int ii;
  for(ii=0; zString[ii]; ii++){
    val = (val << 3) + (int)zString[ii];
  }
  return val;
}

/* 
** Echo virtual table module xFilter method.
*/
static int echoFilter(
  sqlite3_vtab_cursor *pVtabCursor, 







|




|







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
** This module uses only sqlite3_index_info.idxStr, not 
** sqlite3_index_info.idxNum. So to test idxNum, when idxStr is set
** in echoBestIndex(), idxNum is set to the corresponding hash value.
** In echoFilter(), code assert()s that the supplied idxNum value is
** indeed the hash of the supplied idxStr.
*/
static int hashString(const char *zString){
  u32 val = 0;
  int ii;
  for(ii=0; zString[ii]; ii++){
    val = (val << 3) + (int)zString[ii];
  }
  return (int)(val&0x7fffffff);
}

/* 
** Echo virtual table module xFilter method.
*/
static int echoFilter(
  sqlite3_vtab_cursor *pVtabCursor, 

Changes to src/test_malloc.c.

1256
1257
1258
1259
1260
1261
1262




























1263
1264
1265
1266
1267
1268
1269
....
1510
1511
1512
1513
1514
1515
1516

1517
1518
1519
1520
1521
1522
1523

  rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);

  return TCL_OK;
}






























/*
** Usage:    sqlite3_dump_memsys3  FILENAME
**           sqlite3_dump_memsys5  FILENAME
**
** Write a summary of unfreed memsys3 allocations to FILENAME.
*/
................................................................................
     { "sqlite3_config_heap",        test_config_heap              ,0 },
     { "sqlite3_config_heap_size",   test_config_heap_size         ,0 },
     { "sqlite3_config_memstatus",   test_config_memstatus         ,0 },
     { "sqlite3_config_lookaside",   test_config_lookaside         ,0 },
     { "sqlite3_config_error",       test_config_error             ,0 },
     { "sqlite3_config_uri",         test_config_uri               ,0 },
     { "sqlite3_config_cis",         test_config_cis               ,0 },

     { "sqlite3_db_config_lookaside",test_db_config_lookaside      ,0 },
     { "sqlite3_dump_memsys3",       test_dump_memsys3             ,3 },
     { "sqlite3_dump_memsys5",       test_dump_memsys3             ,5 },
     { "sqlite3_install_memsys3",    test_install_memsys3          ,0 },
     { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test          ,0 },
  };
  int i;







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







 







>







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
....
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552

  rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);

  return TCL_OK;
}

/*
** Usage:    sqlite3_config_pmasz  INTEGER
**
** Set the minimum PMA size.
*/
static int test_config_pmasz(
  void * clientData, 
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc;
  int iPmaSz;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp, objv[1], &iPmaSz) ){
    return TCL_ERROR;
  }

  rc = sqlite3_config(SQLITE_CONFIG_PMASZ, iPmaSz);
  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);

  return TCL_OK;
}


/*
** Usage:    sqlite3_dump_memsys3  FILENAME
**           sqlite3_dump_memsys5  FILENAME
**
** Write a summary of unfreed memsys3 allocations to FILENAME.
*/
................................................................................
     { "sqlite3_config_heap",        test_config_heap              ,0 },
     { "sqlite3_config_heap_size",   test_config_heap_size         ,0 },
     { "sqlite3_config_memstatus",   test_config_memstatus         ,0 },
     { "sqlite3_config_lookaside",   test_config_lookaside         ,0 },
     { "sqlite3_config_error",       test_config_error             ,0 },
     { "sqlite3_config_uri",         test_config_uri               ,0 },
     { "sqlite3_config_cis",         test_config_cis               ,0 },
     { "sqlite3_config_pmasz",       test_config_pmasz             ,0 },
     { "sqlite3_db_config_lookaside",test_db_config_lookaside      ,0 },
     { "sqlite3_dump_memsys3",       test_dump_memsys3             ,3 },
     { "sqlite3_dump_memsys5",       test_dump_memsys3             ,5 },
     { "sqlite3_install_memsys3",    test_install_memsys3          ,0 },
     { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test          ,0 },
  };
  int i;

Changes to src/tokenize.c.

387
388
389
390
391
392
393



394
395
396
397
398
399
400
  int tokenType;                  /* type of the next token */
  int lastTokenParsed = -1;       /* type of the previous token */
  u8 enableLookaside;             /* Saved value of db->lookaside.bEnabled */
  sqlite3 *db = pParse->db;       /* The database connection */
  int mxSqlLen;                   /* Max length of an SQL string */





  mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
  if( db->nVdbeActive==0 ){
    db->u1.isInterrupted = 0;
  }
  pParse->rc = SQLITE_OK;
  pParse->zTail = zSql;
  i = 0;







>
>
>







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  int tokenType;                  /* type of the next token */
  int lastTokenParsed = -1;       /* type of the previous token */
  u8 enableLookaside;             /* Saved value of db->lookaside.bEnabled */
  sqlite3 *db = pParse->db;       /* The database connection */
  int mxSqlLen;                   /* Max length of an SQL string */


#ifdef SQLITE_ENABLE_API_ARMOR
  if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT;
#endif
  mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
  if( db->nVdbeActive==0 ){
    db->u1.isInterrupted = 0;
  }
  pParse->rc = SQLITE_OK;
  pParse->zTail = zSql;
  i = 0;

Changes to src/vdbeaux.c.

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
** match, or false otherwise. This function is intended to be used as
** part of an assert statement in the compiler. Similar to:
**
**   assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
*/
int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
  int hasAbort = 0;

  Op *pOp;
  VdbeOpIter sIter;
  memset(&sIter, 0, sizeof(sIter));
  sIter.v = v;

  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
#ifndef SQLITE_OMIT_FOREIGN_KEY
     || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) 
#endif
     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }





  }
  sqlite3DbFree(v->db, sIter.apSub);

  /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
  ** If malloc failed, then the while() loop above may not have iterated
  ** through all opcodes and hasAbort may be set incorrectly. Return
  ** true for this case to prevent the assert() in the callers frame
  ** from failing.  */
  return ( v->db->mallocFailed || hasAbort==mayAbort );
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */

/*
** Loop through the program looking for P2 values that are negative
** on jump instructions.  Each such value is a label.  Resolve the
** label by setting the P2 value to its correct non-zero value.







>








<
<
<






>
>
>
>
>








|







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
** match, or false otherwise. This function is intended to be used as
** part of an assert statement in the compiler. Similar to:
**
**   assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
*/
int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
  int hasAbort = 0;
  int hasFkCounter = 0;
  Op *pOp;
  VdbeOpIter sIter;
  memset(&sIter, 0, sizeof(sIter));
  sIter.v = v;

  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 



     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }
#ifndef SQLITE_OMIT_FOREIGN_KEY
    if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
      hasFkCounter = 1;
    }
#endif
  }
  sqlite3DbFree(v->db, sIter.apSub);

  /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
  ** If malloc failed, then the while() loop above may not have iterated
  ** through all opcodes and hasAbort may be set incorrectly. Return
  ** true for this case to prevent the assert() in the callers frame
  ** from failing.  */
  return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter );
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */

/*
** Loop through the program looking for P2 values that are negative
** on jump instructions.  Each such value is a label.  Resolve the
** label by setting the P2 value to its correct non-zero value.

Changes to src/vdbesort.c.

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
...
847
848
849
850
851
852
853

854
855
856

857
858
859
860
861
862
863
864
....
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137



1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
#endif

/*
** Hard-coded maximum amount of data to accumulate in memory before flushing
** to a level 0 PMA. The purpose of this limit is to prevent various integer
** overflows. 512MiB.
*/
#define SQLITE_MAX_MXPMASIZE    (1<<29)

/*
** Private objects used by the sorter
*/
typedef struct MergeEngine MergeEngine;     /* Merge PMAs together */
typedef struct PmaReader PmaReader;         /* Incrementally read one PMA */
typedef struct PmaWriter PmaWriter;         /* Incrementally write one PMA */
................................................................................
/* Return a pointer to the buffer containing the record data for SorterRecord
** object p. Should be used as if:
**
**   void *SRVAL(SorterRecord *p) { return (void*)&p[1]; }
*/
#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))

/* The minimum PMA size is set to this value multiplied by the database
** page size in bytes.  */
#ifndef SQLITE_SORTER_PMASZ
# define SQLITE_SORTER_PMASZ 10
#endif

/* Maximum number of PMAs that a single MergeEngine can merge */
#define SORTER_MAX_MERGE_COUNT 16

static int vdbeIncrSwap(IncrMerger*);
static void vdbeIncrFree(IncrMerger *);

................................................................................
    pSorter->db = db;
    for(i=0; i<pSorter->nTask; i++){
      SortSubtask *pTask = &pSorter->aTask[i];
      pTask->pSorter = pSorter;
    }

    if( !sqlite3TempInMemory(db) ){

      pSorter->mnPmaSize = SQLITE_SORTER_PMASZ * pgsz;
      mxCache = db->aDb[0].pSchema->cache_size;
      if( mxCache<SQLITE_SORTER_PMASZ ) mxCache = SQLITE_SORTER_PMASZ;

      pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE);

      /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
      ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
      ** large heap allocations.
      */
      if( sqlite3GlobalConfig.pScratch==0 ){
        assert( pSorter->iMemory==0 );
................................................................................
** the VFS has memory mapped it.
**
** Whether or not the file does end up memory mapped of course depends on
** the specific VFS implementation.
*/
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
  if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
    int rc = sqlite3OsTruncate(pFd, nByte);
    if( rc==SQLITE_OK ){
      void *p = 0;



      sqlite3OsFetch(pFd, 0, (int)nByte, &p);
      sqlite3OsUnfetch(pFd, 0, p);
    }
  }
}
#else
# define vdbeSorterExtendFile(x,y,z)
#endif

/*







|







 







<
<
<
<
<







 







>
|

<
>
|







 







<
<
|
>
>
>
|
|
<







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
...
444
445
446
447
448
449
450





451
452
453
454
455
456
457
...
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859
860
....
1124
1125
1126
1127
1128
1129
1130


1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
#endif

/*
** Hard-coded maximum amount of data to accumulate in memory before flushing
** to a level 0 PMA. The purpose of this limit is to prevent various integer
** overflows. 512MiB.
*/
#define SQLITE_MAX_PMASZ    (1<<29)

/*
** Private objects used by the sorter
*/
typedef struct MergeEngine MergeEngine;     /* Merge PMAs together */
typedef struct PmaReader PmaReader;         /* Incrementally read one PMA */
typedef struct PmaWriter PmaWriter;         /* Incrementally write one PMA */
................................................................................
/* Return a pointer to the buffer containing the record data for SorterRecord
** object p. Should be used as if:
**
**   void *SRVAL(SorterRecord *p) { return (void*)&p[1]; }
*/
#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))







/* Maximum number of PMAs that a single MergeEngine can merge */
#define SORTER_MAX_MERGE_COUNT 16

static int vdbeIncrSwap(IncrMerger*);
static void vdbeIncrFree(IncrMerger *);

................................................................................
    pSorter->db = db;
    for(i=0; i<pSorter->nTask; i++){
      SortSubtask *pTask = &pSorter->aTask[i];
      pTask->pSorter = pSorter;
    }

    if( !sqlite3TempInMemory(db) ){
      u32 szPma = sqlite3GlobalConfig.szPma;
      pSorter->mnPmaSize = szPma * pgsz;
      mxCache = db->aDb[0].pSchema->cache_size;

      if( mxCache<szPma ) mxCache = szPma;
      pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);

      /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
      ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
      ** large heap allocations.
      */
      if( sqlite3GlobalConfig.pScratch==0 ){
        assert( pSorter->iMemory==0 );
................................................................................
** the VFS has memory mapped it.
**
** Whether or not the file does end up memory mapped of course depends on
** the specific VFS implementation.
*/
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
  if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){


    void *p = 0;
    int chunksize = 4*1024;
    sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
    sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
    sqlite3OsFetch(pFd, 0, (int)nByte, &p);
    sqlite3OsUnfetch(pFd, 0, p);

  }
}
#else
# define vdbeSorterExtendFile(x,y,z)
#endif

/*

Changes to src/wal.c.

2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
    if( rc!=SQLITE_OK ){
      return rc;
    }
    nCollide = HASHTABLE_NSLOT;
    for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
      u32 iFrame = aHash[iKey] + iZero;
      if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
        /* assert( iFrame>iRead ); -- not true if there is corruption */
        iRead = iFrame;
      }
      if( (nCollide--)==0 ){
        return SQLITE_CORRUPT_BKPT;
      }
    }
  }







|







2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
    if( rc!=SQLITE_OK ){
      return rc;
    }
    nCollide = HASHTABLE_NSLOT;
    for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
      u32 iFrame = aHash[iKey] + iZero;
      if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
        assert( iFrame>iRead || CORRUPT_DB );
        iRead = iFrame;
      }
      if( (nCollide--)==0 ){
        return SQLITE_CORRUPT_BKPT;
      }
    }
  }

Changes to test/bigsort.test.

16
17
18
19
20
21
22









23
24
25
26
27
28
29
..
35
36
37
38
39
40
41
42
43

#--------------------------------------------------------------------
# At one point there was an overflow problem if the product of the 
# cache-size and page-size was larger than 2^31. Causing an infinite 
# loop if the product was also an integer multiple of 2^32, or 
# inefficiency otherwise.
#









do_execsql_test 1.0 {
  PRAGMA page_size = 1024;
  CREATE TABLE t1(a, b);
  BEGIN;
  WITH data(x,y) AS (
    SELECT 1, zeroblob(10000)
    UNION ALL
................................................................................
do_execsql_test 1.1 {
  PRAGMA cache_size = 4194304;
  CREATE INDEX i1 ON t1(a, b);
}


finish_test









>
>
>
>
>
>
>
>
>







 







<
<
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
44
45
46
47
48
49
50



#--------------------------------------------------------------------
# At one point there was an overflow problem if the product of the 
# cache-size and page-size was larger than 2^31. Causing an infinite 
# loop if the product was also an integer multiple of 2^32, or 
# inefficiency otherwise.
#
# This test causes thrashing on machines with smaller amounts of
# memory.  Make sure the host has at least 8GB available before running
# this test.
#
if {[catch {exec free | grep Mem:} out] || [lindex $out 1]<8000000} {
  finish_test
  return
}

do_execsql_test 1.0 {
  PRAGMA page_size = 1024;
  CREATE TABLE t1(a, b);
  BEGIN;
  WITH data(x,y) AS (
    SELECT 1, zeroblob(10000)
    UNION ALL
................................................................................
do_execsql_test 1.1 {
  PRAGMA cache_size = 4194304;
  CREATE INDEX i1 ON t1(a, b);
}


finish_test


Changes to test/e_walauto.test.

62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
    }
  }
} {

  eval $code

  reset_db

  do_execsql_test 1.$tn.0 { PRAGMA journal_mode = WAL } {wal}
  do_execsql_test 1.$tn.1 { CREATE TABLE t1(a, b) }
  set shmfd [open "test.db-shm"]

  # EVIDENCE-OF: R-41531-51083 Every new database connection defaults to
  # having the auto-checkpoint enabled with a threshold of 1000 or
  # SQLITE_DEFAULT_WAL_AUTOCHECKPOINT pages.
  #
  do_autocommit_threshold_test 1.$tn.2 1000
  db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }







>


|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    }
  }
} {

  eval $code

  reset_db
  execsql { PRAGMA auto_vacuum = 0 }
  do_execsql_test 1.$tn.0 { PRAGMA journal_mode = WAL } {wal}
  do_execsql_test 1.$tn.1 { CREATE TABLE t1(a, b) }
  set shmfd [open "test.db-shm" rb]

  # EVIDENCE-OF: R-41531-51083 Every new database connection defaults to
  # having the auto-checkpoint enabled with a threshold of 1000 or
  # SQLITE_DEFAULT_WAL_AUTOCHECKPOINT pages.
  #
  do_autocommit_threshold_test 1.$tn.2 1000
  db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }

Changes to test/e_walckpt.test.

243
244
245
246
247
248
249

250
251
252
253
254
255
256
...
702
703
704
705
706
707
708

709
710
711
712
713
714
715
  testvfs tvfs
  tvfs filter xWrite
  sqlite3 db test.db -vfs tvfs
  sqlite3 db2 test.db -vfs tvfs

  do_test $tn.3.2.1 {
    db2 eval {

      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(x, y);
      INSERT INTO t1 VALUES(1,2);
      INSERT INTO t1 VALUES(3,4);
      INSERT INTO t1 VALUES(5,6);
    }
    file size test.db-wal
................................................................................
}

reset_db
sqlite3 db2 test.db

do_test 6.1 {
  execsql {

    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
  file size test.db-wal
} [wal_file_size 3 1024]








>







 







>







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
  testvfs tvfs
  tvfs filter xWrite
  sqlite3 db test.db -vfs tvfs
  sqlite3 db2 test.db -vfs tvfs

  do_test $tn.3.2.1 {
    db2 eval {
      PRAGMA auto_vacuum = 0;
      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(x, y);
      INSERT INTO t1 VALUES(1,2);
      INSERT INTO t1 VALUES(3,4);
      INSERT INTO t1 VALUES(5,6);
    }
    file size test.db-wal
................................................................................
}

reset_db
sqlite3 db2 test.db

do_test 6.1 {
  execsql {
    PRAGMA auto_vacuum = 0; 
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
  file size test.db-wal
} [wal_file_size 3 1024]

Changes to test/fkey5.test.

248
249
250
251
252
253
254

255
256
257
258
259


260
261


262
263
264
265
266
267
268
do_test fkey5-6.5 {
  db eval {
    PRAGMA foreign_key_check(c12);
  }
} {c12 1 p4 0 c12 3 p4 0 c12 6 p4 0}

do_test fkey5-7.1 {

  db eval {
    INSERT OR IGNORE INTO c13 SELECT * FROM c12;
    INSERT OR IGNORE INTO C14 SELECT * FROM c12;
    DELETE FROM c12;
    PRAGMA foreign_key_check;


  }
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0 c13 1 p3 0 c13 2 p3 0 c13 3 p3 0 c13 4 p3 0 c13 5 p3 0 c13 6 p3 0}


do_test fkey5-7.2 {
  db eval {
    PRAGMA foreign_key_check(c14);
  }
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0}
do_test fkey5-7.3 {
  db eval {







>





>
>

<
>
>







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
do_test fkey5-6.5 {
  db eval {
    PRAGMA foreign_key_check(c12);
  }
} {c12 1 p4 0 c12 3 p4 0 c12 6 p4 0}

do_test fkey5-7.1 {
  set res {}
  db eval {
    INSERT OR IGNORE INTO c13 SELECT * FROM c12;
    INSERT OR IGNORE INTO C14 SELECT * FROM c12;
    DELETE FROM c12;
    PRAGMA foreign_key_check;
  } {
    lappend res [list $table $rowid $fkid $parent]
  }

  lsort $res
} {{c13 1 0 p3} {c13 2 0 p3} {c13 3 0 p3} {c13 4 0 p3} {c13 5 0 p3} {c13 6 0 p3} {c14 1 0 p4} {c14 3 0 p4} {c14 6 0 p4}}
do_test fkey5-7.2 {
  db eval {
    PRAGMA foreign_key_check(c14);
  }
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0}
do_test fkey5-7.3 {
  db eval {

Added test/fkey8.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
# 2001 September 15
#
# 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.
#
# This file implements tests for foreign keys.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fkey8

ifcapable {!foreignkey} {
  finish_test
  return
}
do_execsql_test 1.0 { PRAGMA foreign_keys = 1; }


foreach {tn use_stmt sql schema} {
  1   1 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1);
  }

  2.1     0 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE);
  }
  2.2   0 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE SET NULL);
  }
  2.3   1 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE SET DEFAULT);
  }

  3   1 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE);
    CREATE TRIGGER ct1 AFTER DELETE ON c1 BEGIN
      INSERT INTO p1 VALUES('x');
    END;
  }

  4   1 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
    CREATE TABLE cc1(d REFERENCES c1);
  }

  5.1   0 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
    CREATE TABLE cc1(d REFERENCES c1 ON DELETE CASCADE);
  }
  5.2   0 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
    CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET NULL);
  }
  5.3   1 "DELETE FROM p1" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
    CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET DEFAULT);
  }

  6.1   1 "UPDATE p1 SET a = ?" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c);
  }
  6.2   0 "UPDATE OR IGNORE p1 SET a = ?" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c);
  }
  6.3   1 "UPDATE OR IGNORE p1 SET a = ?" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b REFERENCES p1 ON UPDATE CASCADE, c);
  }
  6.4   1 "UPDATE OR IGNORE p1 SET a = ?" {
    CREATE TABLE p1(a PRIMARY KEY);
    CREATE TABLE c1(b NOT NULL REFERENCES p1 ON UPDATE SET NULL, c);
  }

} {
  drop_all_tables
  do_test 1.$tn {
    execsql $schema
    set stmt [sqlite3_prepare_v2 db $sql -1 dummy]
    set ret [uses_stmt_journal $stmt]
    sqlite3_finalize $stmt
    set ret
  } $use_stmt
}


finish_test

Changes to test/memsubsys1.test.

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
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
  expr {$maxreq<7000}
} 1
do_test memsubsys1-4.6 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1

# Test 5:  Activate both PAGECACHE and SCRATCH.  But make the page size
# such that the SCRATCH allocations are too small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
sqlite3_config_scratch 6000 2
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-5 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-5.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 24
set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
if {[lindex $msize 2]!=0} {
  do_test memsubsys1-5.4 {
    set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
    expr {$maxreq>4096}
  } 1
  do_test memsubsys1-5.5 {
................................................................................
sqlite3_config_scratch 25300 1
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-6 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-6.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 24
#do_test memsubsys1-6.4 {
#  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
#  expr {$maxreq>4096 && $maxreq<=(4096+$xtra_size)}
#} 1
do_test memsubsys1-6.5 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1







|





|






|







 







|







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
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
  expr {$maxreq<7000}
} 1
do_test memsubsys1-4.6 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1

# Test 5:  Activate both PAGECACHE and SCRATCH.  But make the page size is
# such that the SCRATCH allocations are too small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
sqlite3_config_scratch 4000 2
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-5 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-5.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} {/^2[34]$/}
set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
if {[lindex $msize 2]!=0} {
  do_test memsubsys1-5.4 {
    set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
    expr {$maxreq>4096}
  } 1
  do_test memsubsys1-5.5 {
................................................................................
sqlite3_config_scratch 25300 1
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-6 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-6.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} {/^2[34]$/}
#do_test memsubsys1-6.4 {
#  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
#  expr {$maxreq>4096 && $maxreq<=(4096+$xtra_size)}
#} 1
do_test memsubsys1-6.5 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1

Changes to test/notify2.test.

97
98
99
100
101
102
103


104
105
106
107
108
109
110
...
124
125
126
127
128
129
130

131
132
133
134
135
136
137
...
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
200
201
202
203
204
205
206
207


208
209
210
211
212
213
214
...
221
222
223
224
225
226
227
228








229
230
231
232
233
234
235
236
237


238









239
240
241
242
  opendb

  #after 2000

  # This loop runs for ~20 seconds.
  #
  set iStart [clock_seconds]


  while { ([clock_seconds]-$iStart) < $nSecond } {

    # Each transaction does 3 operations. Each operation is either a read
    # or write of a randomly selected table (t1, t2 or t3). Set the variables
    # $SQL(1), $SQL(2) and $SQL(3) to the SQL commands used to implement
    # each operation.
    #
................................................................................
            DROP INDEX IF EXISTS yyy.xxx_i;
      }
      ]]
    }

    # Execute the SQL transaction.
    #

    set rc [catch { execsql_blocking $::DB "
        BEGIN;
          $SQL(1);
          $SQL(2);
          $SQL(3);
        COMMIT;
      "
................................................................................
      # Hit some other kind of error. This is a malfunction.
      error $msg
    } else {
      # No error occurred. Check that any SELECT statements in the transaction
      # returned "1". Otherwise, the invariant was false, indicating that
      # some malfunction has occurred.
      foreach r $msg { if {$r != 1} { puts "Invariant check failed: $msg" } }

    }
  }

  # Close the database connection and return 0.
  #
  sqlite3_close $::DB
  expr 0
}

foreach {iTest xStep xPrepare} {
  1 sqlite3_blocking_step sqlite3_blocking_prepare_v2
  2 sqlite3_step          sqlite3_nonblocking_prepare_v2
} {
  forcedelete test.db test2.db test3.db
................................................................................
  unset -nocomplain finished
  for {set ii 0} {$ii < $nThread} {incr ii} {
    thread_spawn finished($ii) $ThreadSetup $ThreadProgram
  }
  for {set ii 0} {$ii < $nThread} {incr ii} {
    do_test notify2-$iTest.2.$ii {
      if {![info exists finished($ii)]} { vwait finished($ii) }
      set finished($ii)


    } {0}
  }

  # Count the total number of succesful writes.
  do_test notify2-$iTest.3.1 {
    sqlite3 db test.db
    execsql {
................................................................................
           + (SELECT max(a) FROM t3)
    }]
    db close
  } {}
}

# The following tests checks to make sure sqlite3_blocking_step() is
# faster than sqlite3_step().  blocking_step() is always faster on








# multi-core and is usually faster on single-core.  But sometimes, by
# chance, step() will be faster on a single core, in which case the
# following test will fail.
#
puts "The following test seeks to demonstrate that the sqlite3_unlock_notify()"
puts "interface helps multi-core systems to run faster.  This test sometimes"
puts "fails on single-core machines."
puts [array get anWrite]
do_test notify2-3 {


  expr {$anWrite(sqlite3_blocking_step) > $anWrite(sqlite3_step)}









} {1}

sqlite3_enable_shared_cache $::enable_shared_cache
finish_test







>
>







 







>







 







>






|







 







|
>
>







 







|
>
>
>
>
>
>
>
>
|
|



|
|


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




97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
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
  opendb

  #after 2000

  # This loop runs for ~20 seconds.
  #
  set iStart [clock_seconds]
  set nOp 0
  set nAttempt 0
  while { ([clock_seconds]-$iStart) < $nSecond } {

    # Each transaction does 3 operations. Each operation is either a read
    # or write of a randomly selected table (t1, t2 or t3). Set the variables
    # $SQL(1), $SQL(2) and $SQL(3) to the SQL commands used to implement
    # each operation.
    #
................................................................................
            DROP INDEX IF EXISTS yyy.xxx_i;
      }
      ]]
    }

    # Execute the SQL transaction.
    #
    incr nAttempt
    set rc [catch { execsql_blocking $::DB "
        BEGIN;
          $SQL(1);
          $SQL(2);
          $SQL(3);
        COMMIT;
      "
................................................................................
      # Hit some other kind of error. This is a malfunction.
      error $msg
    } else {
      # No error occurred. Check that any SELECT statements in the transaction
      # returned "1". Otherwise, the invariant was false, indicating that
      # some malfunction has occurred.
      foreach r $msg { if {$r != 1} { puts "Invariant check failed: $msg" } }
      incr nOp
    }
  }

  # Close the database connection and return 0.
  #
  sqlite3_close $::DB
  list $nOp $nAttempt
}

foreach {iTest xStep xPrepare} {
  1 sqlite3_blocking_step sqlite3_blocking_prepare_v2
  2 sqlite3_step          sqlite3_nonblocking_prepare_v2
} {
  forcedelete test.db test2.db test3.db
................................................................................
  unset -nocomplain finished
  for {set ii 0} {$ii < $nThread} {incr ii} {
    thread_spawn finished($ii) $ThreadSetup $ThreadProgram
  }
  for {set ii 0} {$ii < $nThread} {incr ii} {
    do_test notify2-$iTest.2.$ii {
      if {![info exists finished($ii)]} { vwait finished($ii) }
      incr anSuccess($xStep) [lindex $finished($ii) 0]
      incr anAttempt($xStep) [lindex $finished($ii) 1]
      expr 0
    } {0}
  }

  # Count the total number of succesful writes.
  do_test notify2-$iTest.3.1 {
    sqlite3 db test.db
    execsql {
................................................................................
           + (SELECT max(a) FROM t3)
    }]
    db close
  } {}
}

# The following tests checks to make sure sqlite3_blocking_step() is
# faster than sqlite3_step(). "Faster" in this case means uses fewer
# CPU cycles. This is not always the same as faster in wall-clock time 
# for this type of test. The number of CPU cycles per transaction is 
# roughly proportional to the number of attempts made (i.e. one plus the 
# number of SQLITE_BUSY or SQLITE_LOCKED errors that require the transaction 
# to be retried). So this test just measures that a greater percentage of
# transactions attempted using blocking_step() succeed.
#
# The blocking_step() function is almost always faster on multi-core and is
# usually faster on single-core.  But sometimes, by chance, step() will be
# faster on a single core, in which case the
# following test will fail.
#
puts "The following test seeks to demonstrate that the sqlite3_unlock_notify()"
puts "interface helps multi-core systems to run more efficiently.  This test"
puts "sometimes fails on single-core machines."
puts [array get anWrite]
do_test notify2-3 {
  set blocking [expr {
    double($anSuccess(sqlite3_blocking_step)) /
    double($anAttempt(sqlite3_blocking_step)) 
  }]
  set non [expr {
    double($anSuccess(sqlite3_step)) /
    double($anAttempt(sqlite3_step)) 
  }]
  puts -nonewline [format " blocking: %.1f%% non-blocking %.1f%% ..." \
    [expr $blocking*100.0] [expr $non*100.0]]

  expr {$blocking > $non}
} {1}

sqlite3_enable_shared_cache $::enable_shared_cache
finish_test

Changes to test/percentile.test.

196
197
198
199
200
201
202
203
204
205
206
207
208
209
      0          0.0
    100    9999990.0
     50    2749999.5
     10      99999.9
  } {
    do_test percentile-2.1.$in {
      execsql {
        SELECT percentile(x, $in) from t3;
      }
    } $out
  }
}

finish_test







|






196
197
198
199
200
201
202
203
204
205
206
207
208
209
      0          0.0
    100    9999990.0
     50    2749999.5
     10      99999.9
  } {
    do_test percentile-2.1.$in {
      execsql {
        SELECT round(percentile(x, $in),1) from t3;
      }
    } $out
  }
}

finish_test

Changes to test/permutations.test.

114
115
116
117
118
119
120





121
122
123
124
125
126
127
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
  walthread.test rtree3.test indexfault.test securedel2.test
  sort3.test sort4.test fts4growth.test fts4growth2.test
  bigsort.test
}]
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
  set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
}






#############################################################################
# Start of tests
#

#-------------------------------------------------------------------------
# Define the generic test suites:
................................................................................
  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 {
................................................................................

  # Exclude stmt.test, which expects sub-journals to use temporary files.
  stmt.test

  zerodamage.test

  # WAL mode is different.
  wal* tkt-2d1a5c67d.test backcompat.test
}]

ifcapable mem3 {
  test_suite "memsys3" -description {
    Run tests using the allocator in mem3.c.
  } -files [test_set $::allquicktests -exclude {
    autovacuum.test           delete3.test              manydb.test







>
>
>
>
>







 







|







 







|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
...
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  walthread.test rtree3.test indexfault.test securedel2.test
  sort3.test sort4.test fts4growth.test fts4growth2.test
  bigsort.test
}]
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
  set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
}
if {[info exists ::env(QUICKTEST_OMIT)]} {
  foreach x [split $::env(QUICKTEST_OMIT) ,] {
    regsub -all \\y$x\\y $allquicktests {} allquicktests
  }
}

#############################################################################
# Start of tests
#

#-------------------------------------------------------------------------
# Define the generic test suites:
................................................................................
  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 enabled.
} -presql {
  pragma mmap_size = 268435456;
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* -include malloc.test
]

test_suite "valgrind" -prefix "" -description {
................................................................................

  # Exclude stmt.test, which expects sub-journals to use temporary files.
  stmt.test

  zerodamage.test

  # WAL mode is different.
  wal* tkt-2d1a5c67d.test backcompat.test e_wal*
}]

ifcapable mem3 {
  test_suite "memsys3" -description {
    Run tests using the allocator in mem3.c.
  } -files [test_set $::allquicktests -exclude {
    autovacuum.test           delete3.test              manydb.test

Added test/pragma3.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
# 2014-12-19
#
# 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.
#
# This file implements tests for PRAGMA data_version command.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_execsql_test pragma3-100 {
  PRAGMA data_version;
} {1}
do_execsql_test pragma3-101 {
  PRAGMA temp.data_version;
} {1}

# Writing to the pragma is a no-op 
do_execsql_test pragma3-102 {
  PRAGMA main.data_version=1234;
  PRAGMA main.data_version;
} {1 1}

# EVIDENCE-OF: R-27726-60934 The "PRAGMA data_version" command provides
# an indication that the database file has been modified.
#
# EVIDENCE-OF: R-47505-58569 The "PRAGMA data_version" value is
# unchanged for commits made on the same database connection.
#
do_execsql_test pragma3-110 {
  PRAGMA data_version;
  BEGIN IMMEDIATE;
  PRAGMA data_version;
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(100),(200),(300);
  PRAGMA data_version;
  COMMIT;
  SELECT * FROM t1;
  PRAGMA data_version;
} {1 1 1 100 200 300 1}

sqlite3 db2 test.db
do_test pragma3-120 {
  db2 eval {
    SELECT * FROM t1;
    PRAGMA data_version;
  }
} {100 200 300 1}

do_execsql_test pragma3-130 {
  PRAGMA data_version;
  BEGIN IMMEDIATE;
  PRAGMA data_version;
  INSERT INTO t1 VALUES(400),(500);
  PRAGMA data_version;
  COMMIT;
  SELECT * FROM t1;
  PRAGMA data_version;
  PRAGMA shrink_memory;
} {1 1 1 100 200 300 400 500 1}

# EVIDENCE-OF: R-63005-41812 The integer values returned by two
# invocations of "PRAGMA data_version" from the same connection will be
# different if changes were committed to the database by any other
# connection in the interim.
#
# Value went from 1 in pragma3-120 to 2 here.
#
do_test pragma3-140 {
  db2 eval {
    SELECT * FROM t1;
    PRAGMA data_version;
    BEGIN IMMEDIATE;
    PRAGMA data_version;
    UPDATE t1 SET a=a+1;
    COMMIT;
    SELECT * FROM t1;
    PRAGMA data_version;
  }
} {100 200 300 400 500 2 2 101 201 301 401 501 2}
do_execsql_test pragma3-150 {
  SELECT * FROM t1;
  PRAGMA data_version;
} {101 201 301 401 501 2}

#
do_test pragma3-160 {
  db eval {
    BEGIN;
    PRAGMA data_version;
    UPDATE t1 SET a=555 WHERE a=501;
    PRAGMA data_version;
    SELECT * FROM t1 ORDER BY a;
    PRAGMA data_version;
  }
} {2 2 101 201 301 401 555 2}
do_test pragma3-170 {
  db2 eval {
    PRAGMA data_version;
  }
} {2}
do_test pragma3-180 {
  db eval {
    COMMIT;
    PRAGMA data_version;
  }
} {2}
do_test pragma3-190 {
  db2 eval {
    PRAGMA data_version;
  }
} {3}

# EVIDENCE-OF: R-19326-44825 The "PRAGMA data_version" value is a local
# property of each database connection and so values returned by two
# concurrent invocations of "PRAGMA data_version" on separate database
# connections are often different even though the underlying database is
# identical.
#
do_test pragma3-195 {
  expr {[db eval {PRAGMA data_version}]!=[db2 eval {PRAGMA data_version}]}
} {1}

# EVIDENCE-OF: R-54562-06892 The behavior of "PRAGMA data_version" is
# the same for all database connections, including database connections
# in separate processes and shared cache database connections.
#
# The next block checks the behavior for separate processes.
#
do_test pragma3-200 {
  db eval {PRAGMA data_version; SELECT * FROM t1;}
} {2 101 201 301 401 555}
do_test pragma3-201 {
  set fd [open pragma3.txt wb]
  puts $fd {
     sqlite3 db test.db;
     db eval {DELETE FROM t1 WHERE a>300};
     db close;
     exit;
  }
  close $fd
  exec [info nameofexec] pragma3.txt
  forcedelete pragma3.txt
  db eval {
    PRAGMA data_version;
    SELECT * FROM t1;
  }
} {3 101 201}
db2 close
db close

# EVIDENCE-OF: R-54562-06892 The behavior of "PRAGMA data_version" is
# the same for all database connections, including database connections
# in separate processes and shared cache database connections.
#
# The next block checks that behavior is the same for shared-cache.
#
ifcapable shared_cache {
  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
  sqlite3 db test.db
  sqlite3 db2 test.db
  do_test pragma3-300 {
    db eval {
      PRAGMA data_version;
      BEGIN;
      CREATE TABLE t3(a,b,c);
      CREATE TABLE t4(x,y,z);
      INSERT INTO t4 VALUES(123,456,789);
      PRAGMA data_version;
      COMMIT;
      PRAGMA data_version;
    }
  } {1 1 1}
  do_test pragma3-310 {
    db2 eval {
      PRAGMA data_version;
      BEGIN;
      INSERT INTO t3(a,b,c) VALUES('abc','def','ghi');
      SELECT * FROM t3;
      PRAGMA data_version;
    }
  } {2 abc def ghi 2}
  # The transaction in db2 has not yet committed, so the data_version in
  # db is unchanged.
  do_test pragma3-320 {
    db eval {
      PRAGMA data_version;
      SELECT * FROM t4;
    }
  } {1 123 456 789}
  do_test pragma3-330 {
    db2 eval {
      COMMIT;
      PRAGMA data_version;
      SELECT * FROM t4;
    }
  } {2 123 456 789}
  do_test pragma3-340 {
    db eval {
      PRAGMA data_version;
      SELECT * FROM t3;
      SELECT * FROM t4;
    }
  } {2 abc def ghi 123 456 789}
  db2 close
  db close
  sqlite3_enable_shared_cache $::enable_shared_cache
}

# Make sure this also works in WAL mode
#
# This will not work with the in-memory journal permutation, as opening
# [db2] switches the journal mode back to "memory"
#
ifcapable wal {
if {[permutation]!="inmemory_journal"} {

  sqlite3 db test.db
  db eval {PRAGMA journal_mode=WAL}
  sqlite3 db2 test.db
  do_test pragma3-400 {
    db eval {
      PRAGMA data_version;
      PRAGMA journal_mode;
      SELECT * FROM t1;
    }
  } {2 wal 101 201}
  do_test pragma3-410 {
    db2 eval {
      PRAGMA data_version;
      PRAGMA journal_mode;
      SELECT * FROM t1;
    }
  } {2 wal 101 201}
  do_test pragma3-420 {
    db eval {UPDATE t1 SET a=111*(a/100); PRAGMA data_version; SELECT * FROM t1}
  } {2 111 222}
  do_test pragma3-430 {
    db2 eval {PRAGMA data_version; SELECT * FROM t1;}
  } {3 111 222}
  db2 close
}
}

finish_test

Deleted test/releasetest.mk.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
########################################################
TOP=/home/drh/sqlite/sqlite

TCL_FLAGS=-I/home/drh/tcltk/86linux
LIBTCL=/home/drh/tcltk/86linux/libtcl8.6.a -lm -ldl -lpthread

BCC = gcc
TCC = gcc -ansi -g $(CFLAGS)
NAWK   = awk
AR     = ar cr
RANLIB = ranlib
THREADLIB = -lpthread -ldl -lz
include $(TOP)/main.mk
########################################################
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























Changes to test/releasetest.tcl.


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
..
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
...
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
...
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
...
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
...
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
...
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


set rcsid {$Id: $}

# Documentation for this script. This may be output to stderr
# if the script is invoked incorrectly. See the [process_options]
# proc below.
#
set ::USAGE_MESSAGE {
This Tcl script is used to test the various configurations required
before releasing a new version. Supported command line options (all 
optional) are:

    -makefile PATH-TO-MAKEFILE           (default "releasetest.mk")
    -platform PLATFORM                   (see below)
    -quick    BOOLEAN                    (default "0")
    -config   CONFIGNAME                 (Run only CONFIGNAME)





The default value for -makefile is "./releasetest.mk".


The script determines the default value for -platform using the
$tcl_platform(os) and $tcl_platform(machine) variables. Supported 
platforms are "Linux-x86", "Linux-x86_64" and "Darwin-i386".

If the -quick option is set to true, then the "veryquick.test" script
is run for all compilation configurations. Otherwise, sometimes "all.test"
is run, sometimes "veryquick.test".

Almost any SQLite makefile (except those generated by configure - see below)
should work. The following properties are required:

  * The makefile should support the "fulltest" target.
  * The makefile should support the variable "OPTS" as a way to pass
    options from the make command line to lemon and the C compiler.

More precisely, the following invocation must be supported:

  make -f $::MAKEFILE fulltest OPTS="-DSQLITE_SECURE_DELETE=1 -DSQLITE_DEBUG=1"

Makefiles generated by the sqlite configure program cannot be used as
they do not respect the OPTS variable.

Example Makefile contents:

  ########################################################
  TOP=/home/dan/work/sqlite/sqlite

  TCL_FLAGS=-I/home/dan/tcl/include
  LIBTCL=-L/home/dan/tcl/lib -ltcl

  BCC = gcc
  TCC = gcc -ansi -g $(CFLAGS)
  NAWK   = awk
  AR     = ar cr
  RANLIB = ranlib
  THREADLIB = -lpthread -ldl
  include $(TOP)/main.mk
  ########################################################
}

array set ::Configs {
  "Default" {
    -O2
  }
  "Ftrapv" {
    -O2 -ftrapv
    -DSQLITE_MAX_ATTACHED=55
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }




  "Unlock-Notify" {
    -O2
    -DSQLITE_ENABLE_UNLOCK_NOTIFY
    -DSQLITE_THREADSAFE
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "Secure-Delete" {
................................................................................
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_SECURE_DELETE=1
    -DSQLITE_SOUNDEX=1
    -DSQLITE_ENABLE_ATOMIC_WRITE=1
    -DSQLITE_ENABLE_IOTRACE=1
    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1

  }
  "Debug-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_MEMDEBUG=1
    -DSQLITE_MUTEX_NOOP=1
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1

  }
  "Device-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=64
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
................................................................................
    -DSQLITE_THREADSAFE=2
  }
  "Locking-Style" {
    -O2
    -DSQLITE_ENABLE_LOCKING_STYLE=1
  }
  "OS-X" {

    -DSQLITE_OMIT_LOAD_EXTENSION=1
    -DSQLITE_DEFAULT_MEMSTATUS=0
    -DSQLITE_THREADSAFE=2
    -DSQLITE_OS_UNIX=1
    -DSQLITE_ENABLE_LOCKING_STYLE=1
    -DUSE_PREAD=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
    -DSQLITE_DEFAULT_CACHE_SIZE=1000
    -DSQLITE_MAX_LENGTH=2147483645
    -DSQLITE_MAX_VARIABLE_NUMBER=500000
    -DSQLITE_DEBUG=1 
    -DSQLITE_PREFER_PROXY_LOCKING=1

  }
  "Extra-Robustness" {
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_MAX_ATTACHED=62
  }
  "Devkit" {
    -DSQLITE_DEFAULT_FILE_FORMAT=4
................................................................................
    -DHAVE_USLEEP=1
  }
}

array set ::Platforms {
  Linux-x86_64 {
    "Check-Symbols"           checksymbols
    "Debug-One"               test
    "Secure-Delete"           test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Update-Delete-Limit"     test
    "Extra-Robustness"        test
    "Device-Two"              test
    "Ftrapv"                  test

    "No-lookaside"            test
    "Devkit"                  test
    "Default"                 "threadtest fulltest"
    "Device-One"              fulltest
  }
  Linux-i686 {
    "Devkit"                  test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Device-One"              test
    "Device-Two"              test
    "Default"                 "threadtest fulltest"
  }
  Darwin-i386 {
    "Locking-Style"           test
    "OS-X"                    "threadtest fulltest"
  }







}


# End of configuration section.
#########################################################################
#########################################################################

................................................................................
  foreach {v t} $value {
    if {0==[info exists ::Configs($v)]} {
      puts stderr "No such configuration: \"$v\""
      exit -1
    }
  }
}

proc run_test_suite {name testtarget config} {


  



































  # Tcl variable $opts is used to build up the value used to set the 
  # OPTS Makefile variable. Variable $cflags holds the value for
  # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
  # CFLAGS is only passed to gcc.
  #
  set cflags ""
  set opts ""

  foreach arg $config {
    if {[string match -D* $arg]} {
      lappend opts $arg


    } else {
      lappend cflags $arg
    }
  }

  set cflags [join $cflags " "]
  set opts   [join $opts " "]
................................................................................

  if {$::tcl_platform(platform)=="windows"} {
    append opts " -DSQLITE_OS_WIN=1"
  } else {
    append opts " -DSQLITE_OS_UNIX=1"
  }

  # Run the test.
  #
  set makefile [file normalize $::MAKEFILE]
  file mkdir $dir



  puts -nonewline "Testing configuration \"$name\" (logfile=$dir/test.log)..."
  flush stdout

  set makecmd [concat                                  \
    [list exec make -C $dir -f $makefile clean]        \
    $testtarget                                        \
    [list CFLAGS=$cflags OPTS=$opts >& $dir/test.log]  \
  ]

  set tm1 [clock seconds] 



  set rc [catch $makecmd]




  set tm2 [clock seconds]



  set minutes [expr {($tm2-$tm1)/60}]

  set seconds [expr {($tm2-$tm1)%60}]
  puts -nonewline [format " (%d:%.2d) " $minutes $seconds]

  if {$rc} {
    puts "FAILED."


  } else {

































    puts "Ok."


  }
}


# This proc processes the command line options passed to this script.
# Currently the only option supported is "-makefile", default
# "releasetest.mk". Set the ::MAKEFILE variable to the value of this
# option.
#
proc process_options {argv} {
  set ::MAKEFILE releasetest.mk                       ;# Default value
  set ::QUICK    0                                    ;# Default value



  set config {}
  set platform $::tcl_platform(os)-$::tcl_platform(machine)

  for {set i 0} {$i < [llength $argv]} {incr i} {
    switch -- [lindex $argv $i] {
      -makefile {


        incr i
        set ::MAKEFILE [lindex $argv $i]

      }

      -platform {
        incr i
        set platform [lindex $argv $i]
      }

      -quick {
        incr i
        set ::QUICK [lindex $argv $i]
      }

      -config {
        incr i
        set config [lindex $argv $i]
      }
  



























      default {
        puts stderr ""
        puts stderr [string trim $::USAGE_MESSAGE]
        exit -1
      }
    }
  }

  set ::MAKEFILE [file normalize $::MAKEFILE]

  if {0==[info exists ::Platforms($platform)]} {
    puts "Unknown platform: $platform"
    puts -nonewline "Set the -platform option to "
    set print [list]
    foreach p [array names ::Platforms] {
      lappend print "\"$p\""
    }
................................................................................

  if {$config!=""} {
    if {[llength $config]==1} {lappend config fulltest}
    set ::CONFIGLIST $config
  } else {
    set ::CONFIGLIST $::Platforms($platform)
  }
  puts "Running the following configurations for $platform:"
  puts "    [string trim $::CONFIGLIST]"





}

# Main routine.
#
proc main {argv} {

  # Process any command line options.
  process_options $argv







  foreach {zConfig target} $::CONFIGLIST {
    if {$::QUICK} {set target test}

    set config_options $::Configs($zConfig)


    run_test_suite $zConfig $target $config_options

    # If the configuration included the SQLITE_DEBUG option, then remove
    # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
    # add it and run veryquick.test.
    if {$target!="checksymbols"} {
      set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]


      if {$debug_idx < 0} {


        run_test_suite "${zConfig}_debug" test [
          concat $config_options -DSQLITE_DEBUG=1
        ]
      } else {



        run_test_suite "${zConfig}_ndebug" test [
          lreplace $config_options $debug_idx $debug_idx
        ]
      }
    }

  }







}

main $argv
>
|
<
<






|


|
|
<
|
>
>
>
>

|
>

|
|


<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








|


>
>
>
>







 







<


>












>







 







>












|

>







 







|






>













|


>
>
>
>
>
>
>







 








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




|

>



>
>







 







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

>

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










|
|
>
>
>




|
|
>
>

<
>








<
|






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








<
<







 







|

>
>
>
>
>








>

>
>
>
>
>


>


>





|

>
>

>
>
|
<
<

>
>
>
|
<
<


|
|
>
>
>
>
>
>
>



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
..
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
...
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
...
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
...
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
...
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
...
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
#!/usr/bin/tclsh
#


# Documentation for this script. This may be output to stderr
# if the script is invoked incorrectly. See the [process_options]
# proc below.
#
set ::USAGE_MESSAGE {
This Tcl script is used to test the various configurations required
before releasing a new version. Supported command line options (all
optional) are:

    --srcdir   TOP-OF-SQLITE-TREE      (see below)
    --platform PLATFORM                (see below)

    --config   CONFIGNAME              (Run only CONFIGNAME)
    --quick                            (Run "veryquick.test" only)
    --buildonly                        (Just build testfixture - do not run)
    --dryrun                           (Print what would have happened)
    --info                             (Show diagnostic info)

The default value for --srcdir is the parent of the directory holding
this script.

The script determines the default value for --platform using the
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
platforms are "Linux-x86", "Linux-x86_64" and "Darwin-i386".





Every test begins with a fresh run of the configure script at the top
of the SQLite source tree.




























}

array set ::Configs {
  "Default" {
    -O2
  }
  "Ftrapv" {
    -O2 -ftrapv
    -DSQLITE_MAX_ATTACHED=125
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "Sanitize" {
    CC=clang -fsanitize=undefined
    -DSQLITE_ENABLE_STAT4
  }
  "Unlock-Notify" {
    -O2
    -DSQLITE_ENABLE_UNLOCK_NOTIFY
    -DSQLITE_THREADSAFE
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "Secure-Delete" {
................................................................................
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_SECURE_DELETE=1
    -DSQLITE_SOUNDEX=1
    -DSQLITE_ENABLE_ATOMIC_WRITE=1

    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_ENABLE_STAT4
  }
  "Debug-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_MEMDEBUG=1
    -DSQLITE_MUTEX_NOOP=1
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_STAT4
  }
  "Device-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=64
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
................................................................................
    -DSQLITE_THREADSAFE=2
  }
  "Locking-Style" {
    -O2
    -DSQLITE_ENABLE_LOCKING_STYLE=1
  }
  "OS-X" {
    -O1   # Avoid a compiler bug in gcc 4.2.1 build 5658
    -DSQLITE_OMIT_LOAD_EXTENSION=1
    -DSQLITE_DEFAULT_MEMSTATUS=0
    -DSQLITE_THREADSAFE=2
    -DSQLITE_OS_UNIX=1
    -DSQLITE_ENABLE_LOCKING_STYLE=1
    -DUSE_PREAD=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
    -DSQLITE_DEFAULT_CACHE_SIZE=1000
    -DSQLITE_MAX_LENGTH=2147483645
    -DSQLITE_MAX_VARIABLE_NUMBER=500000
    -DSQLITE_DEBUG=1
    -DSQLITE_PREFER_PROXY_LOCKING=1
    -DSQLITE_ENABLE_API_ARMOR=1
  }
  "Extra-Robustness" {
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_MAX_ATTACHED=62
  }
  "Devkit" {
    -DSQLITE_DEFAULT_FILE_FORMAT=4
................................................................................
    -DHAVE_USLEEP=1
  }
}

array set ::Platforms {
  Linux-x86_64 {
    "Check-Symbols"           checksymbols
    "Debug-One"               "mptest test"
    "Secure-Delete"           test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Update-Delete-Limit"     test
    "Extra-Robustness"        test
    "Device-Two"              test
    "Ftrapv"                  test
    "Sanitize"                {QUICKTEST_OMIT=func4.test,nan.test test}
    "No-lookaside"            test
    "Devkit"                  test
    "Default"                 "threadtest fulltest"
    "Device-One"              fulltest
  }
  Linux-i686 {
    "Devkit"                  test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Device-One"              test
    "Device-Two"              test
    "Default"                 "threadtest fulltest"
  }
  Darwin-i386 {
    "Locking-Style"           "mptest test"
    "OS-X"                    "threadtest fulltest"
  }
  Darwin-x86_64 {
    "Locking-Style"           "mptest test"
    "OS-X"                    "threadtest fulltest"
  }
  "Windows NT-intel" {
    "Default"                 "mptest fulltestonly"
  }
}


# End of configuration section.
#########################################################################
#########################################################################

................................................................................
  foreach {v t} $value {
    if {0==[info exists ::Configs($v)]} {
      puts stderr "No such configuration: \"$v\""
      exit -1
    }
  }
}

# Open the file $logfile and look for a report on the number of errors
# and the number of test cases run.  Add these values to the global
# $::NERRCASE and $::NTESTCASE variables.
#
# If any errors occur, then write into $errmsgVar the text of an appropriate
# one-line error message to show on the output.
#
proc count_tests_and_errors {logfile rcVar errmsgVar} {
  if {$::DRYRUN} return
  upvar 1 $rcVar rc $errmsgVar errmsg
  set fd [open $logfile rb]
  set seen 0
  while {![eof $fd]} {
    set line [gets $fd]
    if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
      incr ::NERRCASE $nerr
      incr ::NTESTCASE $ntest
      set seen 1
      if {$nerr>0} {
        set rc 1
        set errmsg $line
      }
    }
    if {[regexp {runtime error: +(.*)} $line all msg]} {
      incr ::NERRCASE
      if {$rc==0} {
        set rc 1
        set errmsg $msg
      }
    }
  }
  close $fd
  if {!$seen} {
    set rc 1
    set errmsg "Test did not complete"
  }
}

proc run_test_suite {name testtarget config} {
  # Tcl variable $opts is used to build up the value used to set the
  # OPTS Makefile variable. Variable $cflags holds the value for
  # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
  # CFLAGS is only passed to gcc.
  #
  set cflags "-g"
  set opts ""
  regsub -all {#[^\n]*\n} $config \n config
  foreach arg $config {
    if {[string match -D* $arg]} {
      lappend opts $arg
    } elseif {[string match CC=* $arg]} {
      lappend testtarget $arg
    } else {
      lappend cflags $arg
    }
  }

  set cflags [join $cflags " "]
  set opts   [join $opts " "]
................................................................................

  if {$::tcl_platform(platform)=="windows"} {
    append opts " -DSQLITE_OS_WIN=1"
  } else {
    append opts " -DSQLITE_OS_UNIX=1"
  }




  dryrun file mkdir $dir
  if {!$::DRYRUN} {
    set title ${name}($testtarget)
    set n [string length $title]
    puts -nonewline "${title}[string repeat . [expr {63-$n}]]"
    flush stdout
  }






  set tm1 [clock seconds]
  set origdir [pwd]
  dryrun cd $dir
  set errmsg {}
  set rc [catch [configureCommand]]
  if {!$rc} {
    set rc [catch [makeCommand $testtarget $cflags $opts]]
    count_tests_and_errors test.log rc errmsg
  }
  set tm2 [clock seconds]
  dryrun cd $origdir

  if {!$::DRYRUN} {
    set hours [expr {($tm2-$tm1)/3600}]
    set minutes [expr {(($tm2-$tm1)/60)%60}]
    set seconds [expr {($tm2-$tm1)%60}]

    set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
    if {$rc} {
      puts " FAIL $tm"
      incr ::NERR
      if {$errmsg!=""} {puts "     $errmsg"}
    } else {
      puts " Ok   $tm"
    }
  }
}

# The following procedure returns the "configure" command to be exectued for
# the current platform, which may be Windows (via MinGW, etc).
#
proc configureCommand {} {
  set result [list dryrun exec]
  if {$::tcl_platform(platform)=="windows"} {
    lappend result sh
  }
  lappend result $::SRCDIR/configure -enable-load-extension >& test.log
}

# The following procedure returns the "make" command to be executed for the
# specified targets, compiler flags, and options.
#
proc makeCommand { targets cflags opts } {
  set result [list dryrun exec make clean]
  foreach target $targets {
    lappend result $target
  }
  lappend result CFLAGS=$cflags OPTS=$opts >>& test.log
}

# The following procedure either prints its arguments (if ::DRYRUN is true)
# or executes the command of its arguments in the calling context
# (if ::DRYRUN is false).
#
proc dryrun {args} {
  if {$::DRYRUN} {
    puts $args
  } else {
    uplevel 1 $args
  }
}


# This proc processes the command line options passed to this script.
# Currently the only option supported is "-makefile", default
# "releasetest.mk". Set the ::MAKEFILE variable to the value of this
# option.
#
proc process_options {argv} {
  set ::SRCDIR    [file normalize [file dirname [file dirname $::argv0]]]
  set ::QUICK     0
  set ::BUILDONLY 0
  set ::DRYRUN    0
  set ::EXEC      exec
  set config {}
  set platform $::tcl_platform(os)-$::tcl_platform(machine)

  for {set i 0} {$i < [llength $argv]} {incr i} {
    set x [lindex $argv $i]
    if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
    switch -- $x {
      -srcdir {
        incr i

        set ::SRCDIR [file normalize [lindex $argv $i]]
      }

      -platform {
        incr i
        set platform [lindex $argv $i]
      }

      -quick {

        set ::QUICK 1
      }

      -config {
        incr i
        set config [lindex $argv $i]
      }

      -buildonly {
        set ::BUILDONLY 1
      }

      -dryrun {
        set ::DRYRUN 1
      }

      -info {
        puts "Command-line Options:"
        puts "   --srcdir $::SRCDIR"
        puts "   --platform [list $platform]"
        puts "   --config [list $config]"
        if {$::QUICK}     {puts "   --quick"}
        if {$::BUILDONLY} {puts "   --buildonly"}
        if {$::DRYRUN}    {puts "   --dryrun"}
        puts "\nAvailable --platform options:"
        foreach y [lsort [array names ::Platforms]] {
          puts "   [list $y]"
        }
        puts "\nAvailable --config options:"
        foreach y [lsort [array names ::Configs]] {
          puts "   [list $y]"
        }
        exit
      }

      default {
        puts stderr ""
        puts stderr [string trim $::USAGE_MESSAGE]
        exit -1
      }
    }
  }



  if {0==[info exists ::Platforms($platform)]} {
    puts "Unknown platform: $platform"
    puts -nonewline "Set the -platform option to "
    set print [list]
    foreach p [array names ::Platforms] {
      lappend print "\"$p\""
    }
................................................................................

  if {$config!=""} {
    if {[llength $config]==1} {lappend config fulltest}
    set ::CONFIGLIST $config
  } else {
    set ::CONFIGLIST $::Platforms($platform)
  }
  puts "Running the following test configurations for $platform:"
  puts "    [string trim $::CONFIGLIST]"
  puts -nonewline "Flags:"
  if {$::DRYRUN} {puts -nonewline " --dryrun"}
  if {$::BUILDONLY} {puts -nonewline " --buildonly"}
  if {$::QUICK} {puts -nonewline " --quick"}
  puts ""
}

# Main routine.
#
proc main {argv} {

  # Process any command line options.
  process_options $argv
  puts [string repeat * 79]

  set ::NERR 0
  set ::NTEST 0
  set ::NTESTCASE 0
  set ::NERRCASE 0
  set STARTTIME [clock seconds]
  foreach {zConfig target} $::CONFIGLIST {
    if {$::QUICK} {set target test}
    if {$::BUILDONLY} {set target testfixture}
    set config_options $::Configs($zConfig)

    incr NTEST
    run_test_suite $zConfig $target $config_options

    # If the configuration included the SQLITE_DEBUG option, then remove
    # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
    # add it and run veryquick.test.
    if {$target!="checksymbols" && !$::BUILDONLY} {
      set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
      set xtarget $target
      regsub -all {fulltest[a-z]*} $xtarget test xtarget
      if {$debug_idx < 0} {
        incr NTEST
        append config_options " -DSQLITE_DEBUG=1"
        run_test_suite "${zConfig}_debug" $xtarget $config_options


      } else {
        incr NTEST
        regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options
        regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options
        run_test_suite "${zConfig}_ndebug" $xtarget $config_options


      }
    }
  }

  set elapsetime [expr {[clock seconds]-$STARTTIME}]
  set hr [expr {$elapsetime/3600}]
  set min [expr {($elapsetime/60)%60}]
  set sec [expr {$elapsetime%60}]
  set etime [format (%02d:%02d:%02d) $hr $min $sec]
  puts [string repeat * 79]
  puts "$::NERRCASE failures of $::NTESTCASE tests run in $etime"
}

main $argv

Changes to test/sort.test.

12
13
14
15
16
17
18





19
20
21
22
23
24
25
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sorter (code in vdbesort.c).
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort






# Create a bunch of data to sort against
#
do_test sort-1.0 {
  execsql {
    CREATE TABLE t1(
       n int,







>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sorter (code in vdbesort.c).
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db

# Create a bunch of data to sort against
#
do_test sort-1.0 {
  execsql {
    CREATE TABLE t1(
       n int,

Changes to test/sort2.test.

13
14
15
16
17
18
19





20
21
22
23
24
25
26
# Specifically, the tests in this file attempt to verify that 
# multi-threaded sorting works.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort2






foreach {tn script} {
  1 { }
  2 {
    catch { db close }
    reset_db
    catch { db eval {PRAGMA threads=7} }







>
>
>
>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Specifically, the tests in this file attempt to verify that 
# multi-threaded sorting works.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort2
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db

foreach {tn script} {
  1 { }
  2 {
    catch { db close }
    reset_db
    catch { db eval {PRAGMA threads=7} }

Changes to test/sort4.test.

13
14
15
16
17
18
19






20
21
22
23
24
25
26
# The tests in this file are brute force tests of the multi-threaded
# sorter.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort4







# Configure the sorter to use 3 background threads.
db eval {PRAGMA threads=3}

# Minimum number of seconds to run for. If the value is 0, each test
# is run exactly once. Otherwise, tests are repeated until the timeout
# expires.







>
>
>
>
>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# The tests in this file are brute force tests of the multi-threaded
# sorter.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort4
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db


# Configure the sorter to use 3 background threads.
db eval {PRAGMA threads=3}

# Minimum number of seconds to run for. If the value is 0, each test
# is run exactly once. Otherwise, tests are repeated until the timeout
# expires.

Changes to test/sortfault.test.

13
14
15
16
17
18
19






20
21
22
23
24
25
26
# Specifically, it tests the effects of fault injection on the sorter
# module (code in vdbesort.c).
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sortfault







do_execsql_test 1.0 {
  PRAGMA cache_size = 5;
}

foreach {tn mmap_limit nWorker tmpstore threadsmode fakeheap lookaside} {
          1          0       0     file multithread    false     false







>
>
>
>
>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Specifically, it tests the effects of fault injection on the sorter
# module (code in vdbesort.c).
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sortfault
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db


do_execsql_test 1.0 {
  PRAGMA cache_size = 5;
}

foreach {tn mmap_limit nWorker tmpstore threadsmode fakeheap lookaside} {
          1          0       0     file multithread    false     false

Changes to test/threadtest3.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
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
...
443
444
445
446
447
448
449




450
451

452
453
454
455
456
457
458
...
781
782
783
784
785
786
787

788
789
790
791
792
793
794
...
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
...
980
981
982
983
984
985
986

987
988
989
990
991
992
993
....
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

/*











** The code in this file runs a few multi-threaded test cases using the
** SQLite library. It can be compiled to an executable on unix using the
** following command:
**
**   gcc -O2 threadtest3.c sqlite3.c -ldl -lpthread -lm
**
** Then run the compiled program. The exit status is non-zero if any tests
** failed (hopefully there is also some output to stdout to clarify what went
** wrong).
**
** There are three parts to the code in this file, in the following order:


**
**   1. Code for the SQL aggregate function md5sum() copied from 
**      tclsqlite.c in the SQLite distribution. The names of all the 
**      types and functions in this section begin with "MD5" or "md5".
**
**   2. A set of utility functions that may be used to implement
**      multi-threaded test cases. These are all called by test code
**      via macros that help with error reporting. The macros are defined
**      immediately below this comment.
**
**   3. The test code itself. And a main() routine to drive the test 
**      code.

*/

/*************************************************************************
** Start of test code/infrastructure interface macros.
**
** The following macros constitute the interface between the test
** programs and the test infrastructure. Test infrastructure code 
** does not itself use any of these macros. Test code should not
** call any of the macroname_x() functions directly.
**
** See the header comments above the corresponding macroname_x()
** function for a description of each interface.


*/


/* Database functions */
#define opendb(w,x,y,z)         (SEL(w), opendb_x(w,x,y,z))
#define closedb(y,z)            (SEL(y), closedb_x(y,z))

/* Functions to execute SQL */
#define sql_script(x,y,z)       (SEL(x), sql_script_x(x,y,z))
................................................................................
  char zBuf[33];
  p = sqlite3_aggregate_context(context, sizeof(*p));
  MD5Final(digest,p);
  MD5DigestToBase16(digest, zBuf);
  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}

/*************************************************************************
** End of copied md5sum() code.
*/

typedef sqlite3_int64 i64;

typedef struct Error Error;
typedef struct Sqlite Sqlite;
typedef struct Statement Statement;

................................................................................
  sqlite3_free(p->zErr);
  p->zErr = 0;
  p->rc = 0;
}

static void print_err(Error *p){
  if( p->rc!=SQLITE_OK ){




    printf("Error: (%d) \"%s\" at line %d\n", p->rc, p->zErr, p->iLine);
    nGlobalErr++;

  }
}

static void print_and_free_err(Error *p){
  print_err(p);
  free_err(p);
}
................................................................................
    pNext = p->pNext;
    int rc;
    rc = pthread_join(p->tid, &ret);
    if( rc!=0 ){
      if( pErr->rc==SQLITE_OK ) system_error(pErr, rc);
    }else{
      printf("Thread %d says: %s\n", p->iTid, (ret==0 ? "..." : (char *)ret));

    }
    sqlite3_free(p);
  }
  pThreads->pThread = 0;
}

static i64 filesize_x(
................................................................................
    }else{
      ret = (t >= timelimit);
    }
  }
  return ret;
}

/* 
** The "Set Error Line" macro.
*/
#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))


/*************************************************************************
**************************************************************************
**************************************************************************
** End infrastructure. Begin tests.
*/

................................................................................
  sql_script(&err, &db,
      "PRAGMA journal_mode = WAL;"
      "CREATE TABLE t1(x PRIMARY KEY);"
      "INSERT INTO t1 VALUES(randomblob(100));"
      "INSERT INTO t1 VALUES(randomblob(100));"
      "INSERT INTO t1 SELECT md5sum(x) FROM t1;"
  );


  setstoptime(&err, nMs);
  for(i=0; i<WALTHREAD1_NTHREAD; i++){
    launch_thread(&err, &threads, walthread1_thread, 0);
  }
  launch_thread(&err, &threads, walthread1_ckpt_thread, 0);
  join_all_threads(&err, &threads);
................................................................................
#include "tt3_index.c"
#include "tt3_lookaside1.c"
#include "tt3_vacuum.c"
#include "tt3_stress.c"

int main(int argc, char **argv){
  struct ThreadTest {
    void (*xTest)(int);
    const char *zTest;
    int nMs;
  } aTest[] = {
    { walthread1, "walthread1", 20000 },
    { walthread2, "walthread2", 20000 },
    { walthread3, "walthread3", 20000 },
    { walthread4, "walthread4", 20000 },
    { walthread5, "walthread5",  1000 },
    { walthread5, "walthread5",  1000 },
    
    { cgt_pager_1,      "cgt_pager_1", 0 },
    { dynamic_triggers, "dynamic_triggers", 20000 },

    { checkpoint_starvation_1, "checkpoint_starvation_1", 10000 },
    { checkpoint_starvation_2, "checkpoint_starvation_2", 10000 },
................................................................................

    { create_drop_index_1, "create_drop_index_1", 10000 },
    { lookaside1,          "lookaside1", 10000 },
    { vacuum1,             "vacuum1", 10000 },
    { stress1,             "stress1", 10000 },
    { stress2,             "stress2", 60000 },
  };


  int i;
  int bTestfound = 0;

  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);



  for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
    char const *z = aTest[i].zTest;
    if( argc>1 ){
      int iArg;
      for(iArg=1; iArg<argc; iArg++){

        if( 0==sqlite3_strglob(argv[iArg], z) ) break;
      }
      if( iArg==argc ) continue;

    }





    printf("Running %s for %d seconds...\n", z, aTest[i].nMs/1000);

    aTest[i].xTest(aTest[i].nMs);
    bTestfound++;
  }


  if( bTestfound==0 ) goto usage;

  printf("Total of %d errors across all tests\n", nGlobalErr);

  return (nGlobalErr>0 ? 255 : 0);

 usage:
  printf("Usage: %s [testname|testprefix*]...\n", argv[0]);
  printf("Available tests are:\n");
  for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
    printf("   %s\n", aTest[i].zTest);
  }

  return 254;
}


<

>
>
>
>
>
>
>
>
>
>
>






|
|
|

|
>
>

<
<
|
|
|
|
<
<

<
<
>


<
<
<
<
<
<
<
<
<
<
>
>

>







 







|

|







 







>
>
>
>
|
|
>







 







>







 







<
<
<
<
<







 







>







 







|
|
|





<







 







<
>
|
|


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

<
>











<
<

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
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
...
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
...
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
...
900
901
902
903
904
905
906





907
908
909
910
911
912
913
...
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
....
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



/*
** 2010-07-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.
**
*************************************************************************
**
** The code in this file runs a few multi-threaded test cases using the
** SQLite library. It can be compiled to an executable on unix using the
** following command:
**
**   gcc -O2 threadtest3.c sqlite3.c -ldl -lpthread -lm
**
** Even though threadtest3.c is the only C source code file mentioned on
** the compiler command-line, #include macros are used to pull in additional
** C code files named "tt3_*.c".
**
** After compiling, run this program with an optional argument telling
** which test to run.  All tests are run if no argument is given.  The
** argument can be a glob pattern to match multiple tests.  Examples:
**


**        ./a.out                 -- Run all tests
**        ./a.out walthread3      -- Run the "walthread3" test
**        ./a.out 'wal*'          -- Run all of the wal* tests
**        ./a.out --help          -- List all available tests


**


** The exit status is non-zero if any test fails.
*/











/* 
** The "Set Error Line" macro.
*/
#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))

/* Database functions */
#define opendb(w,x,y,z)         (SEL(w), opendb_x(w,x,y,z))
#define closedb(y,z)            (SEL(y), closedb_x(y,z))

/* Functions to execute SQL */
#define sql_script(x,y,z)       (SEL(x), sql_script_x(x,y,z))
................................................................................
  char zBuf[33];
  p = sqlite3_aggregate_context(context, sizeof(*p));
  MD5Final(digest,p);
  MD5DigestToBase16(digest, zBuf);
  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}

/*
** End of copied md5sum() code.
**************************************************************************/

typedef sqlite3_int64 i64;

typedef struct Error Error;
typedef struct Sqlite Sqlite;
typedef struct Statement Statement;

................................................................................
  sqlite3_free(p->zErr);
  p->zErr = 0;
  p->rc = 0;
}

static void print_err(Error *p){
  if( p->rc!=SQLITE_OK ){
    int isWarn = 0;
    if( p->rc==SQLITE_SCHEMA ) isWarn = 1;
    if( sqlite3_strglob("* - no such table: *",p->zErr)==0 ) isWarn = 1;
    printf("%s: (%d) \"%s\" at line %d\n", isWarn ? "Warning" : "Error",
            p->rc, p->zErr, p->iLine);
    if( !isWarn ) nGlobalErr++;
    fflush(stdout);
  }
}

static void print_and_free_err(Error *p){
  print_err(p);
  free_err(p);
}
................................................................................
    pNext = p->pNext;
    int rc;
    rc = pthread_join(p->tid, &ret);
    if( rc!=0 ){
      if( pErr->rc==SQLITE_OK ) system_error(pErr, rc);
    }else{
      printf("Thread %d says: %s\n", p->iTid, (ret==0 ? "..." : (char *)ret));
      fflush(stdout);
    }
    sqlite3_free(p);
  }
  pThreads->pThread = 0;
}

static i64 filesize_x(
................................................................................
    }else{
      ret = (t >= timelimit);
    }
  }
  return ret;
}







/*************************************************************************
**************************************************************************
**************************************************************************
** End infrastructure. Begin tests.
*/

................................................................................
  sql_script(&err, &db,
      "PRAGMA journal_mode = WAL;"
      "CREATE TABLE t1(x PRIMARY KEY);"
      "INSERT INTO t1 VALUES(randomblob(100));"
      "INSERT INTO t1 VALUES(randomblob(100));"
      "INSERT INTO t1 SELECT md5sum(x) FROM t1;"
  );
  closedb(&err, &db);

  setstoptime(&err, nMs);
  for(i=0; i<WALTHREAD1_NTHREAD; i++){
    launch_thread(&err, &threads, walthread1_thread, 0);
  }
  launch_thread(&err, &threads, walthread1_ckpt_thread, 0);
  join_all_threads(&err, &threads);
................................................................................
#include "tt3_index.c"
#include "tt3_lookaside1.c"
#include "tt3_vacuum.c"
#include "tt3_stress.c"

int main(int argc, char **argv){
  struct ThreadTest {
    void (*xTest)(int);   /* Routine for running this test */
    const char *zTest;    /* Name of this test */
    int nMs;              /* How long to run this test, in milliseconds */
  } aTest[] = {
    { walthread1, "walthread1", 20000 },
    { walthread2, "walthread2", 20000 },
    { walthread3, "walthread3", 20000 },
    { walthread4, "walthread4", 20000 },

    { walthread5, "walthread5",  1000 },
    
    { cgt_pager_1,      "cgt_pager_1", 0 },
    { dynamic_triggers, "dynamic_triggers", 20000 },

    { checkpoint_starvation_1, "checkpoint_starvation_1", 10000 },
    { checkpoint_starvation_2, "checkpoint_starvation_2", 10000 },
................................................................................

    { create_drop_index_1, "create_drop_index_1", 10000 },
    { lookaside1,          "lookaside1", 10000 },
    { vacuum1,             "vacuum1", 10000 },
    { stress1,             "stress1", 10000 },
    { stress2,             "stress2", 60000 },
  };

  static char *substArgv[] = { 0, "*", 0 };
  int i, iArg;
  int nTestfound = 0;

  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  if( argc<2 ){
    argc = 2;
    argv = substArgv;
  }




  for(iArg=1; iArg<argc; iArg++){
    for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
      if( sqlite3_strglob(argv[iArg],aTest[i].zTest)==0 ) break;
    }

    if( i>=sizeof(aTest)/sizeof(aTest[0]) ) goto usage;   
  }

  for(iArg=1; iArg<argc; iArg++){
    for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
      char const *z = aTest[i].zTest;
      if( sqlite3_strglob(argv[iArg],z)==0 ){
        printf("Running %s for %d seconds...\n", z, aTest[i].nMs/1000);
        fflush(stdout);
        aTest[i].xTest(aTest[i].nMs);
        nTestfound++;
      }
    }
  }
  if( nTestfound==0 ) goto usage;


  printf("%d errors out of %d tests\n", nGlobalErr, nTestfound);
  return (nGlobalErr>0 ? 255 : 0);

 usage:
  printf("Usage: %s [testname|testprefix*]...\n", argv[0]);
  printf("Available tests are:\n");
  for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
    printf("   %s\n", aTest[i].zTest);
  }

  return 254;
}


Changes to test/tt3_checkpoint.c.

1
2
3
4
5
6
7
8
9
...
142
143
144
145
146
147
148
149
150
/*
** 2001 September 15
**
** 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.
................................................................................
  CheckpointStarvationCtx ctx = { SQLITE_CHECKPOINT_RESTART, 0 };
  checkpoint_starvation_main(nMs, &ctx);
  if( ctx.nMaxFrame>CHECKPOINT_STARVATION_FRAMELIMIT+10 ){
    test_error(&err, "WAL grew too large - %d frames", ctx.nMaxFrame);
  }
  print_and_free_err(&err);
}



|







 







<
<
1
2
3
4
5
6
7
8
9
...
142
143
144
145
146
147
148


/*
** 2011-02-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.
................................................................................
  CheckpointStarvationCtx ctx = { SQLITE_CHECKPOINT_RESTART, 0 };
  checkpoint_starvation_main(nMs, &ctx);
  if( ctx.nMaxFrame>CHECKPOINT_STARVATION_FRAMELIMIT+10 ){
    test_error(&err, "WAL grew too large - %d frames", ctx.nMaxFrame);
  }
  print_and_free_err(&err);
}


Changes to test/wal5.test.

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
  #
  do_multiclient_test tn {

    code1 $do_wal_checkpoint
    code2 $do_wal_checkpoint
    code3 $do_wal_checkpoint

    do_test 3.$tn.1 {
      sql1 {
        PRAGMA page_size = 1024;

        PRAGMA journal_mode = WAL;
        PRAGMA synchronous = normal;
        CREATE TABLE t1(x, y);
        CREATE INDEX i1 ON t1(x, y);
        INSERT INTO t1 VALUES(1, 2);
        INSERT INTO t1 VALUES(3, 4);
      }
      file size test.db-wal
    } [wal_file_size 8 1024]

    do_test 3.$tn.2 { do_wal_checkpoint db -mode truncate } {0 0 0}
    do_test 3.$tn.3 { file size test.db-wal } 0

    do_test 3.$tn.4 {
      sql2 { SELECT * FROM t1 }
    } {1 2 3 4}

    do_test 3.$tn.5 {
      sql2 { INSERT INTO t1 VALUES('a', 'b') }
      file size test.db-wal
    } [wal_file_size 2 1024]

  }
}


finish_test







|


>










|
|

|



|









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
  #
  do_multiclient_test tn {

    code1 $do_wal_checkpoint
    code2 $do_wal_checkpoint
    code3 $do_wal_checkpoint

    do_test 4.$tn.1 {
      sql1 {
        PRAGMA page_size = 1024;
        PRAGMA auto_vacuum = 0;
        PRAGMA journal_mode = WAL;
        PRAGMA synchronous = normal;
        CREATE TABLE t1(x, y);
        CREATE INDEX i1 ON t1(x, y);
        INSERT INTO t1 VALUES(1, 2);
        INSERT INTO t1 VALUES(3, 4);
      }
      file size test.db-wal
    } [wal_file_size 8 1024]

    do_test 4.$tn.2 { do_wal_checkpoint db -mode truncate } {0 0 0}
    do_test 4.$tn.3 { file size test.db-wal } 0

    do_test 4.$tn.4 {
      sql2 { SELECT * FROM t1 }
    } {1 2 3 4}

    do_test 4.$tn.5 {
      sql2 { INSERT INTO t1 VALUES('a', 'b') }
      file size test.db-wal
    } [wal_file_size 2 1024]

  }
}


finish_test

Added test/without_rowid6.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
# 2014-12-28
#
# 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.
#
#***********************************************************************
#
# Verify that WITHOUT ROWID tables work correctly when the PRIMARY KEY
# has redundant columns.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_execsql_test without_rowid6-100 {
  CREATE TABLE t1(a,b,c,d,e, PRIMARY KEY(a,b,c,a,b,c,d,a,b,c)) WITHOUT ROWID;
  CREATE INDEX t1a ON t1(b, b);
  WITH RECURSIVE
    c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<1000)
  INSERT INTO t1(a,b,c,d,e) SELECT i, i+1000, printf('x%dy',i), 0, 0 FROM c;
  ANALYZE;
} {}
do_execsql_test without_rowid6-110 {
  SELECT c FROM t1 WHERE a=123;
} {x123y}
do_execsql_test without_rowid6-120 {
  SELECT c FROM t1 WHERE b=1123;
} {x123y}
do_execsql_test without_rowid6-130 {
  SELECT c FROM t1 ORDER BY a DESC LIMIT 5;
} {x1000y x999y x998y x997y x996y}
do_execsql_test without_rowid6-140 {
  SELECT c FROM t1 ORDER BY b LIMIT 5;
} {x1y x2y x3y x4y x5y}


finish_test

Changes to tool/lemon.c.

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
....
1808
1809
1810
1811
1812
1813
1814


1815
1816
1817
1818
1819
1820
1821
....
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
  static int mhflag = 0;
  static int nolinenosflag = 0;
  static int noResort = 0;
  static struct s_options options[] = {
    {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
    {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
    {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
    {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
    {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},

    {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
    {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},

    {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
                    "Show conflicts resolved by precedence rules"},
    {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
    {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
    {OPT_FLAG, "s", (char*)&statistics,
                                   "Print parser stats to standard output."},
    {OPT_FLAG, "x", (char*)&version, "Print the version number."},


    {OPT_FLAG,0,0,0}
  };
  int i;
  int exitcode;
  struct lemon lem;

  OptInit(argv,options,stderr);
................................................................................
  v = argv[i][0]=='-' ? 1 : 0;
  if( op[j].label==0 ){
    if( err ){
      fprintf(err,"%sundefined option.\n",emsg);
      errline(i,1,err);
    }
    errcnt++;


  }else if( op[j].type==OPT_FLAG ){
    *((int*)op[j].arg) = v;
  }else if( op[j].type==OPT_FFLAG ){
    (*(void(*)(int))(op[j].arg))(v);
  }else if( op[j].type==OPT_FSTR ){
    (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
  }else{
................................................................................
    switch( op[i].type ){
      case OPT_FLAG:
      case OPT_FFLAG:
        fprintf(errstream,"  -%-*s  %s\n",max,op[i].label,op[i].message);
        break;
      case OPT_INT:
      case OPT_FINT:
        fprintf(errstream,"  %s=<integer>%*s  %s\n",op[i].label,
          (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message);
        break;
      case OPT_DBL:
      case OPT_FDBL:
        fprintf(errstream,"  %s=<real>%*s  %s\n",op[i].label,
          (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message);
        break;
      case OPT_STR:
      case OPT_FSTR:
        fprintf(errstream,"  %s=<string>%*s  %s\n",op[i].label,
          (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message);
        break;
    }
  }
}
/*********************** From the file "parse.c" ****************************/
/*







|

>


>







>
>







 







>
>







 







|




|




|







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
....
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
....
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
  static int mhflag = 0;
  static int nolinenosflag = 0;
  static int noResort = 0;
  static struct s_options options[] = {
    {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
    {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
    {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
    {OPT_FSTR, "f", 0, "Ignored.  (Placeholder for -f compiler options.)"},
    {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
    {OPT_FSTR, "I", 0, "Ignored.  (Placeholder for '-I' compiler options.)"},
    {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
    {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},
    {OPT_FSTR, "O", 0, "Ignored.  (Placeholder for '-O' compiler options.)"},
    {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
                    "Show conflicts resolved by precedence rules"},
    {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
    {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
    {OPT_FLAG, "s", (char*)&statistics,
                                   "Print parser stats to standard output."},
    {OPT_FLAG, "x", (char*)&version, "Print the version number."},
    {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
    {OPT_FSTR, "W", 0, "Ignored.  (Placeholder for '-W' compiler options.)"},
    {OPT_FLAG,0,0,0}
  };
  int i;
  int exitcode;
  struct lemon lem;

  OptInit(argv,options,stderr);
................................................................................
  v = argv[i][0]=='-' ? 1 : 0;
  if( op[j].label==0 ){
    if( err ){
      fprintf(err,"%sundefined option.\n",emsg);
      errline(i,1,err);
    }
    errcnt++;
  }else if( op[j].arg==0 ){
    /* Ignore this option */
  }else if( op[j].type==OPT_FLAG ){
    *((int*)op[j].arg) = v;
  }else if( op[j].type==OPT_FFLAG ){
    (*(void(*)(int))(op[j].arg))(v);
  }else if( op[j].type==OPT_FSTR ){
    (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
  }else{
................................................................................
    switch( op[i].type ){
      case OPT_FLAG:
      case OPT_FFLAG:
        fprintf(errstream,"  -%-*s  %s\n",max,op[i].label,op[i].message);
        break;
      case OPT_INT:
      case OPT_FINT:
        fprintf(errstream,"  -%s<integer>%*s  %s\n",op[i].label,
          (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message);
        break;
      case OPT_DBL:
      case OPT_FDBL:
        fprintf(errstream,"  -%s<real>%*s  %s\n",op[i].label,
          (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message);
        break;
      case OPT_STR:
      case OPT_FSTR:
        fprintf(errstream,"  -%s<string>%*s  %s\n",op[i].label,
          (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message);
        break;
    }
  }
}
/*********************** From the file "parse.c" ****************************/
/*

Changes to tool/mkpragmatab.tcl.

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
  IF:   !defined(SQLITE_OMIT_INTEGRITY_CHECK)

  NAME: encoding
  IF:   !defined(SQLITE_OMIT_UTF16)

  NAME: schema_version
  TYPE: HEADER_VALUE

  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: user_version
  TYPE: HEADER_VALUE







  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: freelist_count
  TYPE: HEADER_VALUE


  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: application_id
  TYPE: HEADER_VALUE

  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: compile_options
  IF:   !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)

  NAME: wal_checkpoint
  FLAG: NeedSchema







>




>
>
>
>
>
>
>




>
>




>







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
  IF:   !defined(SQLITE_OMIT_INTEGRITY_CHECK)

  NAME: encoding
  IF:   !defined(SQLITE_OMIT_UTF16)

  NAME: schema_version
  TYPE: HEADER_VALUE
  ARG:  BTREE_SCHEMA_VERSION
  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: user_version
  TYPE: HEADER_VALUE
  ARG:  BTREE_USER_VERSION
  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: data_version
  TYPE: HEADER_VALUE
  ARG:  BTREE_DATA_VERSION
  FLAG: ReadOnly
  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: freelist_count
  TYPE: HEADER_VALUE
  ARG:  BTREE_FREE_PAGE_COUNT
  FLAG: ReadOnly
  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: application_id
  TYPE: HEADER_VALUE
  ARG:  BTREE_APPLICATION_ID
  IF:   !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)

  NAME: compile_options
  IF:   !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)

  NAME: wal_checkpoint
  FLAG: NeedSchema

Changes to tool/mksqlite3c.tcl.

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
            set line {const char sqlite3_version[] = SQLITE_VERSION;}
          }
          regsub {^SQLITE_EXTERN } $line {} line
          puts $out "SQLITE_API $line"
        }
      } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
        regsub {^SQLITE_EXTERN } $line {} line
        puts $out "SQLITE_PRIVATE $line"
      } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
        puts $out "SQLITE_PRIVATE $line"
      } else {
        puts $out $line
      }
    } else {
      puts $out $line







|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
            set line {const char sqlite3_version[] = SQLITE_VERSION;}
          }
          regsub {^SQLITE_EXTERN } $line {} line
          puts $out "SQLITE_API $line"
        }
      } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
        regsub {^SQLITE_EXTERN } $line {} line
        puts $out $line
      } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
        puts $out "SQLITE_PRIVATE $line"
      } else {
        puts $out $line
      }
    } else {
      puts $out $line