Fossil SCM

Updating from trunk to keep up working in the branch with the most recent fossil code.

viriketo 2011-08-30 08:01 merge_renames merge
Commit 75aaf30aadc5cb32b00a5694e56a9216c07f09a5
83 files changed +38 -16 -3 +3 +9 +1 +2 +35 +1 +15 +73 +35 +314 +307 +1 +9 +144 +2 +80 +21 +3 +74 -21 +1 -1 +73 -36 +2 -2 +24 -8 +92 -15 +1 +17 -3 +5 -1 +1 +201 -52 +2 -2 +22 -16 +151 -36 +32 -6 +9 +4 -4 +2 -1 +61 -1 +11 -5 +9 -3 +16 -7 +32 -25 +3 -4 +10 -2 +1 -6 +5 +6 -2 +1 -1 +1 -1 +1 -1 +12 -2 +3777 -1278 +50 -23 +4 -2 +2 -1 +2 -1 +1 -1 +280 -29 +136 -20 +1 -1 +58 -2 +8 -20 +644 -9 +7 -1 +3 -3 +4 -4 +5 -5 +5 -5 -10 +63 -26 +1 +80 -16 +60 +4 +21 -15 +11 -6 +11 -1 +15 -7 +3 +6 +22
+38 -16
--- BUILD.txt
+++ BUILD.txt
@@ -1,41 +1,60 @@
1
-All of the source code for fossil is contained in the src/ subdirectory.
2
-But there is a lot of generated code, so you will probably want to
3
-use the Makefile. To do a complete build on unix, just type:
1
+To do a complete build, just type:
2
+
3
+ ./configure; make
4
+
5
+The ./configure script builds Makefile from Makefile.in based on
6
+your system and any options you select (run "./configure --help"
7
+for a listing of the available options.)
8
+
9
+If you wish to use the original Makefile with no configuration, you can
10
+instead use:
411
5
- make
12
+ make -f Makefile.classic
613
714
On a windows box, use one of the Makefiles in the win/ subdirectory,
8
-according to your compiler and environment. For example:
15
+according to your compiler and environment. If you have GCC and MSYS
16
+installed on your system, then consider:
17
+
18
+ make -f win/Makefile.mingw
19
+
20
+If you have VC++ installed on your system, then consider:
921
10
- make -f win/Makefile.w32
22
+ cd win; nmake /f Makefile.msc
1123
1224
If you have trouble, or you want to do something fancy, just look at
13
-top level makefile. There are 6 configuration options that are all well
14
-commented. Instead of editing the Makefile, consider copying the Makefile
15
-to an alternative name such as "GNUMakefile", "BSDMakefile", or "makefile"
16
-and editing the copy.
25
+Makefile.classic. There are 6 configuration options that are all well
26
+commented. Instead of editing the Makefile.classic, consider copying
27
+Makefile.classic to an alternative name such as "GNUMakefile",
28
+"BSDMakefile", or "makefile" and editing the copy.
1729
1830
1931
BUILDING OUTSIDE THE SOURCE TREE
2032
2133
An out of source build is pretty easy:
2234
23
- 1. Make a new directory to do the builds in.
24
- 2. Copy "Makefile" from the source into the build directory and
25
- modify the SRCDIR macro along the lines of:
35
+ 1. Make and change to a new directory to do the builds in.
36
+ 2. Run the "configure" script from this directory.
37
+ 3. Type: "make"
38
+
39
+For example:
2640
27
- SRCDIR=../src
28
-
29
- 3. type: "make"
41
+ mkdir build
42
+ cd build
43
+ ../configure
44
+ make
3045
3146
This will now keep all generates files seperate from the maintained
3247
source code.
3348
3449
--------------------------------------------------------------------------
3550
3651
Here are some notes on what is happening behind the scenes:
52
+
53
+* The configure script (if used) examines the options given
54
+ and runs various tests with the C compiler to create Makefile
55
+ from the Makefile.in template as well as autoconfig.h
3756
3857
* The Makefile just sets up a few macros and then invokes the
3958
real makefile in src/main.mk. The src/main.mk makefile is
4059
automatically generated by a TCL script found at src/makemake.tcl.
4160
Do not edit src/main.mk directly. Update src/makemake.tcl and
@@ -51,5 +70,8 @@
5170
A header comment in src/translate.c explains in detail what it does.
5271
5372
* The src/mkindex.c program generates some C code that implements
5473
static lookup tables. See the header comment in the source code
5574
for details on what it does.
75
+
76
+Additional information on the build process is available from
77
+http://www.fossil-scm.org/fossil/doc/trunk/www/makefile.wiki
5678
5779
DELETED Makefile
5880
ADDED Makefile.classic
5981
ADDED Makefile.in
6082
ADDED VERSION
6183
ADDED auto.def
6284
ADDED autosetup/LICENSE
6385
ADDED autosetup/README.autosetup
6486
ADDED autosetup/autosetup
6587
ADDED autosetup/cc-lib.tcl
6688
ADDED autosetup/cc-shared.tcl
6789
ADDED autosetup/cc.tcl
6890
ADDED autosetup/config.guess
6991
ADDED autosetup/config.sub
7092
ADDED autosetup/find-tclsh
7193
ADDED autosetup/jimsh0.c
7294
ADDED autosetup/local.tcl
7395
ADDED autosetup/system.tcl
7496
ADDED autosetup/test-tclsh
7597
ADDED configure
--- BUILD.txt
+++ BUILD.txt
@@ -1,41 +1,60 @@
1 All of the source code for fossil is contained in the src/ subdirectory.
2 But there is a lot of generated code, so you will probably want to
3 use the Makefile. To do a complete build on unix, just type:
 
 
 
 
 
 
 
4
5 make
6
7 On a windows box, use one of the Makefiles in the win/ subdirectory,
8 according to your compiler and environment. For example:
 
 
 
 
 
9
10 make -f win/Makefile.w32
11
12 If you have trouble, or you want to do something fancy, just look at
13 top level makefile. There are 6 configuration options that are all well
14 commented. Instead of editing the Makefile, consider copying the Makefile
15 to an alternative name such as "GNUMakefile", "BSDMakefile", or "makefile"
16 and editing the copy.
17
18
19 BUILDING OUTSIDE THE SOURCE TREE
20
21 An out of source build is pretty easy:
22
23 1. Make a new directory to do the builds in.
24 2. Copy "Makefile" from the source into the build directory and
25 modify the SRCDIR macro along the lines of:
 
 
26
27 SRCDIR=../src
28
29 3. type: "make"
 
30
31 This will now keep all generates files seperate from the maintained
32 source code.
33
34 --------------------------------------------------------------------------
35
36 Here are some notes on what is happening behind the scenes:
 
 
 
 
37
38 * The Makefile just sets up a few macros and then invokes the
39 real makefile in src/main.mk. The src/main.mk makefile is
40 automatically generated by a TCL script found at src/makemake.tcl.
41 Do not edit src/main.mk directly. Update src/makemake.tcl and
@@ -51,5 +70,8 @@
51 A header comment in src/translate.c explains in detail what it does.
52
53 * The src/mkindex.c program generates some C code that implements
54 static lookup tables. See the header comment in the source code
55 for details on what it does.
 
 
 
56
57 ELETED Makefile
58 DDED Makefile.classic
59 DDED Makefile.in
60 DDED VERSION
61 DDED auto.def
62 DDED autosetup/LICENSE
63 DDED autosetup/README.autosetup
64 DDED autosetup/autosetup
65 DDED autosetup/cc-lib.tcl
66 DDED autosetup/cc-shared.tcl
67 DDED autosetup/cc.tcl
68 DDED autosetup/config.guess
69 DDED autosetup/config.sub
70 DDED autosetup/find-tclsh
71 DDED autosetup/jimsh0.c
72 DDED autosetup/local.tcl
73 DDED autosetup/system.tcl
74 DDED autosetup/test-tclsh
75 DDED configure
--- BUILD.txt
+++ BUILD.txt
@@ -1,41 +1,60 @@
1 To do a complete build, just type:
2
3 ./configure; make
4
5 The ./configure script builds Makefile from Makefile.in based on
6 your system and any options you select (run "./configure --help"
7 for a listing of the available options.)
8
9 If you wish to use the original Makefile with no configuration, you can
10 instead use:
11
12 make -f Makefile.classic
13
14 On a windows box, use one of the Makefiles in the win/ subdirectory,
15 according to your compiler and environment. If you have GCC and MSYS
16 installed on your system, then consider:
17
18 make -f win/Makefile.mingw
19
20 If you have VC++ installed on your system, then consider:
21
22 cd win; nmake /f Makefile.msc
23
24 If you have trouble, or you want to do something fancy, just look at
25 Makefile.classic. There are 6 configuration options that are all well
26 commented. Instead of editing the Makefile.classic, consider copying
27 Makefile.classic to an alternative name such as "GNUMakefile",
28 "BSDMakefile", or "makefile" and editing the copy.
29
30
31 BUILDING OUTSIDE THE SOURCE TREE
32
33 An out of source build is pretty easy:
34
35 1. Make and change to a new directory to do the builds in.
36 2. Run the "configure" script from this directory.
37 3. Type: "make"
38
39 For example:
40
41 mkdir build
42 cd build
43 ../configure
44 make
45
46 This will now keep all generates files seperate from the maintained
47 source code.
48
49 --------------------------------------------------------------------------
50
51 Here are some notes on what is happening behind the scenes:
52
53 * The configure script (if used) examines the options given
54 and runs various tests with the C compiler to create Makefile
55 from the Makefile.in template as well as autoconfig.h
56
57 * The Makefile just sets up a few macros and then invokes the
58 real makefile in src/main.mk. The src/main.mk makefile is
59 automatically generated by a TCL script found at src/makemake.tcl.
60 Do not edit src/main.mk directly. Update src/makemake.tcl and
@@ -51,5 +70,8 @@
70 A header comment in src/translate.c explains in detail what it does.
71
72 * The src/mkindex.c program generates some C code that implements
73 static lookup tables. See the header comment in the source code
74 for details on what it does.
75
76 Additional information on the build process is available from
77 http://www.fossil-scm.org/fossil/doc/trunk/www/makefile.wiki
78
79 ELETED Makefile
80 DDED Makefile.classic
81 DDED Makefile.in
82 DDED VERSION
83 DDED auto.def
84 DDED autosetup/LICENSE
85 DDED autosetup/README.autosetup
86 DDED autosetup/autosetup
87 DDED autosetup/cc-lib.tcl
88 DDED autosetup/cc-shared.tcl
89 DDED autosetup/cc.tcl
90 DDED autosetup/config.guess
91 DDED autosetup/config.sub
92 DDED autosetup/find-tclsh
93 DDED autosetup/jimsh0.c
94 DDED autosetup/local.tcl
95 DDED autosetup/system.tcl
96 DDED autosetup/test-tclsh
97 DDED configure
D Makefile
-3
--- a/Makefile
+++ b/Makefile
@@ -1,3 +0,0 @@
1
-#!/usr/bin/make
2
-#
3
-# This is tg the build. This is used
--- a/Makefile
+++ b/Makefile
@@ -1,3 +0,0 @@
1 #!/usr/bin/make
2 #
3 # This is tg the build. This is used
--- a/Makefile
+++ b/Makefile
@@ -1,3 +0,0 @@
 
 
 

No diff available

--- a/Makefile.classic
+++ b/Makefile.classic
@@ -0,0 +1,3 @@
1
+#!/usr/bin/make
2
+#
3
+# This is tg the build. This is used
--- a/Makefile.classic
+++ b/Makefile.classic
@@ -0,0 +1,3 @@
 
 
 
--- a/Makefile.classic
+++ b/Makefile.classic
@@ -0,0 +1,3 @@
1 #!/usr/bin/make
2 #
3 # This is tg the build. This is used
--- a/Makefile.in
+++ b/Makefile.in
@@ -0,0 +1,9 @@
1
+ -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzz -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzzSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -D_HAVE_SQLITE_ssitclsh -DFOSSIL_ENABLE_LEGACY_MV_RM=1@CFLAGS@@CFLAGS@Rdi make source
2
+#
3
+#
4
+OBJDIR = ./@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzz -D_HAVE_SQLITE_ssil-@FOSSILendif
5
+ifeq ($(findstriSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzz -D_HAVE_SQLITE$(MAKE) reconfig
6
+endif
7
+@AUTOREMAKE@ && $(MAKE)
8
+endif
9
+FOSSIL_ENABLE_M +
--- a/Makefile.in
+++ b/Makefile.in
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
--- a/Makefile.in
+++ b/Makefile.in
@@ -0,0 +1,9 @@
1 -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzz -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -D_HAVE_SQLITE_ssil-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzzSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX-@FOSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -D_HAVE_SQLITE_ssitclsh -DFOSSIL_ENABLE_LEGACY_MV_RM=1@CFLAGS@@CFLAGS@Rdi make source
2 #
3 #
4 OBJDIR = ./@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzz -D_HAVE_SQLITE_ssil-@FOSSILendif
5 ifeq ($(findstriSSIL_CI_PFX@P@1BE,N:fossil:@FOSSIL_CI_PFX -fuzz -D_HAVE_SQLITE$(MAKE) reconfig
6 endif
7 @AUTOREMAKE@ && $(MAKE)
8 endif
9 FOSSIL_ENABLE_M +
+1
--- a/VERSION
+++ b/VERSION
@@ -0,0 +1 @@
1
+1.19
--- a/VERSION
+++ b/VERSION
@@ -0,0 +1 @@
 
--- a/VERSION
+++ b/VERSION
@@ -0,0 +1 @@
1 1.19
+2
--- a/auto.def
+++ b/auto.def
@@ -0,0 +1,2 @@
1
+D markdown=0 => {Build with markdown enginemarkdown]} {
2
+MARKDOWMARKDOWipv6=1 =>
--- a/auto.def
+++ b/auto.def
@@ -0,0 +1,2 @@
 
 
--- a/auto.def
+++ b/auto.def
@@ -0,0 +1,2 @@
1 D markdown=0 => {Build with markdown enginemarkdown]} {
2 MARKDOWMARKDOWipv6=1 =>
--- a/autosetup/LICENSE
+++ b/autosetup/LICENSE
@@ -0,0 +1,35 @@
1
+Unless explicitly stated, all files which form part of autosetup
2
+are released under the following license:
3
+
4
+---------------------------------------------------------------------
5
+autosetup - A build environment "autoconfigurator"
6
+
7
+Copyright (c) 2010-2011, WorkWare Systems <http://workware.net.au/>
8
+
9
+Redistribution and use in source and binary forms, with or without
10
+modification, are permitted provided that the following conditions
11
+are met:
12
+
13
+1. Redistributions of source code must retain the above copyright
14
+ notice, this list of conditions and the following disclaimer.
15
+2. Redistributions in binary form must reproduce the above
16
+ copyright notice, this list of conditions and the following
17
+ disclaimer in the documentation and/or other materials
18
+ provided with the distribution.
19
+
20
+THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY
21
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE
24
+SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+
33
+The views and conclusions contained in the software and documentation
34
+are those of the authors and should not be interpreted as representing
35
+official policies, either expressed or implied, of WorkWare Systems.
--- a/autosetup/LICENSE
+++ b/autosetup/LICENSE
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/LICENSE
+++ b/autosetup/LICENSE
@@ -0,0 +1,35 @@
1 Unless explicitly stated, all files which form part of autosetup
2 are released under the following license:
3
4 ---------------------------------------------------------------------
5 autosetup - A build environment "autoconfigurator"
6
7 Copyright (c) 2010-2011, WorkWare Systems <http://workware.net.au/>
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 2. Redistributions in binary form must reproduce the above
16 copyright notice, this list of conditions and the following
17 disclaimer in the documentation and/or other materials
18 provided with the distribution.
19
20 THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY
21 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE
24 SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 The views and conclusions contained in the software and documentation
34 are those of the authors and should not be interpreted as representing
35 official policies, either expressed or implied, of WorkWare Systems.
--- a/autosetup/README.autosetup
+++ b/autosetup/README.autosetup
@@ -0,0 +1 @@
1
+This is autosetup v0.6.2. S
--- a/autosetup/README.autosetup
+++ b/autosetup/README.autosetup
@@ -0,0 +1 @@
 
--- a/autosetup/README.autosetup
+++ b/autosetup/README.autosetup
@@ -0,0 +1 @@
1 This is autosetup v0.6.2. S
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -0,0 +1,15 @@
1
+#!/bin/sh
2
+4 => "create an initial 'confbool init]$source#!/bin/sh
3
+parray define
4
+ } else {
5
+ return $alias
6
+ }[error-location $msg]use cc cc-shareduplevel #0#!/bin/sh
7
+${m}.tcl
8
+uplevel #0 [list source $source]put2put3 "Looking for $source"![string m 2>/dev/null} {
9
+ set create_configure 1Use --initset cre#!/bin/sh
10
+4 => "creat # Jim uses system() for exec under mingw, so
11
+ # we need to fetch the output ourselves
12
+ set tmpfile auto[format %04x [rand 10000]].tmp
13
+ set rc [catch [list exec {*}$readfile $tmpfile]
14
+ file delete $tmpfile
15
+ return -code $rc $result
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -0,0 +1,15 @@
1 #!/bin/sh
2 4 => "create an initial 'confbool init]$source#!/bin/sh
3 parray define
4 } else {
5 return $alias
6 }[error-location $msg]use cc cc-shareduplevel #0#!/bin/sh
7 ${m}.tcl
8 uplevel #0 [list source $source]put2put3 "Looking for $source"![string m 2>/dev/null} {
9 set create_configure 1Use --initset cre#!/bin/sh
10 4 => "creat # Jim uses system() for exec under mingw, so
11 # we need to fetch the output ourselves
12 set tmpfile auto[format %04x [rand 10000]].tmp
13 set rc [catch [list exec {*}$readfile $tmpfile]
14 file delete $tmpfile
15 return -code $rc $result
--- a/autosetup/cc-lib.tcl
+++ b/autosetup/cc-lib.tcl
@@ -0,0 +1,73 @@
1
+# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
2
+# All rights reserved
3
+
4
+# @synopsis:
5
+#
6
+# Provides a library of common tests on top ofmodule-options {}of the 'cc' module.
7
+
8
+use cc
9
+
10
+# @cc-check-lfsAC_SYS_LARGEFILE macro
11
+#
12
+# defines 'HAVE_LFS' if L S is available,
13
+# and defines '_FILE_OFFSET_BITS=64' if necessary
14
+#
15
+# Returns 1 if 'LFS' is available or 0 otherwise
16
+#
17
+proc cc-check-lfs {} {
18
+ cc-check-includes sys/types.h
19
+ msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..."
20
+ set lfs 1
21
+ if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} {
22
+ msg-result no
23
+ } elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} {
24
+ define _FILE_OFFSET_BITS 64
25
+ msg-result yes
26
+ } else {
27
+ set lfs 0
28
+ msg-result none
29
+ }
30
+ define-feature lfs $lfs
31
+ return $lfs
32
+}
33
+
34
+# @cc-check-endian
35
+#
36
+# The equivalent of th eAC_C_BIGENDIAN macroth e 'AC_C_BIGENDIAN' macro.
37
+#
38
+# defines 'HAVE_BIG_ENDIAN' if endian is known to be big,
39
+# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little.
40
+#
41
+# Returns 1 if determined, or 0 if not.
42
+#
43
+proc cc-check-endian {} {
44
+ cc-check-includes sys/types.h sys/param.h
45
+ set rc 0
46
+ msg-checking "Checking endian..."
47
+ cc-with {-includes {sys/types.h sys/param.h}} {
48
+ if {[cctest -code {
49
+ #if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER)
50
+ #error unknown
51
+ #elif BYTE_ORDER != BIG_ENDIAN
52
+ #error little
53
+ #endif
54
+ }]} {
55
+ define-feature big-endian
56
+ msg-result "big"
57
+ set rc 1
58
+ } elseif {[cctest -code {
59
+ #if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER)
60
+ #error unknown
61
+ #elif BYTE_ORDER != LITTLE_ENDIAN
62
+ #error big
63
+ #endif
64
+ }]} {
65
+ define-feature little-endian
66
+ msg-result "little"
67
+ set rc 1
68
+ } else {
69
+ msg-result "unknown"
70
+ }
71
+ }
72
+ return $rc
73
+}
--- a/autosetup/cc-lib.tcl
+++ b/autosetup/cc-lib.tcl
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/cc-lib.tcl
+++ b/autosetup/cc-lib.tcl
@@ -0,0 +1,73 @@
1 # Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # Provides a library of common tests on top ofmodule-options {}of the 'cc' module.
7
8 use cc
9
10 # @cc-check-lfsAC_SYS_LARGEFILE macro
11 #
12 # defines 'HAVE_LFS' if L S is available,
13 # and defines '_FILE_OFFSET_BITS=64' if necessary
14 #
15 # Returns 1 if 'LFS' is available or 0 otherwise
16 #
17 proc cc-check-lfs {} {
18 cc-check-includes sys/types.h
19 msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..."
20 set lfs 1
21 if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} {
22 msg-result no
23 } elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} {
24 define _FILE_OFFSET_BITS 64
25 msg-result yes
26 } else {
27 set lfs 0
28 msg-result none
29 }
30 define-feature lfs $lfs
31 return $lfs
32 }
33
34 # @cc-check-endian
35 #
36 # The equivalent of th eAC_C_BIGENDIAN macroth e 'AC_C_BIGENDIAN' macro.
37 #
38 # defines 'HAVE_BIG_ENDIAN' if endian is known to be big,
39 # or 'HAVE_LITTLE_ENDIAN' if endian is known to be little.
40 #
41 # Returns 1 if determined, or 0 if not.
42 #
43 proc cc-check-endian {} {
44 cc-check-includes sys/types.h sys/param.h
45 set rc 0
46 msg-checking "Checking endian..."
47 cc-with {-includes {sys/types.h sys/param.h}} {
48 if {[cctest -code {
49 #if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER)
50 #error unknown
51 #elif BYTE_ORDER != BIG_ENDIAN
52 #error little
53 #endif
54 }]} {
55 define-feature big-endian
56 msg-result "big"
57 set rc 1
58 } elseif {[cctest -code {
59 #if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER)
60 #error unknown
61 #elif BYTE_ORDER != LITTLE_ENDIAN
62 #error big
63 #endif
64 }]} {
65 define-feature little-endian
66 msg-result "little"
67 set rc 1
68 } else {
69 msg-result "unknown"
70 }
71 }
72 return $rc
73 }
--- a/autosetup/cc-shared.tcl
+++ b/autosetup/cc-shared.tcl
@@ -0,0 +1,35 @@
1
+# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2
+# All rights reserved
3
+
4
+# @synopsis:
5
+#
6
+# The 'cc-shared' module provides support for shared libraries and shared objects.
7
+# It defines the following variables:
8
+#
9
+## SH_CFLAGS Flags to use compiling sources destined for a shared library
10
+## SH_LDFLAGS Flags to use linking t the soname when cread libs - %s = version
11
+## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object
12
+## ll symbols table, %s = path
13
+## SH_LINKFLAGS Flags to use linking an executable which will load shared objects
14
+## LD_LIBRARY_PATH Environment variable which specifie
15
+module-options {}
16
+
17
+foreach i {SH_LINKFLAGS SH_CFLAGS SH_LDFLAGS SHOBJ_CFLAGS SHOBJ_LLD_LIBRARY_PATH define SHOBJ_LDFLAGS_R -bobject
18
+## SHOBJ_LDFLAGS Flags to are System# Copyright ( Flags to usDYLD_LIBRARY_PATH
19
+ }
20
+ *-*-ming* {sharedOBJ_LDFLAGSshared}
21
+ *-*-solaris* {
22
+# Copyright (c) 20mwed
23
+## SHOBJ_LD-Kpic Flags to us-Kpic"-G"
24
+define LD_LIBthe toolch-strip-unneeded
25
+
26
+# Note: Thiain
27
+# http://sourceforge sparc* {
28
+AGS SHOBJ_LDFLAGS_rdynamicference for identify-fPICshared Flags to us-fPIC}
29
+ * {
30
+ # Generic Unix settingsstems http://www.workwa# Copyrigference for identifying the toolchain
31
+# http://sourceforge.net/apps/mediawiki/predef/ define SHOBJ_LDFLAGS_R -bobject
32
+## SHOBJ_LDFLAGS Flags to us-fpshared Flags to us-fpicf/ define SHOBJ_LDFLAGS_R -bobject
33
+## SHOBJ_LDFLAGS Flags to us"-shared -nostartfiles"
34
+ }
35
+}
--- a/autosetup/cc-shared.tcl
+++ b/autosetup/cc-shared.tcl
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/cc-shared.tcl
+++ b/autosetup/cc-shared.tcl
@@ -0,0 +1,35 @@
1 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'cc-shared' module provides support for shared libraries and shared objects.
7 # It defines the following variables:
8 #
9 ## SH_CFLAGS Flags to use compiling sources destined for a shared library
10 ## SH_LDFLAGS Flags to use linking t the soname when cread libs - %s = version
11 ## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object
12 ## ll symbols table, %s = path
13 ## SH_LINKFLAGS Flags to use linking an executable which will load shared objects
14 ## LD_LIBRARY_PATH Environment variable which specifie
15 module-options {}
16
17 foreach i {SH_LINKFLAGS SH_CFLAGS SH_LDFLAGS SHOBJ_CFLAGS SHOBJ_LLD_LIBRARY_PATH define SHOBJ_LDFLAGS_R -bobject
18 ## SHOBJ_LDFLAGS Flags to are System# Copyright ( Flags to usDYLD_LIBRARY_PATH
19 }
20 *-*-ming* {sharedOBJ_LDFLAGSshared}
21 *-*-solaris* {
22 # Copyright (c) 20mwed
23 ## SHOBJ_LD-Kpic Flags to us-Kpic"-G"
24 define LD_LIBthe toolch-strip-unneeded
25
26 # Note: Thiain
27 # http://sourceforge sparc* {
28 AGS SHOBJ_LDFLAGS_rdynamicference for identify-fPICshared Flags to us-fPIC}
29 * {
30 # Generic Unix settingsstems http://www.workwa# Copyrigference for identifying the toolchain
31 # http://sourceforge.net/apps/mediawiki/predef/ define SHOBJ_LDFLAGS_R -bobject
32 ## SHOBJ_LDFLAGS Flags to us-fpshared Flags to us-fpicf/ define SHOBJ_LDFLAGS_R -bobject
33 ## SHOBJ_LDFLAGS Flags to us"-shared -nostartfiles"
34 }
35 }
--- a/autosetup/cc.tcl
+++ b/autosetup/cc.tcl
@@ -0,0 +1,314 @@
1
+# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2
+# All rights reserved
3
+
4
+# @synopsis:
5
+#
6
+# The 'cc' module supports checking various 'features' of the C or C++
7
+# compiler/linker environment. Common commands are ,
8
+# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-templatement variables are used if set:
9
+#
10
+## CC - C compiler
11
+## CXX - C++ compiler
12
+## CPP - C preprocessor
13
+##CACHE - Set to "none" to disable automatic use of ccache
14
+## Ciler flags
15
+## CXXFLAGS - Additional C++ compiler flags
16
+## LDFLAGS - Additional compiler flags during linking
17
+## LINKFLAGS - ?How is this diffes to use (for all tests)
18
+## CROSS - Tool prefix for cross compilation
19
+#
20
+# The following variables are defined from the corresponding
21
+# environment variables if set.
22
+#
23
+## CC_FOR_BUILD
24
+## LD
25
+
26
+use systPPFLAGS
27
+## LINKFLAGSmodule-options {}
28
+
29
+# Checks for the existence of the giveNote that the return code is not meaningful
30
+proc cc-check-something {name code} {
31
+ uplevel 1 $codee given type/strunction {function} {
32
+ cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
33
+}
34
+
35
+# Checks for the existence of the given type by compiling
36
+proc cctest_type {type} {
37
+ cctest -code "$type _x;"
38
+}
39
+
40
+# Checks for the existence of the given type/structure member.
41
+# e.g. "struct stat.st_mtime"
42
+proc cctest_member {struct_member} {
43
+ # split at the first dot
44
+ regexp {^([^.]+)[.](.*)$} $lassign me;\n#endif"
45
+}
46
+
47
+# @cc-ch
48
+# e.g. "struct stypeses a variable with the 4 8 1 2 16 32} {
49
+ if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
50
+ set size $i
51
+ break
52
+ }
53
+ }
54
+ msg-result $size
55
+ set define [feature-define-name $type SIZEOF_]
56
+ define $define $size
57
+ }
58
+ # Return the last result
59
+ get-define $define
60
+}
61
+
62
+# Checks for each feature in $list by using the given script.
63
+#
64
+# When the script is evaluated, $each is set to the feature
65
+# being checked, and $extra is set to any additional cctest args.
66
+#
67
+# Returns 1 if all features were found, or 0 otherwise.
68
+proc cc-check-some-feature {list script} {
69
+ set ret 1
70
+ foreach each $list {
71
+ if {![check-feature $each $script]} {
72
+ set ret 0
73
+ }
74
+ }
75
+ return $ret
76
+}
77
+
78
+# @cc-check-includes includes ...
79
+#
80
+# Checks that the given include files can be used.
81
+proc cc-check-includes {args} {
82
+ c
83
+procproc cctest_define {cc-check-some-xp {^([^.]+)[.](.*)$} $struct_member -> struct member
84
+ cctest -code "static $struct _s; return sizeof(_s.$member);"
85
+}
86
+
87
+# Checks for the existence of the given define by compiling
88
+#
89
+proc cctest_define {name} {
90
+ cctest -code "#ifndef $name\n#error not defined\n#endif"
91
+}
92
+
93
+# Checks forcks that the given include files can be used.
94
+proc cc-check-includes {args} {
95
+ cc-check-some-feature $args {
96
+ set with {}
97
+ if {[dict exists $::autosetup(cc-include-deps) $each]} {
98
+ set deps! cc-check-include$exeecks tha]} {
99
+ cc-with [list -includes $w }
100
+ define $TOOL $exeed if set:
101
+#
102
+## CC
103
+# @synopsis:
104
+#
105
+# The 'cc' module supports checking various 'features' of the C or C++
106
+# compiler/linker environment. Common commands are ,
107
+# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-templatement variables are used if set:
108
+#
109
+## CC - C compiler
110
+## CXX - C++ compiler
111
+## CPP - C preprocessor
112
+##CACHE - Set to "none" to disable automatic use of ccache
113
+## Ciler flags
114
+## CXXFLAGS - Additional C++ compiler flags
115
+## LDFLAGS - Additional compiler flags during linking
116
+## LINKFLAGS - ?How is this diffes to use (for all tests)
117
+## CROSS - Tool prefix for cross compilation
118
+#
119
+# The following variables are defined from the corresponding
120
+# environment variables if set.
121
+#
122
+## CC_FOR_BUILD
123
+## LD
124
+
125
+use systPPFLAGS
126
+## LINKFLAGSmodule-options {}
127
+
128
+# Checks for the existence of the giveNote that the return code is not meaningful
129
+proc cc-check-something {name code} {
130
+ uplevel 1 $codee given type/strunction {function} {
131
+ cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
132
+}
133
+
134
+# Checks for the existence of the given type by compiling
135
+proc cctest_type {type} {
136
+ cctest -code "$type _x;"
137
+}
138
+
139
+# Checks for the existence of the given type/structure member.
140
+# e.g. "struct stat.st_mtime"
141
+proc cctest_member {struct_member} {
142
+ # split at the first dot
143
+ regexp {^([^.]+)[.](.*)$} $lassign [split $struct_member .]rn sizeof(_s.$member);"
144
+}
145
+
146
+# Checks for the existence of the given define by compiling
147
+#
148
+proc cctest_define {name} {
149
+ cctest -code "#ifndef $name\n#error not defined\n#endif"
150
+}
151
+
152
+# Checks for the existence of the given name either as
153
+# a macro (#define) or an rvalue (such as an enum)
154
+#
155
+proc cctest_decl {name} {
156
+ cctest -code "#ifndef $name\n(void)$name;\n#endif"
157
+}
158
+
159
+# @cc-check-sizeof type ...
160
+#
161
+# Checks the size of the given types (between 1 and 32, inclusive).
162
+# Defines a variable with the size determined, or 'unknown'"unknown"ng', defines 'SIZEOF_LSIZEOF_LONG_LONGe.
163
+#
164
+proc cc-check-sizeof {args} {
165
+ foreach type $args {
166
+ msg-checking "Checking for sizeof $type..."
167
+ set size unknown
168
+ # Try the most common sizes first
169
+ foreach i {4 8 1 2 16 32} {
170
+ if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
171
+ set size $i
172
+ break
173
+ }
174
+ }
175
+ msg-result $size
176
+ set define [feature-define-name $type SIZEOF_]
177
+ define $define $size
178
+ }
179
+ # Return the last result
180
+ get-define $define
181
+}
182
+
183
+# Checks for each feature in $list by using the given script.
184
+#
185
+# When the script is evaluated, $each is set to the feature
186
+# being checked, and $extra is set to any additional cctest args.
187
+#
188
+# Returns 1 if all features were found, or 0 otherwise.
189
+proc cc-check-some-feature {list script} {
190
+ set ret 1
191
+ foreach each $list {
192
+ if {![check-feature $each $script]} {
193
+ set ret 0
194
+ }
195
+ }
196
+ return $ret
197
+}
198
+
199
+# @cc-check-includes includes ...
200
+#
201
+# Checks that the given include files can be used.
202
+proc cc-check-includes {args} {
203
+ c
204
+procproc cctest_define {cc-check-some-xp {^([^.]+)[.](.*)$} $struct_member -> struct member
205
+ cctest -code "static $struct _s; return sizeof(_s.$member);"
206
+}
207
+
208
+# Checks for the existence of the given define by compiling
209
+#
210
+proc cctest_define {name} {
211
+ cctest -code "#ifndef $name\n#error not defined\n#endif"
212
+}
213
+
214
+# Checks for the existence of the given name either as
215
+# a macro (#define) or an rvalue (such as an enum)
216
+#
217
+proc cctest_decl {name} {
218
+ cctest -code "#ifndef $name\n(void)$name;\n#endif"
219
+}
220
+ given types (bet#includeddetermined, or 'unknown' otherwise.
221
+# e.g. for type 'long long', defines 'SIZEOF_LONG_LONG'.
222
+# Returns the size of the last type.
223
+#
224
+proc cc-check-sizeof {args} {
225
+ foreach type $adfirst dot
226
+ regexp {^([^.]+)[.](.*)$} $struct_member -> struct member
227
+ cctest -code "static $struct _s; return sizeof(_s.$member);"
228
+}
229
+
230
+# Checks for the existence of the given define by compiling
231
+#
232
+proc cctest_define FLAGS - ?How is this di# @synopsis:
233
+#
234
+# The 'cc' module supports checking various 'features' of the C or C++
235
+# compiler/linker environment. Common commands are ,
236
+# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-templatement variables are used if set:
237
+#
238
+## CC - C compiler
239
+## CXX - C++ compiler
240
+## CPP - C preprocessor
241
+##CACHE - Set to "none" to disfor a declsable automatic use of ccache
242
+## Ciler flags
243
+## C# Copyright (c) 2010 Work foreach type $args {
244
+ msg-checking "Checking for sizeof $type..."
245
+ set size unknown
246
+ # Try the most common sizes first
247
+ foreach i {4 8 1 2 16 32} {
248
+ if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
249
+ set size $i
250
+ break
251
+ }
252
+ }
253
+ msg-result $size
254
+ set define [feature-define-name $type SIZEOF_]
255
+ define $define $size
256
+ }
257
+ # Return the last result
258
+ get-define $define
259
+}
260
+
261
+# Checks for each feature in $list by using the given script.
262
+#
263
+# When the script is evaluated, $each is set to the feature
264
+# being checked, and $extra is set to any additional cctest args.
265
+#
266
+# Returns 1 if all features were found, or 0 otherwise.
267
+proc cc-check-some-feature {list script} {
268
+ set ret 1ch $script]} {
269
+ set ret 0
270
+ }
271
+ }
272
+ return $ret
273
+}
274
+
275
+# @cc-check-includes includes ...
276
+#
277
+# Checks that the given include files can be used.
278
+proc cc-check-includes {args} {
279
+ cc-check-some-feature $args {
280
+ set with {}
281
+ if {[dict exists $::autosetup(cc-include-deps) $each]} {
282
+ set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
283
+ msg-quiet cc-check-includes {*}$deps
284
+ foreach i $deps {
285
+ if {[have-feature $i]} {
286
+ lappend with $i
287
+ure $each $scriptargs {
288
+ set new($name) $value
289
+ } $i]} {
290
+ lappend$newme\n(void)$name;\n#th]} {
291
+ cc-with [list -includes $with] {
292
+ cctest -includes $each
293
+ }
294
+ } else {
295
+ cctest -includes $each
296
+ }
297
+ }
298
+}
299
+
300
+# @cc-include-needs include required ...
301
+#
302
+# Ensures that when checking for '$include', a check is first
303
+# made for eachtk is first
304
+# made for each '$required' file, and if found, it is included with '#include'.
305
+proc cc-include-needs {file args} {
306
+ foreach depfile $args {
307
+ dict set ::autosetup(cc-include-deps) $file $depfile 1
308
+ }
309
+}
310
+
311
+# C *-*-darwin* {
312
+ # Don't-gstabs
313
+ }
314
+ }$value$valuecc-check-tools ld
--- a/autosetup/cc.tcl
+++ b/autosetup/cc.tcl
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/cc.tcl
+++ b/autosetup/cc.tcl
@@ -0,0 +1,314 @@
1 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # The 'cc' module supports checking various 'features' of the C or C++
7 # compiler/linker environment. Common commands are ,
8 # cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-templatement variables are used if set:
9 #
10 ## CC - C compiler
11 ## CXX - C++ compiler
12 ## CPP - C preprocessor
13 ##CACHE - Set to "none" to disable automatic use of ccache
14 ## Ciler flags
15 ## CXXFLAGS - Additional C++ compiler flags
16 ## LDFLAGS - Additional compiler flags during linking
17 ## LINKFLAGS - ?How is this diffes to use (for all tests)
18 ## CROSS - Tool prefix for cross compilation
19 #
20 # The following variables are defined from the corresponding
21 # environment variables if set.
22 #
23 ## CC_FOR_BUILD
24 ## LD
25
26 use systPPFLAGS
27 ## LINKFLAGSmodule-options {}
28
29 # Checks for the existence of the giveNote that the return code is not meaningful
30 proc cc-check-something {name code} {
31 uplevel 1 $codee given type/strunction {function} {
32 cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
33 }
34
35 # Checks for the existence of the given type by compiling
36 proc cctest_type {type} {
37 cctest -code "$type _x;"
38 }
39
40 # Checks for the existence of the given type/structure member.
41 # e.g. "struct stat.st_mtime"
42 proc cctest_member {struct_member} {
43 # split at the first dot
44 regexp {^([^.]+)[.](.*)$} $lassign me;\n#endif"
45 }
46
47 # @cc-ch
48 # e.g. "struct stypeses a variable with the 4 8 1 2 16 32} {
49 if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
50 set size $i
51 break
52 }
53 }
54 msg-result $size
55 set define [feature-define-name $type SIZEOF_]
56 define $define $size
57 }
58 # Return the last result
59 get-define $define
60 }
61
62 # Checks for each feature in $list by using the given script.
63 #
64 # When the script is evaluated, $each is set to the feature
65 # being checked, and $extra is set to any additional cctest args.
66 #
67 # Returns 1 if all features were found, or 0 otherwise.
68 proc cc-check-some-feature {list script} {
69 set ret 1
70 foreach each $list {
71 if {![check-feature $each $script]} {
72 set ret 0
73 }
74 }
75 return $ret
76 }
77
78 # @cc-check-includes includes ...
79 #
80 # Checks that the given include files can be used.
81 proc cc-check-includes {args} {
82 c
83 procproc cctest_define {cc-check-some-xp {^([^.]+)[.](.*)$} $struct_member -> struct member
84 cctest -code "static $struct _s; return sizeof(_s.$member);"
85 }
86
87 # Checks for the existence of the given define by compiling
88 #
89 proc cctest_define {name} {
90 cctest -code "#ifndef $name\n#error not defined\n#endif"
91 }
92
93 # Checks forcks that the given include files can be used.
94 proc cc-check-includes {args} {
95 cc-check-some-feature $args {
96 set with {}
97 if {[dict exists $::autosetup(cc-include-deps) $each]} {
98 set deps! cc-check-include$exeecks tha]} {
99 cc-with [list -includes $w }
100 define $TOOL $exeed if set:
101 #
102 ## CC
103 # @synopsis:
104 #
105 # The 'cc' module supports checking various 'features' of the C or C++
106 # compiler/linker environment. Common commands are ,
107 # cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-templatement variables are used if set:
108 #
109 ## CC - C compiler
110 ## CXX - C++ compiler
111 ## CPP - C preprocessor
112 ##CACHE - Set to "none" to disable automatic use of ccache
113 ## Ciler flags
114 ## CXXFLAGS - Additional C++ compiler flags
115 ## LDFLAGS - Additional compiler flags during linking
116 ## LINKFLAGS - ?How is this diffes to use (for all tests)
117 ## CROSS - Tool prefix for cross compilation
118 #
119 # The following variables are defined from the corresponding
120 # environment variables if set.
121 #
122 ## CC_FOR_BUILD
123 ## LD
124
125 use systPPFLAGS
126 ## LINKFLAGSmodule-options {}
127
128 # Checks for the existence of the giveNote that the return code is not meaningful
129 proc cc-check-something {name code} {
130 uplevel 1 $codee given type/strunction {function} {
131 cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
132 }
133
134 # Checks for the existence of the given type by compiling
135 proc cctest_type {type} {
136 cctest -code "$type _x;"
137 }
138
139 # Checks for the existence of the given type/structure member.
140 # e.g. "struct stat.st_mtime"
141 proc cctest_member {struct_member} {
142 # split at the first dot
143 regexp {^([^.]+)[.](.*)$} $lassign [split $struct_member .]rn sizeof(_s.$member);"
144 }
145
146 # Checks for the existence of the given define by compiling
147 #
148 proc cctest_define {name} {
149 cctest -code "#ifndef $name\n#error not defined\n#endif"
150 }
151
152 # Checks for the existence of the given name either as
153 # a macro (#define) or an rvalue (such as an enum)
154 #
155 proc cctest_decl {name} {
156 cctest -code "#ifndef $name\n(void)$name;\n#endif"
157 }
158
159 # @cc-check-sizeof type ...
160 #
161 # Checks the size of the given types (between 1 and 32, inclusive).
162 # Defines a variable with the size determined, or 'unknown'"unknown"ng', defines 'SIZEOF_LSIZEOF_LONG_LONGe.
163 #
164 proc cc-check-sizeof {args} {
165 foreach type $args {
166 msg-checking "Checking for sizeof $type..."
167 set size unknown
168 # Try the most common sizes first
169 foreach i {4 8 1 2 16 32} {
170 if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
171 set size $i
172 break
173 }
174 }
175 msg-result $size
176 set define [feature-define-name $type SIZEOF_]
177 define $define $size
178 }
179 # Return the last result
180 get-define $define
181 }
182
183 # Checks for each feature in $list by using the given script.
184 #
185 # When the script is evaluated, $each is set to the feature
186 # being checked, and $extra is set to any additional cctest args.
187 #
188 # Returns 1 if all features were found, or 0 otherwise.
189 proc cc-check-some-feature {list script} {
190 set ret 1
191 foreach each $list {
192 if {![check-feature $each $script]} {
193 set ret 0
194 }
195 }
196 return $ret
197 }
198
199 # @cc-check-includes includes ...
200 #
201 # Checks that the given include files can be used.
202 proc cc-check-includes {args} {
203 c
204 procproc cctest_define {cc-check-some-xp {^([^.]+)[.](.*)$} $struct_member -> struct member
205 cctest -code "static $struct _s; return sizeof(_s.$member);"
206 }
207
208 # Checks for the existence of the given define by compiling
209 #
210 proc cctest_define {name} {
211 cctest -code "#ifndef $name\n#error not defined\n#endif"
212 }
213
214 # Checks for the existence of the given name either as
215 # a macro (#define) or an rvalue (such as an enum)
216 #
217 proc cctest_decl {name} {
218 cctest -code "#ifndef $name\n(void)$name;\n#endif"
219 }
220 given types (bet#includeddetermined, or 'unknown' otherwise.
221 # e.g. for type 'long long', defines 'SIZEOF_LONG_LONG'.
222 # Returns the size of the last type.
223 #
224 proc cc-check-sizeof {args} {
225 foreach type $adfirst dot
226 regexp {^([^.]+)[.](.*)$} $struct_member -> struct member
227 cctest -code "static $struct _s; return sizeof(_s.$member);"
228 }
229
230 # Checks for the existence of the given define by compiling
231 #
232 proc cctest_define FLAGS - ?How is this di# @synopsis:
233 #
234 # The 'cc' module supports checking various 'features' of the C or C++
235 # compiler/linker environment. Common commands are ,
236 # cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-templatement variables are used if set:
237 #
238 ## CC - C compiler
239 ## CXX - C++ compiler
240 ## CPP - C preprocessor
241 ##CACHE - Set to "none" to disfor a declsable automatic use of ccache
242 ## Ciler flags
243 ## C# Copyright (c) 2010 Work foreach type $args {
244 msg-checking "Checking for sizeof $type..."
245 set size unknown
246 # Try the most common sizes first
247 foreach i {4 8 1 2 16 32} {
248 if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
249 set size $i
250 break
251 }
252 }
253 msg-result $size
254 set define [feature-define-name $type SIZEOF_]
255 define $define $size
256 }
257 # Return the last result
258 get-define $define
259 }
260
261 # Checks for each feature in $list by using the given script.
262 #
263 # When the script is evaluated, $each is set to the feature
264 # being checked, and $extra is set to any additional cctest args.
265 #
266 # Returns 1 if all features were found, or 0 otherwise.
267 proc cc-check-some-feature {list script} {
268 set ret 1ch $script]} {
269 set ret 0
270 }
271 }
272 return $ret
273 }
274
275 # @cc-check-includes includes ...
276 #
277 # Checks that the given include files can be used.
278 proc cc-check-includes {args} {
279 cc-check-some-feature $args {
280 set with {}
281 if {[dict exists $::autosetup(cc-include-deps) $each]} {
282 set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
283 msg-quiet cc-check-includes {*}$deps
284 foreach i $deps {
285 if {[have-feature $i]} {
286 lappend with $i
287 ure $each $scriptargs {
288 set new($name) $value
289 } $i]} {
290 lappend$newme\n(void)$name;\n#th]} {
291 cc-with [list -includes $with] {
292 cctest -includes $each
293 }
294 } else {
295 cctest -includes $each
296 }
297 }
298 }
299
300 # @cc-include-needs include required ...
301 #
302 # Ensures that when checking for '$include', a check is first
303 # made for eachtk is first
304 # made for each '$required' file, and if found, it is included with '#include'.
305 proc cc-include-needs {file args} {
306 foreach depfile $args {
307 dict set ::autosetup(cc-include-deps) $file $depfile 1
308 }
309 }
310
311 # C *-*-darwin* {
312 # Don't-gstabs
313 }
314 }$value$valuecc-check-tools ld
--- a/autosetup/config.guess
+++ b/autosetup/config.guess
@@ -0,0 +1,307 @@
1
+03-23 the terms of the GNU General Public License as published by
2
+# t(C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006,oftware Foundation, 0-09-24r
4
+# (at your option) any later version.
5
+#
6
+# This program is distributed in the hope that it will be useful, but
7
+# WITHOUT ANY WARRANTY; without even the implied w2 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8
+# General Public License for more details.
9
+#
10
+# You should have received a copy of the GNU General Public License
11
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
12
+#
13
+# As a special exceptionto the GNU General Public License, if you
14
+# distribute this file as part of a program that contains a
15
+# configuration script generated by Autoconwrite to the Free Software
16
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Bmay include it under
17
+# the same distribution terms that you use for the rest of that
18
+# program. This Exception is an additional permission under section 7
19
+# of the GNU General Public License, version 3 ("GPLv3").
20
+#
21
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
22
+#
23
+# You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
24
+
25
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
26
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
27
+# Attempt to guess a canonical system name.
28
+# Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
29
+# under the terms of the GNU General Public License as published by
30
+# t;e Free Software Foundation, either version 3 of the L;cense, or
31
+# (at your option) any later version.
32
+#
33
+# This program is distributed in the hope that it will be useful, but
34
+# WITHOUT ANY WARRANTY; without even the implied warranty of
35
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36
+# General Public License for more details.
37
+#
38
+# You should have received a copy of the GNU General Public License
39
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
40
+#
41
+# As a special exceptionto the GNU General Public License, if you
42
+# distribute this file as part of a program that contains a
43
+# configuration script generated by Autoconf, you may include it under
44
+# the same distribution terms that you use for the rest of that
45
+# program. This Exception is an additional permission under section 7
46
+# of the GNU General Public License, version 3 ("GPLv3").
47
+#
48
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
49
+#
50
+# You can get the latest version of this script from:
51
+# https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
52
+
53
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
54
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
55
+# Attempt to guess a canoniAttempt to g! /bin/sh
56
+# Attemp#*) machine=${! /bin/sh
57
+# Attemp#! /bin/sh
58
+# Attempt to guess a canonical system name.
59
+# Copyright 1992-2018canonical system name.
60
+# Copyrig! /bin/sh
61
+# Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
62
+# Attemp#! /bin/sh
63
+# Attempt to guess a ${! /bin/sh
64
+# Attemp#! /bin/sh
65
+# Attempt to guess a cekkoBSD:*:*)
66
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
67
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
68
+# Attempt to guess a canonical system name.
69
+# Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
70
+# Copyright 1992-2018 Free Software Foundation, Inc.
71
+
72
+timestamp='2018-03-08it and/or modify it
73
+# under the terms of the GNU General Public License as published by
74
+# t;e Free Software Foundation, either version 3 of the L;cense, or
75
+# (at your o program.
76
+
77
+
78
+# neral Public License
79
+# along with he GNU General Public03-23 the terms of the and include a ChangeLog
80
+# entrhe GNU General Public License as published by
81
+# t;e Free Software Foundation, either version 3 of the L;cense, or
82
+# (at your option) any later version.
83
+#
84
+# This program is distributed in the hope that it will be useful, but
85
+# WITHOUT ANY WARRANTY; without even the implied warranty of
86
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
87
+# General Public License for more details.
88
+#
89
+# You should have received a copy of the GNU General Public License
90
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
91
+#
92
+# As a special exceptionto the GNU General Public License, if you
93
+# distribute this file as part of a program that contains a
94
+# configuration script generated by Autoconf, you may include it under
95
+# the same distribution terms that you use for the rest of that
96
+# program. This Exception is an additional permission under section 7
97
+# of the GNU General Public License, version 3 ("GPLv3").
98
+#
99
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
100
+#
101
+# You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
102
+
103
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
104
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
105
+# Attempt to guess a canonical system name.
106
+# Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
107
+# under the terms of the GNU General Public License as published by
108
+# t;e Free Software Foundation, either version 3 of the L;cense, or
109
+# (at your option) any later version.
110
+#
111
+# This program is distributed in the hope that it will be useful, but
112
+# WITHOUT ANY WARRANTY; without even the implied warranty of
113
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
114
+# General Public License for more details.
115
+#
116
+# You should have received a copy of the GNU General Public License
117
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
118
+#
119
+# As a special exceptionto the GNU General Public License, if you
120
+# distribute this file as part of a program that contains a
121
+# configuration script generated by Autoconf, you may include it under
122
+# the same distribution terms that you use for the rest of that
123
+# program. This Exception is an additional permission under section 7
124
+# of the GNU General Public License, version 3 ("GPLv3").
125
+#
126
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
127
+#
128
+# You can get the latest version of this script from:
129
+# https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
130
+
131
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
132
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
133
+# Attempt to guess a canoniAttempt to g! /bin/sh
134
+# Attemp#*) machine=${! /bin/sh
135
+# Attemp#! /bin/sh
136
+# Attempt to guess a canonical system name.
137
+# Copyright 1992-2018canonical system name.
138
+# Copyrig! /bin/sh
139
+# Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
140
+# Attemp#! /bin/sh
141
+# Attempt to guess a ${! /bin/sh
142
+# Attemp#! /bin/sh
143
+# Attempt to guess a cekkoBSD:*:*)
144
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
145
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
146
+# Attempt to guess a canonical system name.
147
+# Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
148
+# Copyright 1992-2018 Free Software Foundation, Inc.
149
+
150
+timestamp='2018-03-08it and/or modify it
151
+# under the terms of the GNU General Public License as published by
152
+# t;e Free Software Foundation, either version 3 of the L;cense, or
153
+# (at your o.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
154
+# Attempt to guess a canonical system name.
155
+# Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
156
+# under the terms of the GNU General Public License as published by
157
+# t;e Free Software Foundation, either version 3 of the L;cense, or
158
+# (at your option) any later version.
159
+#
160
+# This program is distributed in the hope that it will be useful, but
161
+# WITHOUT ANY WARRANTY; without even the implied warranty of
162
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
163
+# General Public License for more details.
164
+#
165
+# You should have received a copy of the GNU General Public License
166
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
167
+#
168
+# As a special exceptionto the GNU General Public License, if you
169
+# distribute this file as part of a program that contains a
170
+# configuration script generated by Autoconf, you may include it under
171
+# the same distribution terms that you use for the rest of that
172
+# program. This Exception is an additional permission under section 7
173
+# of the GNU General Public License, version 3 ("GPLv3").
174
+#
175
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
176
+#
177
+# You can get the latest version of this script from:
178
+# https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
179
+
180
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
181
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
182
+# Attempt to guess a canoniAttempt to g! /bin/sh
183
+# Attemp#*) machine=${! /bin/sh
184
+# Attemp#! /bin/sh
185
+# Attempt to guess a canonical system name.
186
+# Copyright 1992-2018canonical system name.
187
+# Copyrig! /bin/sh
188
+# Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
189
+# Attemp#! /bin/sh
190
+# Attempt to guess a ${! /bin/sh
191
+# Attemp#! /bin/sh
192
+# Attempt to guess a cekkoBSD:*:*)
193
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
194
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
195
+# Attempt to guess a canonical system name.
196
+# Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
197
+# Copyright 1992-2018 Free Software Foundation, Inc.
198
+
199
+timestamp='2018-03-08it and/or modify it
200
+# under the terms of the GNU General Public License as published by
201
+# t;e Free Software Foundation, either version 3 of the L;cense, or
202
+# (at your oished by
203
+# t;e Free Software Foundation, either version 3 of the L;cense, or
204
+# (at your option) any later version.
205
+#
206
+# This program is distributed in the hope that it will be useful, but
207
+# WITHOUT ANY WARRANTY; without even the implied warranty of
208
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
209
+# General Public License for more details.
210
+#
211
+# You should have received a copy of the GNU General Public License
212
+# along with this progra(C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
213
+2001, 2002, 2003, 2004, 2005, 2006, 2implied warranty ofot, see <https://www.gnu.org/licenses/>.
214
+#
215
+# As a special exceptionto the GNU General Public License, if you
216
+# distribute this file as part of a program that contains a
217
+# configuration script generated by Autoconf, you may include it under
218
+# the same distribution terms that you use for the rest of that
219
+# program. This Exception is an additional permission under section 7
220
+# of the GNU General Public License, version 3 ("GPLv3").
221
+#
222
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
223
+#
224
+# You can get the latest version of this script from:
225
+# https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
226
+
227
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
228
+ cat <<-EOF > $dummy.c`$CC_FORHUP INT TERMneral Public License, version 3 ("GPLv3").
229
+#
230
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
231
+#
232
+# You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
233
+
234
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
235
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
236
+# Attempt to guess a canonical system name.
237
+# Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
238
+# under the terms of the GNU General Public License as published by
239
+# t;e Free Software Foundation, either version 3 of the L;cense, or
240
+# (at your optionHUP INT PIPE TERM03-23 the terms of the GNU General Public License as published by
241
+# t;e Free Software Foundation, either version 3 of the L;cense, or
242
+# (at your option) any later version.
243
+#
244
+# This program is distributed in the hope tha03-23 the terms of the GNU General Public License as published by
245
+# t;e Free Software Foundation, either version 3 of the L;cense, or
246
+# (at your option) any later version.
247
+#
248
+# This program is distributed in the hope that it will be useful, but
249
+# WITHOUT ANY WARRANTY; without even the implied warranty of
250
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
251
+# General Public License for more details.
252
+#
253
+# You should have received a copy of the GNU General Public License
254
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
255
+#
256
+# As a special exceptionto the GNU General Public License, if you
257
+# distribute this file as part of a program that contains a
258
+# configuration script generated by Autoconf, you may include it under
259
+# the same distribution terms that you use for the rest of that
260
+# program. This Exception is an additional permission under section 7
261
+# of the GNU General Public License, version 3 ("GPLv3").
262
+#
263
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
264
+#
265
+# You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
266
+
267
+$dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
268
+ cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
269
+# Attempt to guess a canonical system name.
270
+# Open exit :riscos:*:*|arm t it will be useful, but
271
+03-23 th 23 the terms of the GNU General Public License as published by
272
+# t;e Free Software Foundation, either version 3 of the L;cense, or
273
+# (at your option) any later version.
274
+#
275
+# This program is distributed in the hope that it will be useful, but
276
+# WITHOUT ANY WARRANTY; without even the implied warranty of
277
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
278
+# General Public License for more details.
279
+#
280
+# You should have received a copy of the GNU General Public License
281
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
282
+#
283
+# As a special exceptionto the GNU General Public License, if you
284
+# distribute this file as part of a program that contains a
285
+# configuration script generated by Autoconf, you may include it under
286
+# the same distribution terms that you use for the rest of that
287
+# program. This Exception is an additional permission under section 7
288
+# of the GNU General Public License, version 3 ("GPLv3").
289
+#
290
+# Originally written ms of the GNU Genera532)case "${sc_kernel_bits}" in
291
+ 32) HP_ARCH="hppa2.0n" ;;
292
+esac ;;
293
+
294
+ #include <stdlib.h>
295
+ #include <unistd.h>
296
+
297
+ int main ()
298
+ {
299
+ #if
300
+ #endif
301
+switch (cpu)
302
+ "); break;
303
+ 2_0:
304
+ #if
305
+ switch (bits)
306
+ {
307
+
--- a/autosetup/config.guess
+++ b/autosetup/config.guess
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/config.guess
+++ b/autosetup/config.guess
@@ -0,0 +1,307 @@
1 03-23 the terms of the GNU General Public License as published by
2 # t(C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006,oftware Foundation, 0-09-24r
4 # (at your option) any later version.
5 #
6 # This program is distributed in the hope that it will be useful, but
7 # WITHOUT ANY WARRANTY; without even the implied w2 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8 # General Public License for more details.
9 #
10 # You should have received a copy of the GNU General Public License
11 # along with this program; if not, see <https://www.gnu.org/licenses/>.
12 #
13 # As a special exceptionto the GNU General Public License, if you
14 # distribute this file as part of a program that contains a
15 # configuration script generated by Autoconwrite to the Free Software
16 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Bmay include it under
17 # the same distribution terms that you use for the rest of that
18 # program. This Exception is an additional permission under section 7
19 # of the GNU General Public License, version 3 ("GPLv3").
20 #
21 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
22 #
23 # You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
24
25 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
26 cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
27 # Attempt to guess a canonical system name.
28 # Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
29 # under the terms of the GNU General Public License as published by
30 # t;e Free Software Foundation, either version 3 of the L;cense, or
31 # (at your option) any later version.
32 #
33 # This program is distributed in the hope that it will be useful, but
34 # WITHOUT ANY WARRANTY; without even the implied warranty of
35 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 # General Public License for more details.
37 #
38 # You should have received a copy of the GNU General Public License
39 # along with this program; if not, see <https://www.gnu.org/licenses/>.
40 #
41 # As a special exceptionto the GNU General Public License, if you
42 # distribute this file as part of a program that contains a
43 # configuration script generated by Autoconf, you may include it under
44 # the same distribution terms that you use for the rest of that
45 # program. This Exception is an additional permission under section 7
46 # of the GNU General Public License, version 3 ("GPLv3").
47 #
48 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
49 #
50 # You can get the latest version of this script from:
51 # https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
52
53 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
54 cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
55 # Attempt to guess a canoniAttempt to g! /bin/sh
56 # Attemp#*) machine=${! /bin/sh
57 # Attemp#! /bin/sh
58 # Attempt to guess a canonical system name.
59 # Copyright 1992-2018canonical system name.
60 # Copyrig! /bin/sh
61 # Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
62 # Attemp#! /bin/sh
63 # Attempt to guess a ${! /bin/sh
64 # Attemp#! /bin/sh
65 # Attempt to guess a cekkoBSD:*:*)
66 echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
67 echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
68 # Attempt to guess a canonical system name.
69 # Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
70 # Copyright 1992-2018 Free Software Foundation, Inc.
71
72 timestamp='2018-03-08it and/or modify it
73 # under the terms of the GNU General Public License as published by
74 # t;e Free Software Foundation, either version 3 of the L;cense, or
75 # (at your o program.
76
77
78 # neral Public License
79 # along with he GNU General Public03-23 the terms of the and include a ChangeLog
80 # entrhe GNU General Public License as published by
81 # t;e Free Software Foundation, either version 3 of the L;cense, or
82 # (at your option) any later version.
83 #
84 # This program is distributed in the hope that it will be useful, but
85 # WITHOUT ANY WARRANTY; without even the implied warranty of
86 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
87 # General Public License for more details.
88 #
89 # You should have received a copy of the GNU General Public License
90 # along with this program; if not, see <https://www.gnu.org/licenses/>.
91 #
92 # As a special exceptionto the GNU General Public License, if you
93 # distribute this file as part of a program that contains a
94 # configuration script generated by Autoconf, you may include it under
95 # the same distribution terms that you use for the rest of that
96 # program. This Exception is an additional permission under section 7
97 # of the GNU General Public License, version 3 ("GPLv3").
98 #
99 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
100 #
101 # You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
102
103 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
104 cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
105 # Attempt to guess a canonical system name.
106 # Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
107 # under the terms of the GNU General Public License as published by
108 # t;e Free Software Foundation, either version 3 of the L;cense, or
109 # (at your option) any later version.
110 #
111 # This program is distributed in the hope that it will be useful, but
112 # WITHOUT ANY WARRANTY; without even the implied warranty of
113 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
114 # General Public License for more details.
115 #
116 # You should have received a copy of the GNU General Public License
117 # along with this program; if not, see <https://www.gnu.org/licenses/>.
118 #
119 # As a special exceptionto the GNU General Public License, if you
120 # distribute this file as part of a program that contains a
121 # configuration script generated by Autoconf, you may include it under
122 # the same distribution terms that you use for the rest of that
123 # program. This Exception is an additional permission under section 7
124 # of the GNU General Public License, version 3 ("GPLv3").
125 #
126 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
127 #
128 # You can get the latest version of this script from:
129 # https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
130
131 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
132 cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
133 # Attempt to guess a canoniAttempt to g! /bin/sh
134 # Attemp#*) machine=${! /bin/sh
135 # Attemp#! /bin/sh
136 # Attempt to guess a canonical system name.
137 # Copyright 1992-2018canonical system name.
138 # Copyrig! /bin/sh
139 # Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
140 # Attemp#! /bin/sh
141 # Attempt to guess a ${! /bin/sh
142 # Attemp#! /bin/sh
143 # Attempt to guess a cekkoBSD:*:*)
144 echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
145 echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
146 # Attempt to guess a canonical system name.
147 # Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
148 # Copyright 1992-2018 Free Software Foundation, Inc.
149
150 timestamp='2018-03-08it and/or modify it
151 # under the terms of the GNU General Public License as published by
152 # t;e Free Software Foundation, either version 3 of the L;cense, or
153 # (at your o.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
154 # Attempt to guess a canonical system name.
155 # Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
156 # under the terms of the GNU General Public License as published by
157 # t;e Free Software Foundation, either version 3 of the L;cense, or
158 # (at your option) any later version.
159 #
160 # This program is distributed in the hope that it will be useful, but
161 # WITHOUT ANY WARRANTY; without even the implied warranty of
162 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
163 # General Public License for more details.
164 #
165 # You should have received a copy of the GNU General Public License
166 # along with this program; if not, see <https://www.gnu.org/licenses/>.
167 #
168 # As a special exceptionto the GNU General Public License, if you
169 # distribute this file as part of a program that contains a
170 # configuration script generated by Autoconf, you may include it under
171 # the same distribution terms that you use for the rest of that
172 # program. This Exception is an additional permission under section 7
173 # of the GNU General Public License, version 3 ("GPLv3").
174 #
175 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
176 #
177 # You can get the latest version of this script from:
178 # https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
179
180 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
181 cat <<-EOF > $dummy.c`$CC_FOR_BUILD -E $dummy.c'^LIBC' | sed 's, ,,g'`{UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}/sbin/$sysctl/usr/sbin/$sysctl
182 # Attempt to guess a canoniAttempt to g! /bin/sh
183 # Attemp#*) machine=${! /bin/sh
184 # Attemp#! /bin/sh
185 # Attempt to guess a canonical system name.
186 # Copyright 1992-2018canonical system name.
187 # Copyrig! /bin/sh
188 # Attemp#! /b{UNAME_VERSION}${UNAME_REL{machine}-${os}${release}${! /bin/sh
189 # Attemp#! /bin/sh
190 # Attempt to guess a ${! /bin/sh
191 # Attemp#! /bin/sh
192 # Attempt to guess a cekkoBSD:*:*)
193 echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}SolidBSD:*:*)
194 echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}${UNAME_RELEASE}${UNAME_MACHINE}-unk"alpha""alpha""alpha""alphaev5"A"alphaev56""alphapca56""alphapca57""alphaev6""alphaev67""alphaev68""alphaev68""alphaev68""alphaev69""alphaev7""alphaev79"${UNAME_MACHINE}-dec-osf`echo RELEASE}'' ''` /bin/sh
195 # Attempt to guess a canonical system name.
196 # Copyright 1992-2018 Free Software FouAttempt to guess a canonical system name.
197 # Copyright 1992-2018 Free Software Foundation, Inc.
198
199 timestamp='2018-03-08it and/or modify it
200 # under the terms of the GNU General Public License as published by
201 # t;e Free Software Foundation, either version 3 of the L;cense, or
202 # (at your oished by
203 # t;e Free Software Foundation, either version 3 of the L;cense, or
204 # (at your option) any later version.
205 #
206 # This program is distributed in the hope that it will be useful, but
207 # WITHOUT ANY WARRANTY; without even the implied warranty of
208 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
209 # General Public License for more details.
210 #
211 # You should have received a copy of the GNU General Public License
212 # along with this progra(C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
213 2001, 2002, 2003, 2004, 2005, 2006, 2implied warranty ofot, see <https://www.gnu.org/licenses/>.
214 #
215 # As a special exceptionto the GNU General Public License, if you
216 # distribute this file as part of a program that contains a
217 # configuration script generated by Autoconf, you may include it under
218 # the same distribution terms that you use for the rest of that
219 # program. This Exception is an additional permission under section 7
220 # of the GNU General Public License, version 3 ("GPLv3").
221 #
222 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
223 #
224 # You can get the latest version of this script from:
225 # https://git.savannah.gnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
226
227 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
228 cat <<-EOF > $dummy.c`$CC_FORHUP INT TERMneral Public License, version 3 ("GPLv3").
229 #
230 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
231 #
232 # You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
233
234 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
235 cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
236 # Attempt to guess a canonical system name.
237 # Copyright 1992-2014 Free Software Found4-11-04it and/or modify it
238 # under the terms of the GNU General Public License as published by
239 # t;e Free Software Foundation, either version 3 of the L;cense, or
240 # (at your optionHUP INT PIPE TERM03-23 the terms of the GNU General Public License as published by
241 # t;e Free Software Foundation, either version 3 of the L;cense, or
242 # (at your option) any later version.
243 #
244 # This program is distributed in the hope tha03-23 the terms of the GNU General Public License as published by
245 # t;e Free Software Foundation, either version 3 of the L;cense, or
246 # (at your option) any later version.
247 #
248 # This program is distributed in the hope that it will be useful, but
249 # WITHOUT ANY WARRANTY; without even the implied warranty of
250 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
251 # General Public License for more details.
252 #
253 # You should have received a copy of the GNU General Public License
254 # along with this program; if not, see <https://www.gnu.org/licenses/>.
255 #
256 # As a special exceptionto the GNU General Public License, if you
257 # distribute this file as part of a program that contains a
258 # configuration script generated by Autoconf, you may include it under
259 # the same distribution terms that you use for the rest of that
260 # program. This Exception is an additional permission under section 7
261 # of the GNU General Public License, version 3 ("GPLv3").
262 #
263 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
264 #
265 # You can ggnu.org/guess;hb=HEADeration mode4 Free Software Foundation, Inc.
266
267 $dummy.c$dummy.o $dummy.c{UNAME_SYSTEM}
268 cat <<-EOF > $dummy.c`$CC_FOR_BUILwith a ChangeLog entry to to guess a canonical s#! /bin/sh
269 # Attempt to guess a canonical system name.
270 # Open exit :riscos:*:*|arm t it will be useful, but
271 03-23 th 23 the terms of the GNU General Public License as published by
272 # t;e Free Software Foundation, either version 3 of the L;cense, or
273 # (at your option) any later version.
274 #
275 # This program is distributed in the hope that it will be useful, but
276 # WITHOUT ANY WARRANTY; without even the implied warranty of
277 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
278 # General Public License for more details.
279 #
280 # You should have received a copy of the GNU General Public License
281 # along with this program; if not, see <https://www.gnu.org/licenses/>.
282 #
283 # As a special exceptionto the GNU General Public License, if you
284 # distribute this file as part of a program that contains a
285 # configuration script generated by Autoconf, you may include it under
286 # the same distribution terms that you use for the rest of that
287 # program. This Exception is an additional permission under section 7
288 # of the GNU General Public License, version 3 ("GPLv3").
289 #
290 # Originally written ms of the GNU Genera532)case "${sc_kernel_bits}" in
291 32) HP_ARCH="hppa2.0n" ;;
292 esac ;;
293
294 #include <stdlib.h>
295 #include <unistd.h>
296
297 int main ()
298 {
299 #if
300 #endif
301 switch (cpu)
302 "); break;
303 2_0:
304 #if
305 switch (bits)
306 {
307
--- a/autosetup/config.sub
+++ b/autosetup/config.sub
@@ -0,0 +1 @@
1
+#! /bin/ncr3#! /bin/
--- a/autosetup/config.sub
+++ b/autosetup/config.sub
@@ -0,0 +1 @@
 
--- a/autosetup/config.sub
+++ b/autosetup/config.sub
@@ -0,0 +1 @@
1 #! /bin/ncr3#! /bin/
--- a/autosetup/find-tclsh
+++ b/autosetup/find-tclsh
@@ -0,0 +1,9 @@
1
+#!/bin/sh
2
+# Looks for a suitable tclsh or jimsh in the PATH
3
+# If not foundstrap jimsh d=`dirname "$0"`
4
+{ "$d/jimshd/${1-ac"; } 2>&imsh0"
5
+for cc in tclsh8.7; do
6
+ jimsh0-tclsh}"; } 2>/devexit 0
7
+done
8
+echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
9
+for cc in ${CC_FOR_BUILD:-PATH="$PATH:$d2>/dev/null
--- a/autosetup/find-tclsh
+++ b/autosetup/find-tclsh
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
--- a/autosetup/find-tclsh
+++ b/autosetup/find-tclsh
@@ -0,0 +1,9 @@
1 #!/bin/sh
2 # Looks for a suitable tclsh or jimsh in the PATH
3 # If not foundstrap jimsh d=`dirname "$0"`
4 { "$d/jimshd/${1-ac"; } 2>&imsh0"
5 for cc in tclsh8.7; do
6 jimsh0-tclsh}"; } 2>/devexit 0
7 done
8 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
9 for cc in ${CC_FOR_BUILD:-PATH="$PATH:$d2>/dev/null
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -0,0 +1,144 @@
1
+3cl. See http://jim.berlios.de/ */
2
+#define _GNU_SOURCEREFERENCES single source file,/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
3
+#define JIM_TCL_COMPAT_H
4
+#define TCL_LIBRARY "."
5
+#define jim_ext_stdlib
6
+#define jimregexpxec
7
+#define jim_efilexec
8
+#define jim_eexecxec
9
+#define jim_eclockxec
10
+#define jim_ee TCL_PLATFORM_OS "windows"
11
+#define TCL_PLATFORM_PLATFORM "windows"
12
+#define TCL_PLATFORM_PATH_SEPARATOR ";"
13
+#define HAVE_MKDIR_ONE_ARG
14
+#define HAVE_SYSTEM
15
+#elif defined(__MINGW32__)
16
+#defi HAVE_DIRENT_H
17
+#define HAVE_UNISTD_H
18
+#define HAVE_UMASK
19
+#include elseSEPARATOR ":"
20
+#ifdef _ATFORM_PLATFORM "unix"
21
+#define TCL_PLATFORM_PATH_SEPARMKSTEMP
22
+#define HAVE_LINK
23
+#define HAVE_SYS_TIME_H
24
+#define HAVE_DITFORM "unix"
25
+#define TCL_PLATFndif
26
+#define JIM_VERS3cl. See http://jim.berlios.de/ */
27
+#define _GNU_SOURCEREFERENCES single source file,/* /**
28
+ * UTF-8 utility functions
29
+ *
30
+ * (c) 2010 Steve Bennett <[email protected]>
31
+ *
32
+ * See LICENCE for licence details.
33
+ */
34
+
35
+/**
36
+ * Converts the given unicode codepoint (0 - 0xffff) to utf-8
37
+ * and stores the result at 'p'.
38
+ *
39
+ * Returns the number of utf-8 characters (1-3).
40
+ */
41
+intJim Tcl. See http://jim.tcl.tk/ */
42
+#define JIM_TCL_COMPAT_H
43
+#define/* No utf-8 support. 1 byte = 1 char */
44
+#define utf8_strlen(S, B) TCL_LIBRARY "."
45
+#define j
46
+#defineS, CP) (*(CP) = #define jim_eexecxec
47
+#define jim_eclockxec
48
+#define jim_ee TCL_PLATFORM_OS "windows"
49
+#define TCL_PLATFORM_PLATFORM "windows"
50
+#define TCL_PLAT/**
51
+ * Returns the length of the utf-8 sequence starting with 'c'.
52
+ *
53
+ * Returns 1-4, or -1 if this is not a valid start byte.
54
+ *
55
+ * Note that charlen=4 is not supported by the rest of the API.
56
+ */
57
+int utf8_charlen(int c);
58
+
59
+/**
60
+ * Returns the number of characters in the utf-8
61
+ * string of the given byte length.
62
+ *
63
+ * Any bytes which are not part of an valid utf-8
64
+ * sequence are treated as individual characters.
65
+ *
66
+ * The string *must* be null terminated.
67
+ *
68
+ * Does not support unicode code points > \uffff
69
+ */
70
+int utf8_strlen(bytelen);
71
+
72
+/**
73
+ * Returns the byte index of the given character in the utf-8 string.
74
+ *
75
+ * The string *must* be null terminated.
76
+ *
77
+ * This will return the byte length of a utf-8 string
78
+ * if given the char charindex);
79
+
80
+/**
81
+ * Returns the unicode codepoint corresponding to the
82
+ * utf-8 sequence 'str'.
83
+ *
84
+ * Stores the result in *uc and returns the number of bytes
85
+ * consumed.
86
+ *
87
+ * If 'str' is null terminated, then an invalid utf-8 sequence
88
+ * at the end of the string will be returned as individual bytes.
89
+ *
90
+ * If it is not null terminated, the length *must* be checked first.
91
+ *
92
+ * Does not support unicode c*uc);
93
+
94
+/**
95
+ * Returns the number of bytes before 'str' that the previous
96
+ * utf-8 character sequence starts (which may be the middle of a sequence).
97
+ *
98
+ * Looks back at most 'len' bytes backwards, which must be > 0.
99
+ * If no start char is found, returns -len
100
+ */
101
+int utf8_prev_len(
102
+/**
103
+ * Returns the upper-case variant of the given unicode codepoint.
104
+ *
105
+ * Does not support unicode code points > \uffff
106
+ */
107
+int utf8_upper(int uc);
108
+
109
+/**
110
+ * Returns the lower-case variant of the given unicode codepoint.
111
+ *
112
+ * NOTE: Use utf8_upper() in preference for case-insensitive matching.
113
+ *
114
+ * Does not support unicode code points > \uffff
115
+ */
116
+int utf8_lower(int uc);
117
+
118
+#endif
119
+
120
+#endif
121
+/* Jim - A small embeddable Tcl interpreter
122
+ *
123
+ * Copyright 2005 Salvatore Sanfilippo <[email protected]>
124
+ * Copyright 2005 Clemens Hintze <[email protected]>
125
+ * Copyright 2005 patthoyts - Pat Thoyts <[email protected]>
126
+ * Copyright 2008 oharboe - �yvind Harboe - [email protected]
127
+ * Copyright 2008 Andrew Lunn <[email protected]>
128
+ * Copyright 2008 Duane Ellis <[email protected]>
129
+ * Copyright 2008 Uwe Klein <[email protected]>
130
+ *
131
+ * Redistribution and use in source and binary forms, with or without
132
+ * modification, are permitted provided that the following conditions
133
+ * are met:
134
+ *
135
+ * 1. Redistributions of source code must retain the above copyright
136
+ * notice, this list of conditions and the following disclaimer.
137
+ * 2. Redistributions in binary form must reproduce the above
138
+ * copyright notice, this list of conditions and the following
139
+ * disclaimer in the documentation and/or other materials
140
+ * provided with the distribution.
141
+ *
142
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
143
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
144
+ * THE IMPLIED WARRANTIES OF MERCHANTABILI
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -0,0 +1,144 @@
1 3cl. See http://jim.berlios.de/ */
2 #define _GNU_SOURCEREFERENCES single source file,/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */
3 #define JIM_TCL_COMPAT_H
4 #define TCL_LIBRARY "."
5 #define jim_ext_stdlib
6 #define jimregexpxec
7 #define jim_efilexec
8 #define jim_eexecxec
9 #define jim_eclockxec
10 #define jim_ee TCL_PLATFORM_OS "windows"
11 #define TCL_PLATFORM_PLATFORM "windows"
12 #define TCL_PLATFORM_PATH_SEPARATOR ";"
13 #define HAVE_MKDIR_ONE_ARG
14 #define HAVE_SYSTEM
15 #elif defined(__MINGW32__)
16 #defi HAVE_DIRENT_H
17 #define HAVE_UNISTD_H
18 #define HAVE_UMASK
19 #include elseSEPARATOR ":"
20 #ifdef _ATFORM_PLATFORM "unix"
21 #define TCL_PLATFORM_PATH_SEPARMKSTEMP
22 #define HAVE_LINK
23 #define HAVE_SYS_TIME_H
24 #define HAVE_DITFORM "unix"
25 #define TCL_PLATFndif
26 #define JIM_VERS3cl. See http://jim.berlios.de/ */
27 #define _GNU_SOURCEREFERENCES single source file,/* /**
28 * UTF-8 utility functions
29 *
30 * (c) 2010 Steve Bennett <[email protected]>
31 *
32 * See LICENCE for licence details.
33 */
34
35 /**
36 * Converts the given unicode codepoint (0 - 0xffff) to utf-8
37 * and stores the result at 'p'.
38 *
39 * Returns the number of utf-8 characters (1-3).
40 */
41 intJim Tcl. See http://jim.tcl.tk/ */
42 #define JIM_TCL_COMPAT_H
43 #define/* No utf-8 support. 1 byte = 1 char */
44 #define utf8_strlen(S, B) TCL_LIBRARY "."
45 #define j
46 #defineS, CP) (*(CP) = #define jim_eexecxec
47 #define jim_eclockxec
48 #define jim_ee TCL_PLATFORM_OS "windows"
49 #define TCL_PLATFORM_PLATFORM "windows"
50 #define TCL_PLAT/**
51 * Returns the length of the utf-8 sequence starting with 'c'.
52 *
53 * Returns 1-4, or -1 if this is not a valid start byte.
54 *
55 * Note that charlen=4 is not supported by the rest of the API.
56 */
57 int utf8_charlen(int c);
58
59 /**
60 * Returns the number of characters in the utf-8
61 * string of the given byte length.
62 *
63 * Any bytes which are not part of an valid utf-8
64 * sequence are treated as individual characters.
65 *
66 * The string *must* be null terminated.
67 *
68 * Does not support unicode code points > \uffff
69 */
70 int utf8_strlen(bytelen);
71
72 /**
73 * Returns the byte index of the given character in the utf-8 string.
74 *
75 * The string *must* be null terminated.
76 *
77 * This will return the byte length of a utf-8 string
78 * if given the char charindex);
79
80 /**
81 * Returns the unicode codepoint corresponding to the
82 * utf-8 sequence 'str'.
83 *
84 * Stores the result in *uc and returns the number of bytes
85 * consumed.
86 *
87 * If 'str' is null terminated, then an invalid utf-8 sequence
88 * at the end of the string will be returned as individual bytes.
89 *
90 * If it is not null terminated, the length *must* be checked first.
91 *
92 * Does not support unicode c*uc);
93
94 /**
95 * Returns the number of bytes before 'str' that the previous
96 * utf-8 character sequence starts (which may be the middle of a sequence).
97 *
98 * Looks back at most 'len' bytes backwards, which must be > 0.
99 * If no start char is found, returns -len
100 */
101 int utf8_prev_len(
102 /**
103 * Returns the upper-case variant of the given unicode codepoint.
104 *
105 * Does not support unicode code points > \uffff
106 */
107 int utf8_upper(int uc);
108
109 /**
110 * Returns the lower-case variant of the given unicode codepoint.
111 *
112 * NOTE: Use utf8_upper() in preference for case-insensitive matching.
113 *
114 * Does not support unicode code points > \uffff
115 */
116 int utf8_lower(int uc);
117
118 #endif
119
120 #endif
121 /* Jim - A small embeddable Tcl interpreter
122 *
123 * Copyright 2005 Salvatore Sanfilippo <[email protected]>
124 * Copyright 2005 Clemens Hintze <[email protected]>
125 * Copyright 2005 patthoyts - Pat Thoyts <[email protected]>
126 * Copyright 2008 oharboe - �yvind Harboe - [email protected]
127 * Copyright 2008 Andrew Lunn <[email protected]>
128 * Copyright 2008 Duane Ellis <[email protected]>
129 * Copyright 2008 Uwe Klein <[email protected]>
130 *
131 * Redistribution and use in source and binary forms, with or without
132 * modification, are permitted provided that the following conditions
133 * are met:
134 *
135 * 1. Redistributions of source code must retain the above copyright
136 * notice, this list of conditions and the following disclaimer.
137 * 2. Redistributions in binary form must reproduce the above
138 * copyright notice, this list of conditions and the following
139 * disclaimer in the documentation and/or other materials
140 * provided with the distribution.
141 *
142 * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
143 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
144 * THE IMPLIED WARRANTIES OF MERCHANTABILI
--- a/autosetup/local.tcl
+++ b/autosetup/local.tcl
@@ -0,0 +1,2 @@
1
+# For this project, d
2
+set useropts(nopager)tosetup(optdefault) nopager 1
--- a/autosetup/local.tcl
+++ b/autosetup/local.tcl
@@ -0,0 +1,2 @@
 
 
--- a/autosetup/local.tcl
+++ b/autosetup/local.tcl
@@ -0,0 +1,2 @@
1 # For this project, d
2 set useropts(nopager)tosetup(optdefault) nopager 1
--- a/autosetup/system.tcl
+++ b/autosetup/system.tcl
@@ -0,0 +1,80 @@
1
+# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2
+# All rights reserved
3
+
4
+# @synopsis:
5
+#
6
+# This module supports common system interroga--host, --build, --prefix, and setting srcdir, builddir, and EXEXT.
7
+#
8
+# It naming convention, where searchisys/type.h defines HAVE_SYS_TYPES_H
9
+#
10
+# It defines the fol--prefix unless overridden by the module-optionsation and options
11
+# such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
12
+#
13
+# It also support the "feature" naming convention, where searching
14
+# for a feature such as 'sys/type => ines the followins to '$defaultprefix overridden by the user:
15
+#
16
+## datadir
17
+## sysconfdir
18
+## sharedstatedir
19
+## localstatedir
20
+## infodir
21
+## mandir
22
+## includedir
23
+#
24
+# If '--prefix' is not /usr/localaults to '/usr/local' unless 'options-defaults { prefix ... }'prefix ... }' #
25
+ program-transform-name:
26
+}
27
+
28
+# @check-feature name { script }
29
+#
30
+# defines feature '$nReturns 1 if exists, or 0 if not
31
+#ode} {
32
+ msg-checking "Checking for $name..."
33
+ set r [uplevel 1 $code
34
+ define-feature $name $r
35
+ if {$r} {
36
+ msg-result "ok"
37
+ } else {
38
+ msg-result "not found"
39
+ }
40
+ return $r
41
+}
42
+
43
+# @have-feature name ?default=0?
44
+#
45
+# Returns the value of feature '$name' if defined,the feature if de
46
+# is translated thehave-feature {name {defathe 0}. Use @top_sr# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
47
+# All rights reserved
48
+
49
+# @synopsis:
50
+#
51
+# This module supports common system interroga--host, --build, --prefix, and setting srcdir, builddir, and EXEXT.
52
+#
53
+# It naming convention, where searchisys/type.h defines HAVE_SYS_TYPES_H
54
+#
55
+# It defines the fol--prefix unless overridden by the module-optionsation and options
56
+# such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
57
+#
58
+# It also support the "feature" naming convention, where searching
59
+# for a feature such as 'sys/type => ines the followins to '$defaultprefix overridden by the user:
60
+#
61
+## datadir
62
+## sysconfdir
63
+## sharedstatedir
64
+## localstatedir
65
+## infodir
66
+## mandir
67
+## includedir
68
+#
69
+# If '--prefix' is not /usr/localaults to '/usr/local' unless 'options-defaults { prefix ... }'prefix ... }' #
70
+ program-transform-name:
71
+}
72
+
73
+# @check-feature set prefixdefine[get-env exec-prefix \${prefix}]]\${exec_prefix}/bin
74
+ sbindir \${exec_prefix}/sbin
75
+ libexecdir \${exec_prefix}/libexec
76
+ libdir \${exec_prefix}/lib
77
+ datadir \${prefix}/share
78
+ sysconfdir \${prefix}/etc
79
+ sharedstatedir \${prefix}\${prefix}/var
80
+ infodir \${prefix}\${prefix}/share Copyright (c) ht (c) 2010 WorkWare Sys
--- a/autosetup/system.tcl
+++ b/autosetup/system.tcl
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/system.tcl
+++ b/autosetup/system.tcl
@@ -0,0 +1,80 @@
1 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2 # All rights reserved
3
4 # @synopsis:
5 #
6 # This module supports common system interroga--host, --build, --prefix, and setting srcdir, builddir, and EXEXT.
7 #
8 # It naming convention, where searchisys/type.h defines HAVE_SYS_TYPES_H
9 #
10 # It defines the fol--prefix unless overridden by the module-optionsation and options
11 # such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
12 #
13 # It also support the "feature" naming convention, where searching
14 # for a feature such as 'sys/type => ines the followins to '$defaultprefix overridden by the user:
15 #
16 ## datadir
17 ## sysconfdir
18 ## sharedstatedir
19 ## localstatedir
20 ## infodir
21 ## mandir
22 ## includedir
23 #
24 # If '--prefix' is not /usr/localaults to '/usr/local' unless 'options-defaults { prefix ... }'prefix ... }' #
25 program-transform-name:
26 }
27
28 # @check-feature name { script }
29 #
30 # defines feature '$nReturns 1 if exists, or 0 if not
31 #ode} {
32 msg-checking "Checking for $name..."
33 set r [uplevel 1 $code
34 define-feature $name $r
35 if {$r} {
36 msg-result "ok"
37 } else {
38 msg-result "not found"
39 }
40 return $r
41 }
42
43 # @have-feature name ?default=0?
44 #
45 # Returns the value of feature '$name' if defined,the feature if de
46 # is translated thehave-feature {name {defathe 0}. Use @top_sr# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
47 # All rights reserved
48
49 # @synopsis:
50 #
51 # This module supports common system interroga--host, --build, --prefix, and setting srcdir, builddir, and EXEXT.
52 #
53 # It naming convention, where searchisys/type.h defines HAVE_SYS_TYPES_H
54 #
55 # It defines the fol--prefix unless overridden by the module-optionsation and options
56 # such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
57 #
58 # It also support the "feature" naming convention, where searching
59 # for a feature such as 'sys/type => ines the followins to '$defaultprefix overridden by the user:
60 #
61 ## datadir
62 ## sysconfdir
63 ## sharedstatedir
64 ## localstatedir
65 ## infodir
66 ## mandir
67 ## includedir
68 #
69 # If '--prefix' is not /usr/localaults to '/usr/local' unless 'options-defaults { prefix ... }'prefix ... }' #
70 program-transform-name:
71 }
72
73 # @check-feature set prefixdefine[get-env exec-prefix \${prefix}]]\${exec_prefix}/bin
74 sbindir \${exec_prefix}/sbin
75 libexecdir \${exec_prefix}/libexec
76 libdir \${exec_prefix}/lib
77 datadir \${prefix}/share
78 sysconfdir \${prefix}/etc
79 sharedstatedir \${prefix}\${prefix}/var
80 infodir \${prefix}\${prefix}/share Copyright (c) ht (c) 2010 WorkWare Sys
--- a/autosetup/test-tclsh
+++ b/autosetup/test-tclsh
@@ -0,0 +1,21 @@
1
+# A small Tcl script to verify that the chosen
2
+# interpreter works. Sometimes we might e.g. pick up
3
+# an interpreter for a different arch.
4
+# Outputs the full path to the interpreter
5
+
6
+if {[catch {info version} version] == 0} {
7
+ # This is Jim Tcl
8
+ if {$version >= 0.70} {
9
+ # Ensure that rege
10
+ # Older versions of jimsh mayinfo patchlevel]]} {
11
+ puts [info nameofexecutable]
12
+ exit 0
13
+ }
14
+}
15
+exit 1
16
+puts [file join [p]
17
+ exit 0
18
+ }
19
+} elseif {[catch {info tclversion} version] == 0} {
20
+ if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
21
+ puts [info nameofexecut
--- a/autosetup/test-tclsh
+++ b/autosetup/test-tclsh
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/autosetup/test-tclsh
+++ b/autosetup/test-tclsh
@@ -0,0 +1,21 @@
1 # A small Tcl script to verify that the chosen
2 # interpreter works. Sometimes we might e.g. pick up
3 # an interpreter for a different arch.
4 # Outputs the full path to the interpreter
5
6 if {[catch {info version} version] == 0} {
7 # This is Jim Tcl
8 if {$version >= 0.70} {
9 # Ensure that rege
10 # Older versions of jimsh mayinfo patchlevel]]} {
11 puts [info nameofexecutable]
12 exit 0
13 }
14 }
15 exit 1
16 puts [file join [p]
17 exit 0
18 }
19 } elseif {[catch {info tclversion} version] == 0} {
20 if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
21 puts [info nameofexecut
+3
--- a/configure
+++ b/configure
@@ -0,0 +1,3 @@
1
+#!/bin/sh
2
+dir=autosetup"
3
+# exec "`$dir/find-tcl
--- a/configure
+++ b/configure
@@ -0,0 +1,3 @@
 
 
 
--- a/configure
+++ b/configure
@@ -0,0 +1,3 @@
1 #!/bin/sh
2 dir=autosetup"
3 # exec "`$dir/find-tcl
+74 -21
--- src/add.c
+++ src/add.c
@@ -92,66 +92,76 @@
9292
**
9393
** Omit any file whose name is pOmit.
9494
*/
9595
static int add_one_file(
9696
const char *zPath, /* Tree-name of file to add. */
97
- int vid /* Add to this VFILE */
97
+ int vid, /* Add to this VFILE */
98
+ int caseSensitive /* True if filenames are case sensitive */
9899
){
100
+ const char *zCollate = caseSensitive ? "binary" : "nocase";
99101
if( !file_is_simple_pathname(zPath) ){
100102
fossil_fatal("filename contains illegal characters: %s", zPath);
101103
}
102
-#if defined(_WIN32)
103104
if( db_exists("SELECT 1 FROM vfile"
104
- " WHERE pathname=%Q COLLATE nocase", zPath) ){
105
+ " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
105106
db_multi_exec("UPDATE vfile SET deleted=0"
106
- " WHERE pathname=%Q COLLATE nocase", zPath);
107
- }
108
-#else
109
- if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
110
- db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
111
- }
112
-#endif
113
- else{
107
+ " WHERE pathname=%Q COLLATE %s", zPath, zCollate);
108
+ }else{
114109
char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
115110
db_multi_exec(
116111
"INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
117112
"VALUES(%d,0,0,0,%Q,%d)",
118113
vid, zPath, file_isexe(zFullname));
119114
fossil_free(zFullname);
120115
}
121
- fossil_print("ADDED %s\n", zPath);
122
- return 1;
116
+ if( db_changes() ){
117
+ fossil_print("ADDED %s\n", zPath);
118
+ return 1;
119
+ }else{
120
+ fossil_print("SKIP %s\n", zPath);
121
+ return 0;
122
+ }
123123
}
124124
125125
/*
126126
** Add all files in the sfile temp table.
127127
**
128128
** Automatically exclude the repository file.
129129
*/
130
-static int add_files_in_sfile(int vid){
130
+static int add_files_in_sfile(int vid, int caseSensitive){
131131
const char *zRepo; /* Name of the repository database file */
132132
int nAdd = 0; /* Number of files added */
133133
int i; /* Loop counter */
134134
const char *zReserved; /* Name of a reserved file */
135135
Blob repoName; /* Treename of the repository */
136136
Stmt loop; /* SQL to loop over all files to add */
137
+ int (*xCmp)(const char*,const char*);
137138
138139
if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
139140
blob_zero(&repoName);
140141
zRepo = "";
141142
}else{
142143
zRepo = blob_str(&repoName);
144
+ }
145
+ if( caseSensitive ){
146
+ xCmp = fossil_strcmp;
147
+ }else{
148
+ xCmp = fossil_stricmp;
149
+ db_multi_exec(
150
+ "CREATE INDEX IF NOT EXISTS vfile_nocase"
151
+ " ON vfile(pathname COLLATE nocase)"
152
+ );
143153
}
144154
db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
145155
while( db_step(&loop)==SQLITE_ROW ){
146156
const char *zToAdd = db_column_text(&loop, 0);
147157
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
148158
for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
149
- if( fossil_strcmp(zToAdd, zReserved)==0 ) break;
159
+ if( xCmp(zToAdd, zReserved)==0 ) break;
150160
}
151161
if( zReserved ) continue;
152
- nAdd += add_one_file(zToAdd, vid);
162
+ nAdd += add_one_file(zToAdd, vid, caseSensitive);
153163
}
154164
db_finalize(&loop);
155165
blob_reset(&repoName);
156166
return nAdd;
157167
}
@@ -180,14 +190,17 @@
180190
int i; /* Loop counter */
181191
int vid; /* Currently checked out version */
182192
int nRoot; /* Full path characters in g.zLocalRoot */
183193
const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
184194
Glob *pIgnore; /* Ignore everything matching this glob pattern */
195
+ int caseSensitive; /* True if filenames are case sensitive */
185196
186197
zIgnoreFlag = find_option("ignore",0,1);
187198
includeDotFiles = find_option("dotfiles",0,0)!=0;
199
+ capture_case_sensitive_option();
188200
db_must_be_within_tree();
201
+ caseSensitive = filenames_are_case_sensitive();
189202
if( zIgnoreFlag==0 ){
190203
zIgnoreFlag = db_get("ignore-glob", 0);
191204
}
192205
vid = db_lget_int("checkout",0);
193206
if( vid==0 ){
@@ -229,11 +242,11 @@
229242
}
230243
blob_reset(&fullName);
231244
}
232245
glob_free(pIgnore);
233246
234
- add_files_in_sfile(vid);
247
+ add_files_in_sfile(vid, caseSensitive);
235248
db_end_transaction(0);
236249
}
237250
238251
/*
239252
** COMMAND: rm
@@ -289,10 +302,48 @@
289302
"UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
290303
"DELETE FROM vfile WHERE rid=0 AND deleted;"
291304
);
292305
db_end_transaction(0);
293306
}
307
+
308
+/*
309
+** Capture the command-line --case-sensitive option.
310
+*/
311
+static const char *zCaseSensitive = 0;
312
+void capture_case_sensitive_option(void){
313
+ if( zCaseSensitive==0 ){
314
+ zCaseSensitive = find_option("case-sensitive",0,1);
315
+ }
316
+}
317
+
318
+/*
319
+** This routine determines if files should be case-sensitive or not.
320
+** In other words, this routine determines if two filenames that
321
+** differ only in case should be considered the same name or not.
322
+**
323
+** The case-sensitive setting determines the default value. If
324
+** the case-sensitive setting is undefined, then case sensitivity
325
+** defaults on for Mac and Windows and off for all other unix.
326
+**
327
+** The --case-sensitive BOOLEAN command-line option overrides any
328
+** setting.
329
+*/
330
+int filenames_are_case_sensitive(void){
331
+ int caseSensitive;
332
+
333
+ if( zCaseSensitive ){
334
+ caseSensitive = is_truth(zCaseSensitive);
335
+ }else{
336
+#if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__)
337
+ caseSensitive = 1;
338
+#else
339
+ caseSensitive = 0;
340
+#endif
341
+ caseSensitive = db_get_boolean("case-sensitive",caseSensitive);
342
+ }
343
+ return caseSensitive;
344
+}
294345
295346
/*
296347
** COMMAND: addremove
297348
**
298349
** Usage: %fossil addremove ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
@@ -319,27 +370,29 @@
319370
**
320371
** The --test option shows what would happen without actually doing anything.
321372
**
322373
** This command can be used to track third party software.
323374
**
324
-**
325375
** SUMMARY: fossil addremove
326
-** Options: ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
376
+** Options: ?--dotfiles? ?--ignore GLOB? ?--test? ?--case-sensitive BOOL?
327377
*/
328
-void import_cmd(void){
378
+void addremove_cmd(void){
329379
Blob path;
330380
const char *zIgnoreFlag = find_option("ignore",0,1);
331381
int allFlag = find_option("dotfiles",0,0)!=0;
332382
int isTest = find_option("test",0,0)!=0;
383
+ int caseSensitive;
333384
int n;
334385
Stmt q;
335386
int vid;
336387
int nAdd = 0;
337388
int nDelete = 0;
338389
Glob *pIgnore;
339390
391
+ capture_case_sensitive_option();
340392
db_must_be_within_tree();
393
+ caseSensitive = filenames_are_case_sensitive();
341394
if( zIgnoreFlag==0 ){
342395
zIgnoreFlag = db_get("ignore-glob", 0);
343396
}
344397
vid = db_lget_int("checkout",0);
345398
if( vid==0 ){
@@ -358,11 +411,11 @@
358411
blob_init(&path, g.zLocalRoot, n-1);
359412
/* now we read the complete file structure into a temp table */
360413
pIgnore = glob_create(zIgnoreFlag);
361414
vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
362415
glob_free(pIgnore);
363
- nAdd = add_files_in_sfile(vid);
416
+ nAdd = add_files_in_sfile(vid, caseSensitive);
364417
365418
/* step 2: search for missing files */
366419
db_prepare(&q,
367420
"SELECT pathname, %Q || pathname, deleted FROM vfile"
368421
" WHERE NOT deleted"
369422
--- src/add.c
+++ src/add.c
@@ -92,66 +92,76 @@
92 **
93 ** Omit any file whose name is pOmit.
94 */
95 static int add_one_file(
96 const char *zPath, /* Tree-name of file to add. */
97 int vid /* Add to this VFILE */
 
98 ){
 
99 if( !file_is_simple_pathname(zPath) ){
100 fossil_fatal("filename contains illegal characters: %s", zPath);
101 }
102 #if defined(_WIN32)
103 if( db_exists("SELECT 1 FROM vfile"
104 " WHERE pathname=%Q COLLATE nocase", zPath) ){
105 db_multi_exec("UPDATE vfile SET deleted=0"
106 " WHERE pathname=%Q COLLATE nocase", zPath);
107 }
108 #else
109 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
110 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
111 }
112 #endif
113 else{
114 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
115 db_multi_exec(
116 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
117 "VALUES(%d,0,0,0,%Q,%d)",
118 vid, zPath, file_isexe(zFullname));
119 fossil_free(zFullname);
120 }
121 fossil_print("ADDED %s\n", zPath);
122 return 1;
 
 
 
 
 
123 }
124
125 /*
126 ** Add all files in the sfile temp table.
127 **
128 ** Automatically exclude the repository file.
129 */
130 static int add_files_in_sfile(int vid){
131 const char *zRepo; /* Name of the repository database file */
132 int nAdd = 0; /* Number of files added */
133 int i; /* Loop counter */
134 const char *zReserved; /* Name of a reserved file */
135 Blob repoName; /* Treename of the repository */
136 Stmt loop; /* SQL to loop over all files to add */
 
137
138 if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
139 blob_zero(&repoName);
140 zRepo = "";
141 }else{
142 zRepo = blob_str(&repoName);
 
 
 
 
 
 
 
 
 
143 }
144 db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
145 while( db_step(&loop)==SQLITE_ROW ){
146 const char *zToAdd = db_column_text(&loop, 0);
147 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
148 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
149 if( fossil_strcmp(zToAdd, zReserved)==0 ) break;
150 }
151 if( zReserved ) continue;
152 nAdd += add_one_file(zToAdd, vid);
153 }
154 db_finalize(&loop);
155 blob_reset(&repoName);
156 return nAdd;
157 }
@@ -180,14 +190,17 @@
180 int i; /* Loop counter */
181 int vid; /* Currently checked out version */
182 int nRoot; /* Full path characters in g.zLocalRoot */
183 const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
184 Glob *pIgnore; /* Ignore everything matching this glob pattern */
 
185
186 zIgnoreFlag = find_option("ignore",0,1);
187 includeDotFiles = find_option("dotfiles",0,0)!=0;
 
188 db_must_be_within_tree();
 
189 if( zIgnoreFlag==0 ){
190 zIgnoreFlag = db_get("ignore-glob", 0);
191 }
192 vid = db_lget_int("checkout",0);
193 if( vid==0 ){
@@ -229,11 +242,11 @@
229 }
230 blob_reset(&fullName);
231 }
232 glob_free(pIgnore);
233
234 add_files_in_sfile(vid);
235 db_end_transaction(0);
236 }
237
238 /*
239 ** COMMAND: rm
@@ -289,10 +302,48 @@
289 "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
290 "DELETE FROM vfile WHERE rid=0 AND deleted;"
291 );
292 db_end_transaction(0);
293 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
295 /*
296 ** COMMAND: addremove
297 **
298 ** Usage: %fossil addremove ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
@@ -319,27 +370,29 @@
319 **
320 ** The --test option shows what would happen without actually doing anything.
321 **
322 ** This command can be used to track third party software.
323 **
324 **
325 ** SUMMARY: fossil addremove
326 ** Options: ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
327 */
328 void import_cmd(void){
329 Blob path;
330 const char *zIgnoreFlag = find_option("ignore",0,1);
331 int allFlag = find_option("dotfiles",0,0)!=0;
332 int isTest = find_option("test",0,0)!=0;
 
333 int n;
334 Stmt q;
335 int vid;
336 int nAdd = 0;
337 int nDelete = 0;
338 Glob *pIgnore;
339
 
340 db_must_be_within_tree();
 
341 if( zIgnoreFlag==0 ){
342 zIgnoreFlag = db_get("ignore-glob", 0);
343 }
344 vid = db_lget_int("checkout",0);
345 if( vid==0 ){
@@ -358,11 +411,11 @@
358 blob_init(&path, g.zLocalRoot, n-1);
359 /* now we read the complete file structure into a temp table */
360 pIgnore = glob_create(zIgnoreFlag);
361 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
362 glob_free(pIgnore);
363 nAdd = add_files_in_sfile(vid);
364
365 /* step 2: search for missing files */
366 db_prepare(&q,
367 "SELECT pathname, %Q || pathname, deleted FROM vfile"
368 " WHERE NOT deleted"
369
--- src/add.c
+++ src/add.c
@@ -92,66 +92,76 @@
92 **
93 ** Omit any file whose name is pOmit.
94 */
95 static int add_one_file(
96 const char *zPath, /* Tree-name of file to add. */
97 int vid, /* Add to this VFILE */
98 int caseSensitive /* True if filenames are case sensitive */
99 ){
100 const char *zCollate = caseSensitive ? "binary" : "nocase";
101 if( !file_is_simple_pathname(zPath) ){
102 fossil_fatal("filename contains illegal characters: %s", zPath);
103 }
 
104 if( db_exists("SELECT 1 FROM vfile"
105 " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
106 db_multi_exec("UPDATE vfile SET deleted=0"
107 " WHERE pathname=%Q COLLATE %s", zPath, zCollate);
108 }else{
 
 
 
 
 
 
109 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
110 db_multi_exec(
111 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
112 "VALUES(%d,0,0,0,%Q,%d)",
113 vid, zPath, file_isexe(zFullname));
114 fossil_free(zFullname);
115 }
116 if( db_changes() ){
117 fossil_print("ADDED %s\n", zPath);
118 return 1;
119 }else{
120 fossil_print("SKIP %s\n", zPath);
121 return 0;
122 }
123 }
124
125 /*
126 ** Add all files in the sfile temp table.
127 **
128 ** Automatically exclude the repository file.
129 */
130 static int add_files_in_sfile(int vid, int caseSensitive){
131 const char *zRepo; /* Name of the repository database file */
132 int nAdd = 0; /* Number of files added */
133 int i; /* Loop counter */
134 const char *zReserved; /* Name of a reserved file */
135 Blob repoName; /* Treename of the repository */
136 Stmt loop; /* SQL to loop over all files to add */
137 int (*xCmp)(const char*,const char*);
138
139 if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
140 blob_zero(&repoName);
141 zRepo = "";
142 }else{
143 zRepo = blob_str(&repoName);
144 }
145 if( caseSensitive ){
146 xCmp = fossil_strcmp;
147 }else{
148 xCmp = fossil_stricmp;
149 db_multi_exec(
150 "CREATE INDEX IF NOT EXISTS vfile_nocase"
151 " ON vfile(pathname COLLATE nocase)"
152 );
153 }
154 db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
155 while( db_step(&loop)==SQLITE_ROW ){
156 const char *zToAdd = db_column_text(&loop, 0);
157 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
158 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
159 if( xCmp(zToAdd, zReserved)==0 ) break;
160 }
161 if( zReserved ) continue;
162 nAdd += add_one_file(zToAdd, vid, caseSensitive);
163 }
164 db_finalize(&loop);
165 blob_reset(&repoName);
166 return nAdd;
167 }
@@ -180,14 +190,17 @@
190 int i; /* Loop counter */
191 int vid; /* Currently checked out version */
192 int nRoot; /* Full path characters in g.zLocalRoot */
193 const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
194 Glob *pIgnore; /* Ignore everything matching this glob pattern */
195 int caseSensitive; /* True if filenames are case sensitive */
196
197 zIgnoreFlag = find_option("ignore",0,1);
198 includeDotFiles = find_option("dotfiles",0,0)!=0;
199 capture_case_sensitive_option();
200 db_must_be_within_tree();
201 caseSensitive = filenames_are_case_sensitive();
202 if( zIgnoreFlag==0 ){
203 zIgnoreFlag = db_get("ignore-glob", 0);
204 }
205 vid = db_lget_int("checkout",0);
206 if( vid==0 ){
@@ -229,11 +242,11 @@
242 }
243 blob_reset(&fullName);
244 }
245 glob_free(pIgnore);
246
247 add_files_in_sfile(vid, caseSensitive);
248 db_end_transaction(0);
249 }
250
251 /*
252 ** COMMAND: rm
@@ -289,10 +302,48 @@
302 "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
303 "DELETE FROM vfile WHERE rid=0 AND deleted;"
304 );
305 db_end_transaction(0);
306 }
307
308 /*
309 ** Capture the command-line --case-sensitive option.
310 */
311 static const char *zCaseSensitive = 0;
312 void capture_case_sensitive_option(void){
313 if( zCaseSensitive==0 ){
314 zCaseSensitive = find_option("case-sensitive",0,1);
315 }
316 }
317
318 /*
319 ** This routine determines if files should be case-sensitive or not.
320 ** In other words, this routine determines if two filenames that
321 ** differ only in case should be considered the same name or not.
322 **
323 ** The case-sensitive setting determines the default value. If
324 ** the case-sensitive setting is undefined, then case sensitivity
325 ** defaults on for Mac and Windows and off for all other unix.
326 **
327 ** The --case-sensitive BOOLEAN command-line option overrides any
328 ** setting.
329 */
330 int filenames_are_case_sensitive(void){
331 int caseSensitive;
332
333 if( zCaseSensitive ){
334 caseSensitive = is_truth(zCaseSensitive);
335 }else{
336 #if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__)
337 caseSensitive = 1;
338 #else
339 caseSensitive = 0;
340 #endif
341 caseSensitive = db_get_boolean("case-sensitive",caseSensitive);
342 }
343 return caseSensitive;
344 }
345
346 /*
347 ** COMMAND: addremove
348 **
349 ** Usage: %fossil addremove ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
@@ -319,27 +370,29 @@
370 **
371 ** The --test option shows what would happen without actually doing anything.
372 **
373 ** This command can be used to track third party software.
374 **
 
375 ** SUMMARY: fossil addremove
376 ** Options: ?--dotfiles? ?--ignore GLOB? ?--test? ?--case-sensitive BOOL?
377 */
378 void addremove_cmd(void){
379 Blob path;
380 const char *zIgnoreFlag = find_option("ignore",0,1);
381 int allFlag = find_option("dotfiles",0,0)!=0;
382 int isTest = find_option("test",0,0)!=0;
383 int caseSensitive;
384 int n;
385 Stmt q;
386 int vid;
387 int nAdd = 0;
388 int nDelete = 0;
389 Glob *pIgnore;
390
391 capture_case_sensitive_option();
392 db_must_be_within_tree();
393 caseSensitive = filenames_are_case_sensitive();
394 if( zIgnoreFlag==0 ){
395 zIgnoreFlag = db_get("ignore-glob", 0);
396 }
397 vid = db_lget_int("checkout",0);
398 if( vid==0 ){
@@ -358,11 +411,11 @@
411 blob_init(&path, g.zLocalRoot, n-1);
412 /* now we read the complete file structure into a temp table */
413 pIgnore = glob_create(zIgnoreFlag);
414 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
415 glob_free(pIgnore);
416 nAdd = add_files_in_sfile(vid, caseSensitive);
417
418 /* step 2: search for missing files */
419 db_prepare(&q,
420 "SELECT pathname, %Q || pathname, deleted FROM vfile"
421 " WHERE NOT deleted"
422
+1 -1
--- src/blob.c
+++ src/blob.c
@@ -120,11 +120,11 @@
120120
** This routine is called if a blob operation fails because we
121121
** have run out of memory.
122122
*/
123123
static void blob_panic(void){
124124
static const char zErrMsg[] = "out of memory\n";
125
- write(2, zErrMsg, sizeof(zErrMsg)-1);
125
+ fputs(zErrMsg, stderr);
126126
fossil_exit(1);
127127
}
128128
129129
/*
130130
** A reallocation function that assumes that aData came from malloc().
131131
--- src/blob.c
+++ src/blob.c
@@ -120,11 +120,11 @@
120 ** This routine is called if a blob operation fails because we
121 ** have run out of memory.
122 */
123 static void blob_panic(void){
124 static const char zErrMsg[] = "out of memory\n";
125 write(2, zErrMsg, sizeof(zErrMsg)-1);
126 fossil_exit(1);
127 }
128
129 /*
130 ** A reallocation function that assumes that aData came from malloc().
131
--- src/blob.c
+++ src/blob.c
@@ -120,11 +120,11 @@
120 ** This routine is called if a blob operation fails because we
121 ** have run out of memory.
122 */
123 static void blob_panic(void){
124 static const char zErrMsg[] = "out of memory\n";
125 fputs(zErrMsg, stderr);
126 fossil_exit(1);
127 }
128
129 /*
130 ** A reallocation function that assumes that aData came from malloc().
131
+73 -36
--- src/branch.c
+++ src/branch.c
@@ -174,12 +174,49 @@
174174
175175
/* Commit */
176176
db_end_transaction(0);
177177
178178
/* Do an autosync push, if requested */
179
- autosync(AUTOSYNC_PUSH);
179
+ if( !isPrivate ) autosync(AUTOSYNC_PUSH);
180
+}
181
+
182
+/*
183
+** Prepare a query that will list all branches.
184
+*/
185
+static void prepareBranchQuery(Stmt *pQuery, int showAll, int showClosed){
186
+ if( showClosed ){
187
+ db_prepare(pQuery,
188
+ "SELECT value FROM tagxref"
189
+ " WHERE tagid=%d AND value NOT NULL "
190
+ "EXCEPT "
191
+ "SELECT value FROM tagxref"
192
+ " WHERE tagid=%d"
193
+ " AND rid IN leaf"
194
+ " AND NOT %z"
195
+ " ORDER BY value COLLATE nocase /*sort*/",
196
+ TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
197
+ );
198
+ }else if( showAll ){
199
+ db_prepare(pQuery,
200
+ "SELECT DISTINCT value FROM tagxref"
201
+ " WHERE tagid=%d AND value NOT NULL"
202
+ " AND rid IN leaf"
203
+ " ORDER BY value COLLATE nocase /*sort*/",
204
+ TAG_BRANCH
205
+ );
206
+ }else{
207
+ db_prepare(pQuery,
208
+ "SELECT DISTINCT value FROM tagxref"
209
+ " WHERE tagid=%d AND value NOT NULL"
210
+ " AND rid IN leaf"
211
+ " AND NOT %z"
212
+ " ORDER BY value COLLATE nocase /*sort*/",
213
+ TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
214
+ );
215
+ }
180216
}
217
+
181218
182219
/*
183220
** COMMAND: branch
184221
**
185222
** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
@@ -194,11 +231,12 @@
194231
** --private option makes the branch private.
195232
**
196233
** %fossil branch list
197234
** %fossil branch ls
198235
**
199
-** List all branches
236
+** List all branches. Use --all or --closed to list all branches
237
+** or closed branches. The default is to show only open branches.
200238
**
201239
*/
202240
void branch_cmd(void){
203241
int n;
204242
const char *zCmd = "list";
@@ -212,24 +250,19 @@
212250
branch_new();
213251
}else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
214252
Stmt q;
215253
int vid;
216254
char *zCurrent = 0;
255
+ int showAll = find_option("all",0,0)!=0;
256
+ int showClosed = find_option("closed",0,0)!=0;
217257
218258
if( g.localOpen ){
219259
vid = db_lget_int("checkout", 0);
220260
zCurrent = db_text(0, "SELECT value FROM tagxref"
221261
" WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
222262
}
223
- db_prepare(&q,
224
- "SELECT DISTINCT value FROM tagxref"
225
- " WHERE tagid=%d AND value NOT NULL"
226
- " AND rid IN leaf"
227
- " AND NOT %z"
228
- " ORDER BY value /*sort*/",
229
- TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
230
- );
263
+ prepareBranchQuery(&q, showAll, showClosed);
231264
while( db_step(&q)==SQLITE_ROW ){
232265
const char *zBr = db_column_text(&q, 0);
233266
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
234267
fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
235268
}
@@ -247,21 +280,38 @@
247280
*/
248281
void brlist_page(void){
249282
Stmt q;
250283
int cnt;
251284
int showClosed = P("closed")!=0;
285
+ int showAll = P("all")!=0;
286
+ int colorTest = P("colortest")!=0;
252287
253288
login_check_credentials();
254289
if( !g.okRead ){ login_needed(); return; }
290
+ if( colorTest ){
291
+ showClosed = 0;
292
+ showAll = 1;
293
+ }
255294
256
- style_header(showClosed ? "Closed Branches" : "Open Branches");
295
+ style_header(showClosed ? "Closed Branches" :
296
+ showAll ? "All Branches" : "Open Branches");
257297
style_submenu_element("Timeline", "Timeline", "brtimeline");
258298
if( showClosed ){
299
+ style_submenu_element("All", "All", "brlist?all");
300
+ style_submenu_element("Open","Open","brlist");
301
+ }else if( showAll ){
302
+ style_submenu_element("Closed", "Closed", "brlist?closed");
259303
style_submenu_element("Open","Open","brlist");
260304
}else{
305
+ style_submenu_element("All", "All", "brlist?all");
261306
style_submenu_element("Closed","Closed","brlist?closed");
262307
}
308
+ if( !colorTest ){
309
+ style_submenu_element("Color-Test", "Color-Test", "brlist?colortest");
310
+ }else{
311
+ style_submenu_element("All", "All", "brlist?all");
312
+ }
263313
login_anonymous_available();
264314
style_sidebox_begin("Nomenclature:", "33%");
265315
@ <ol>
266316
@ <li> An <div class="sideboxDescribed"><a href="brlist">
267317
@ open branch</a></div> is a branch that has one or
@@ -275,46 +325,33 @@
275325
@ Closed branches are fixed and do not change (unless they are first
276326
@ reopened)</li>
277327
@ </ol>
278328
style_sidebox_end();
279329
330
+ prepareBranchQuery(&q, showAll, showClosed);
280331
cnt = 0;
281
- if( showClosed ){
282
- db_prepare(&q,
283
- "SELECT value FROM tagxref"
284
- " WHERE tagid=%d AND value NOT NULL "
285
- "EXCEPT "
286
- "SELECT value FROM tagxref"
287
- " WHERE tagid=%d"
288
- " AND rid IN leaf"
289
- " AND NOT %z"
290
- " ORDER BY value /*sort*/",
291
- TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
292
- );
293
- }else{
294
- db_prepare(&q,
295
- "SELECT DISTINCT value FROM tagxref"
296
- " WHERE tagid=%d AND value NOT NULL"
297
- " AND rid IN leaf"
298
- " AND NOT %z"
299
- " ORDER BY value /*sort*/",
300
- TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
301
- );
302
- }
303332
while( db_step(&q)==SQLITE_ROW ){
304333
const char *zBr = db_column_text(&q, 0);
305334
if( cnt==0 ){
306
- if( showClosed ){
335
+ if( colorTest ){
336
+ @ <h2>Default background colors for all branches:</h2>
337
+ }else if( showAll ){
338
+ @ <h2>All Branches:</h2>
339
+ }else if( showClosed ){
307340
@ <h2>Closed Branches:</h2>
308341
}else{
309342
@ <h2>Open Branches:</h2>
310343
}
311344
@ <ul>
312345
cnt++;
313346
}
314
- if( g.okHistory ){
315
- @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a></li>
347
+ if( colorTest ){
348
+ const char *zColor = hash_color(zBr);
349
+ @ <li><span style="background-color: %s(zColor)">
350
+ @ %h(zBr) &rarr; %s(zColor)</span></li>
351
+ }else if( g.okHistory ){
352
+ @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
316353
}else{
317354
@ <li><b>%h(zBr)</b></li>
318355
}
319356
}
320357
if( cnt ){
321358
--- src/branch.c
+++ src/branch.c
@@ -174,12 +174,49 @@
174
175 /* Commit */
176 db_end_transaction(0);
177
178 /* Do an autosync push, if requested */
179 autosync(AUTOSYNC_PUSH);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180 }
 
181
182 /*
183 ** COMMAND: branch
184 **
185 ** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
@@ -194,11 +231,12 @@
194 ** --private option makes the branch private.
195 **
196 ** %fossil branch list
197 ** %fossil branch ls
198 **
199 ** List all branches
 
200 **
201 */
202 void branch_cmd(void){
203 int n;
204 const char *zCmd = "list";
@@ -212,24 +250,19 @@
212 branch_new();
213 }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
214 Stmt q;
215 int vid;
216 char *zCurrent = 0;
 
 
217
218 if( g.localOpen ){
219 vid = db_lget_int("checkout", 0);
220 zCurrent = db_text(0, "SELECT value FROM tagxref"
221 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
222 }
223 db_prepare(&q,
224 "SELECT DISTINCT value FROM tagxref"
225 " WHERE tagid=%d AND value NOT NULL"
226 " AND rid IN leaf"
227 " AND NOT %z"
228 " ORDER BY value /*sort*/",
229 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
230 );
231 while( db_step(&q)==SQLITE_ROW ){
232 const char *zBr = db_column_text(&q, 0);
233 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
234 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
235 }
@@ -247,21 +280,38 @@
247 */
248 void brlist_page(void){
249 Stmt q;
250 int cnt;
251 int showClosed = P("closed")!=0;
 
 
252
253 login_check_credentials();
254 if( !g.okRead ){ login_needed(); return; }
 
 
 
 
255
256 style_header(showClosed ? "Closed Branches" : "Open Branches");
 
257 style_submenu_element("Timeline", "Timeline", "brtimeline");
258 if( showClosed ){
 
 
 
 
259 style_submenu_element("Open","Open","brlist");
260 }else{
 
261 style_submenu_element("Closed","Closed","brlist?closed");
262 }
 
 
 
 
 
263 login_anonymous_available();
264 style_sidebox_begin("Nomenclature:", "33%");
265 @ <ol>
266 @ <li> An <div class="sideboxDescribed"><a href="brlist">
267 @ open branch</a></div> is a branch that has one or
@@ -275,46 +325,33 @@
275 @ Closed branches are fixed and do not change (unless they are first
276 @ reopened)</li>
277 @ </ol>
278 style_sidebox_end();
279
 
280 cnt = 0;
281 if( showClosed ){
282 db_prepare(&q,
283 "SELECT value FROM tagxref"
284 " WHERE tagid=%d AND value NOT NULL "
285 "EXCEPT "
286 "SELECT value FROM tagxref"
287 " WHERE tagid=%d"
288 " AND rid IN leaf"
289 " AND NOT %z"
290 " ORDER BY value /*sort*/",
291 TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
292 );
293 }else{
294 db_prepare(&q,
295 "SELECT DISTINCT value FROM tagxref"
296 " WHERE tagid=%d AND value NOT NULL"
297 " AND rid IN leaf"
298 " AND NOT %z"
299 " ORDER BY value /*sort*/",
300 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
301 );
302 }
303 while( db_step(&q)==SQLITE_ROW ){
304 const char *zBr = db_column_text(&q, 0);
305 if( cnt==0 ){
306 if( showClosed ){
 
 
 
 
307 @ <h2>Closed Branches:</h2>
308 }else{
309 @ <h2>Open Branches:</h2>
310 }
311 @ <ul>
312 cnt++;
313 }
314 if( g.okHistory ){
315 @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a></li>
 
 
 
 
316 }else{
317 @ <li><b>%h(zBr)</b></li>
318 }
319 }
320 if( cnt ){
321
--- src/branch.c
+++ src/branch.c
@@ -174,12 +174,49 @@
174
175 /* Commit */
176 db_end_transaction(0);
177
178 /* Do an autosync push, if requested */
179 if( !isPrivate ) autosync(AUTOSYNC_PUSH);
180 }
181
182 /*
183 ** Prepare a query that will list all branches.
184 */
185 static void prepareBranchQuery(Stmt *pQuery, int showAll, int showClosed){
186 if( showClosed ){
187 db_prepare(pQuery,
188 "SELECT value FROM tagxref"
189 " WHERE tagid=%d AND value NOT NULL "
190 "EXCEPT "
191 "SELECT value FROM tagxref"
192 " WHERE tagid=%d"
193 " AND rid IN leaf"
194 " AND NOT %z"
195 " ORDER BY value COLLATE nocase /*sort*/",
196 TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
197 );
198 }else if( showAll ){
199 db_prepare(pQuery,
200 "SELECT DISTINCT value FROM tagxref"
201 " WHERE tagid=%d AND value NOT NULL"
202 " AND rid IN leaf"
203 " ORDER BY value COLLATE nocase /*sort*/",
204 TAG_BRANCH
205 );
206 }else{
207 db_prepare(pQuery,
208 "SELECT DISTINCT value FROM tagxref"
209 " WHERE tagid=%d AND value NOT NULL"
210 " AND rid IN leaf"
211 " AND NOT %z"
212 " ORDER BY value COLLATE nocase /*sort*/",
213 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
214 );
215 }
216 }
217
218
219 /*
220 ** COMMAND: branch
221 **
222 ** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
@@ -194,11 +231,12 @@
231 ** --private option makes the branch private.
232 **
233 ** %fossil branch list
234 ** %fossil branch ls
235 **
236 ** List all branches. Use --all or --closed to list all branches
237 ** or closed branches. The default is to show only open branches.
238 **
239 */
240 void branch_cmd(void){
241 int n;
242 const char *zCmd = "list";
@@ -212,24 +250,19 @@
250 branch_new();
251 }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
252 Stmt q;
253 int vid;
254 char *zCurrent = 0;
255 int showAll = find_option("all",0,0)!=0;
256 int showClosed = find_option("closed",0,0)!=0;
257
258 if( g.localOpen ){
259 vid = db_lget_int("checkout", 0);
260 zCurrent = db_text(0, "SELECT value FROM tagxref"
261 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
262 }
263 prepareBranchQuery(&q, showAll, showClosed);
 
 
 
 
 
 
 
264 while( db_step(&q)==SQLITE_ROW ){
265 const char *zBr = db_column_text(&q, 0);
266 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
267 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
268 }
@@ -247,21 +280,38 @@
280 */
281 void brlist_page(void){
282 Stmt q;
283 int cnt;
284 int showClosed = P("closed")!=0;
285 int showAll = P("all")!=0;
286 int colorTest = P("colortest")!=0;
287
288 login_check_credentials();
289 if( !g.okRead ){ login_needed(); return; }
290 if( colorTest ){
291 showClosed = 0;
292 showAll = 1;
293 }
294
295 style_header(showClosed ? "Closed Branches" :
296 showAll ? "All Branches" : "Open Branches");
297 style_submenu_element("Timeline", "Timeline", "brtimeline");
298 if( showClosed ){
299 style_submenu_element("All", "All", "brlist?all");
300 style_submenu_element("Open","Open","brlist");
301 }else if( showAll ){
302 style_submenu_element("Closed", "Closed", "brlist?closed");
303 style_submenu_element("Open","Open","brlist");
304 }else{
305 style_submenu_element("All", "All", "brlist?all");
306 style_submenu_element("Closed","Closed","brlist?closed");
307 }
308 if( !colorTest ){
309 style_submenu_element("Color-Test", "Color-Test", "brlist?colortest");
310 }else{
311 style_submenu_element("All", "All", "brlist?all");
312 }
313 login_anonymous_available();
314 style_sidebox_begin("Nomenclature:", "33%");
315 @ <ol>
316 @ <li> An <div class="sideboxDescribed"><a href="brlist">
317 @ open branch</a></div> is a branch that has one or
@@ -275,46 +325,33 @@
325 @ Closed branches are fixed and do not change (unless they are first
326 @ reopened)</li>
327 @ </ol>
328 style_sidebox_end();
329
330 prepareBranchQuery(&q, showAll, showClosed);
331 cnt = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332 while( db_step(&q)==SQLITE_ROW ){
333 const char *zBr = db_column_text(&q, 0);
334 if( cnt==0 ){
335 if( colorTest ){
336 @ <h2>Default background colors for all branches:</h2>
337 }else if( showAll ){
338 @ <h2>All Branches:</h2>
339 }else if( showClosed ){
340 @ <h2>Closed Branches:</h2>
341 }else{
342 @ <h2>Open Branches:</h2>
343 }
344 @ <ul>
345 cnt++;
346 }
347 if( colorTest ){
348 const char *zColor = hash_color(zBr);
349 @ <li><span style="background-color: %s(zColor)">
350 @ %h(zBr) &rarr; %s(zColor)</span></li>
351 }else if( g.okHistory ){
352 @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
353 }else{
354 @ <li><b>%h(zBr)</b></li>
355 }
356 }
357 if( cnt ){
358
+2 -2
--- src/browse.c
+++ src/browse.c
@@ -146,11 +146,11 @@
146146
/* Compute the title of the page */
147147
blob_zero(&dirname);
148148
if( zD ){
149149
blob_append(&dirname, "in directory ", -1);
150150
hyperlinked_path(zD, &dirname, zCI);
151
- zPrefix = mprintf("%h/", zD);
151
+ zPrefix = mprintf("%s/", zD);
152152
}else{
153153
blob_append(&dirname, "in the top-level directory", -1);
154154
zPrefix = "";
155155
}
156156
if( zCI ){
@@ -267,11 +267,11 @@
267267
if( zFN[0]=='/' ){
268268
zFN++;
269269
@ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
270270
}else if( zCI ){
271271
const char *zUuid = db_column_text(&q, 1);
272
- @ <li><a href="%s(g.zTop)/artifact?name=%s(zUuid)">%h(zFN)</a></li>
272
+ @ <li><a href="%s(g.zTop)/artifact/%s(zUuid)">%h(zFN)</a></li>
273273
}else{
274274
@ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
275275
@ </a></li>
276276
}
277277
}
278278
--- src/browse.c
+++ src/browse.c
@@ -146,11 +146,11 @@
146 /* Compute the title of the page */
147 blob_zero(&dirname);
148 if( zD ){
149 blob_append(&dirname, "in directory ", -1);
150 hyperlinked_path(zD, &dirname, zCI);
151 zPrefix = mprintf("%h/", zD);
152 }else{
153 blob_append(&dirname, "in the top-level directory", -1);
154 zPrefix = "";
155 }
156 if( zCI ){
@@ -267,11 +267,11 @@
267 if( zFN[0]=='/' ){
268 zFN++;
269 @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
270 }else if( zCI ){
271 const char *zUuid = db_column_text(&q, 1);
272 @ <li><a href="%s(g.zTop)/artifact?name=%s(zUuid)">%h(zFN)</a></li>
273 }else{
274 @ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
275 @ </a></li>
276 }
277 }
278
--- src/browse.c
+++ src/browse.c
@@ -146,11 +146,11 @@
146 /* Compute the title of the page */
147 blob_zero(&dirname);
148 if( zD ){
149 blob_append(&dirname, "in directory ", -1);
150 hyperlinked_path(zD, &dirname, zCI);
151 zPrefix = mprintf("%s/", zD);
152 }else{
153 blob_append(&dirname, "in the top-level directory", -1);
154 zPrefix = "";
155 }
156 if( zCI ){
@@ -267,11 +267,11 @@
267 if( zFN[0]=='/' ){
268 zFN++;
269 @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
270 }else if( zCI ){
271 const char *zUuid = db_column_text(&q, 1);
272 @ <li><a href="%s(g.zTop)/artifact/%s(zUuid)">%h(zFN)</a></li>
273 }else{
274 @ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
275 @ </a></li>
276 }
277 }
278
+24 -8
--- src/cgi.c
+++ src/cgi.c
@@ -295,11 +295,11 @@
295295
if( blob_size(&extraHeader)>0 ){
296296
fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
297297
}
298298
299299
/* Add headers to turn on useful security options in browsers. */
300
- fprintf(g.httpOut, "X-Frame-Options: DENY\r\n");
300
+ fprintf(g.httpOut, "X-Frame-Options: SAMEORIGIN\r\n");
301301
/* This stops fossil pages appearing in frames or iframes, preventing
302302
** click-jacking attacks on supporting browsers.
303303
**
304304
** Other good headers would be
305305
** Strict-Transport-Security: max-age=62208000
@@ -353,10 +353,11 @@
353353
if( size>0 ){
354354
fwrite(blob_buffer(&cgiContent[i]), 1, size, g.httpOut);
355355
}
356356
}
357357
}
358
+ fflush(g.httpOut);
358359
CGIDEBUG(("DONE\n"));
359360
}
360361
361362
/*
362363
** Do a redirect request to the URL given in the argument.
@@ -887,17 +888,26 @@
887888
}
888889
889890
/*
890891
** Print all query parameters on standard output. Format the
891892
** parameters as HTML. This is used for testing and debugging.
893
+** Release builds omit the values of the cookies to avoid defeating
894
+** the purpose of setting HttpOnly cookies.
892895
*/
893896
void cgi_print_all(void){
894897
int i;
898
+ int showAll = 0;
899
+#ifdef FOSSIL_DEBUG
900
+ /* Show the values of cookies in debug mode. */
901
+ showAll = 1;
902
+#endif
895903
cgi_parameter("",""); /* Force the parameters into sorted order */
896904
for(i=0; i<nUsedQP; i++){
897
- cgi_printf("%s = %s <br />\n",
898
- htmlize(aParamQP[i].zName, -1), htmlize(aParamQP[i].zValue, -1));
905
+ if( showAll || (fossil_stricmp("HTTP_COOKIE",aParamQP[i].zName)!=0 && fossil_strnicmp("fossil-",aParamQP[i].zName,7)!=0) ){
906
+ cgi_printf("%s = %s <br />\n",
907
+ htmlize(aParamQP[i].zName, -1), htmlize(aParamQP[i].zValue, -1));
908
+ }
899909
}
900910
}
901911
902912
/*
903913
** This routine works like "printf" except that it has the
@@ -1143,11 +1153,13 @@
11431153
fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
11441154
fflush(stdout);
11451155
}
11461156
if( zBrowser ){
11471157
zBrowser = mprintf(zBrowser, iPort);
1148
- system(zBrowser);
1158
+ if( system(zBrowser)<0 ){
1159
+ fossil_warning("cannot start browser: %s\n", zBrowser);
1160
+ }
11491161
}
11501162
while( 1 ){
11511163
if( nchildren>MAX_PARALLEL ){
11521164
/* Slow down if connections are arriving too fast */
11531165
sleep( nchildren-MAX_PARALLEL );
@@ -1164,20 +1176,24 @@
11641176
child = fork();
11651177
if( child!=0 ){
11661178
if( child>0 ) nchildren++;
11671179
close(connection);
11681180
}else{
1181
+ int nErr = 0, fd;
11691182
close(0);
1170
- dup(connection);
1183
+ fd = dup(connection);
1184
+ if( fd!=0 ) nErr++;
11711185
close(1);
1172
- dup(connection);
1186
+ fd = dup(connection);
1187
+ if( fd!=1 ) nErr++;
11731188
if( !g.fHttpTrace && !g.fSqlTrace ){
11741189
close(2);
1175
- dup(connection);
1190
+ fd = dup(connection);
1191
+ if( fd!=2 ) nErr++;
11761192
}
11771193
close(connection);
1178
- return 0;
1194
+ return nErr;
11791195
}
11801196
}
11811197
}
11821198
/* Bury dead children */
11831199
while( waitpid(0, 0, WNOHANG)>0 ){
11841200
--- src/cgi.c
+++ src/cgi.c
@@ -295,11 +295,11 @@
295 if( blob_size(&extraHeader)>0 ){
296 fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
297 }
298
299 /* Add headers to turn on useful security options in browsers. */
300 fprintf(g.httpOut, "X-Frame-Options: DENY\r\n");
301 /* This stops fossil pages appearing in frames or iframes, preventing
302 ** click-jacking attacks on supporting browsers.
303 **
304 ** Other good headers would be
305 ** Strict-Transport-Security: max-age=62208000
@@ -353,10 +353,11 @@
353 if( size>0 ){
354 fwrite(blob_buffer(&cgiContent[i]), 1, size, g.httpOut);
355 }
356 }
357 }
 
358 CGIDEBUG(("DONE\n"));
359 }
360
361 /*
362 ** Do a redirect request to the URL given in the argument.
@@ -887,17 +888,26 @@
887 }
888
889 /*
890 ** Print all query parameters on standard output. Format the
891 ** parameters as HTML. This is used for testing and debugging.
 
 
892 */
893 void cgi_print_all(void){
894 int i;
 
 
 
 
 
895 cgi_parameter("",""); /* Force the parameters into sorted order */
896 for(i=0; i<nUsedQP; i++){
897 cgi_printf("%s = %s <br />\n",
898 htmlize(aParamQP[i].zName, -1), htmlize(aParamQP[i].zValue, -1));
 
 
899 }
900 }
901
902 /*
903 ** This routine works like "printf" except that it has the
@@ -1143,11 +1153,13 @@
1143 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
1144 fflush(stdout);
1145 }
1146 if( zBrowser ){
1147 zBrowser = mprintf(zBrowser, iPort);
1148 system(zBrowser);
 
 
1149 }
1150 while( 1 ){
1151 if( nchildren>MAX_PARALLEL ){
1152 /* Slow down if connections are arriving too fast */
1153 sleep( nchildren-MAX_PARALLEL );
@@ -1164,20 +1176,24 @@
1164 child = fork();
1165 if( child!=0 ){
1166 if( child>0 ) nchildren++;
1167 close(connection);
1168 }else{
 
1169 close(0);
1170 dup(connection);
 
1171 close(1);
1172 dup(connection);
 
1173 if( !g.fHttpTrace && !g.fSqlTrace ){
1174 close(2);
1175 dup(connection);
 
1176 }
1177 close(connection);
1178 return 0;
1179 }
1180 }
1181 }
1182 /* Bury dead children */
1183 while( waitpid(0, 0, WNOHANG)>0 ){
1184
--- src/cgi.c
+++ src/cgi.c
@@ -295,11 +295,11 @@
295 if( blob_size(&extraHeader)>0 ){
296 fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
297 }
298
299 /* Add headers to turn on useful security options in browsers. */
300 fprintf(g.httpOut, "X-Frame-Options: SAMEORIGIN\r\n");
301 /* This stops fossil pages appearing in frames or iframes, preventing
302 ** click-jacking attacks on supporting browsers.
303 **
304 ** Other good headers would be
305 ** Strict-Transport-Security: max-age=62208000
@@ -353,10 +353,11 @@
353 if( size>0 ){
354 fwrite(blob_buffer(&cgiContent[i]), 1, size, g.httpOut);
355 }
356 }
357 }
358 fflush(g.httpOut);
359 CGIDEBUG(("DONE\n"));
360 }
361
362 /*
363 ** Do a redirect request to the URL given in the argument.
@@ -887,17 +888,26 @@
888 }
889
890 /*
891 ** Print all query parameters on standard output. Format the
892 ** parameters as HTML. This is used for testing and debugging.
893 ** Release builds omit the values of the cookies to avoid defeating
894 ** the purpose of setting HttpOnly cookies.
895 */
896 void cgi_print_all(void){
897 int i;
898 int showAll = 0;
899 #ifdef FOSSIL_DEBUG
900 /* Show the values of cookies in debug mode. */
901 showAll = 1;
902 #endif
903 cgi_parameter("",""); /* Force the parameters into sorted order */
904 for(i=0; i<nUsedQP; i++){
905 if( showAll || (fossil_stricmp("HTTP_COOKIE",aParamQP[i].zName)!=0 && fossil_strnicmp("fossil-",aParamQP[i].zName,7)!=0) ){
906 cgi_printf("%s = %s <br />\n",
907 htmlize(aParamQP[i].zName, -1), htmlize(aParamQP[i].zValue, -1));
908 }
909 }
910 }
911
912 /*
913 ** This routine works like "printf" except that it has the
@@ -1143,11 +1153,13 @@
1153 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
1154 fflush(stdout);
1155 }
1156 if( zBrowser ){
1157 zBrowser = mprintf(zBrowser, iPort);
1158 if( system(zBrowser)<0 ){
1159 fossil_warning("cannot start browser: %s\n", zBrowser);
1160 }
1161 }
1162 while( 1 ){
1163 if( nchildren>MAX_PARALLEL ){
1164 /* Slow down if connections are arriving too fast */
1165 sleep( nchildren-MAX_PARALLEL );
@@ -1164,20 +1176,24 @@
1176 child = fork();
1177 if( child!=0 ){
1178 if( child>0 ) nchildren++;
1179 close(connection);
1180 }else{
1181 int nErr = 0, fd;
1182 close(0);
1183 fd = dup(connection);
1184 if( fd!=0 ) nErr++;
1185 close(1);
1186 fd = dup(connection);
1187 if( fd!=1 ) nErr++;
1188 if( !g.fHttpTrace && !g.fSqlTrace ){
1189 close(2);
1190 fd = dup(connection);
1191 if( fd!=2 ) nErr++;
1192 }
1193 close(connection);
1194 return nErr;
1195 }
1196 }
1197 }
1198 /* Bury dead children */
1199 while( waitpid(0, 0, WNOHANG)>0 ){
1200
+92 -15
--- src/checkin.c
+++ src/checkin.c
@@ -32,60 +32,72 @@
3232
** are not true files results in a fatal error.
3333
*/
3434
static void status_report(
3535
Blob *report, /* Append the status report here */
3636
const char *zPrefix, /* Prefix on each line of the report */
37
- int missingIsFatal /* MISSING and NOT_A_FILE are fatal errors */
37
+ int missingIsFatal, /* MISSING and NOT_A_FILE are fatal errors */
38
+ int cwdRelative /* Report relative to the current working dir */
3839
){
3940
Stmt q;
4041
int nPrefix = strlen(zPrefix);
4142
int nErr = 0;
43
+ Blob rewrittenPathname;
4244
db_prepare(&q,
4345
"SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
4446
" FROM vfile "
4547
" WHERE file_is_selected(id)"
4648
" AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1"
4749
);
50
+ blob_zero(&rewrittenPathname);
4851
while( db_step(&q)==SQLITE_ROW ){
4952
const char *zPathname = db_column_text(&q,0);
53
+ const char *zDisplayName = zPathname;
5054
int isDeleted = db_column_int(&q, 1);
5155
int isChnged = db_column_int(&q,2);
5256
int isNew = db_column_int(&q,3)==0;
5357
int isRenamed = db_column_int(&q,4);
5458
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
59
+ if( cwdRelative ){
60
+ file_relative_name(zFullName, &rewrittenPathname);
61
+ zDisplayName = blob_str(&rewrittenPathname);
62
+ if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
63
+ zDisplayName += 2; /* no unnecessary ./ prefix */
64
+ }
65
+ }
5566
blob_append(report, zPrefix, nPrefix);
5667
if( isDeleted ){
57
- blob_appendf(report, "DELETED %s\n", zPathname);
68
+ blob_appendf(report, "DELETED %s\n", zDisplayName);
5869
}else if( !file_isfile(zFullName) ){
5970
if( file_access(zFullName, 0)==0 ){
60
- blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
71
+ blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName);
6172
if( missingIsFatal ){
62
- fossil_warning("not a file: %s", zPathname);
73
+ fossil_warning("not a file: %s", zDisplayName);
6374
nErr++;
6475
}
6576
}else{
66
- blob_appendf(report, "MISSING %s\n", zPathname);
77
+ blob_appendf(report, "MISSING %s\n", zDisplayName);
6778
if( missingIsFatal ){
68
- fossil_warning("missing file: %s", zPathname);
79
+ fossil_warning("missing file: %s", zDisplayName);
6980
nErr++;
7081
}
7182
}
7283
}else if( isNew ){
73
- blob_appendf(report, "ADDED %s\n", zPathname);
84
+ blob_appendf(report, "ADDED %s\n", zDisplayName);
7485
}else if( isDeleted ){
75
- blob_appendf(report, "DELETED %s\n", zPathname);
86
+ blob_appendf(report, "DELETED %s\n", zDisplayName);
7687
}else if( isChnged==2 ){
77
- blob_appendf(report, "UPDATED_BY_MERGE %s\n", zPathname);
88
+ blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
7889
}else if( isChnged==3 ){
79
- blob_appendf(report, "ADDED_BY_MERGE %s\n", zPathname);
90
+ blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
8091
}else if( isChnged==1 ){
81
- blob_appendf(report, "EDITED %s\n", zPathname);
92
+ blob_appendf(report, "EDITED %s\n", zDisplayName);
8293
}else if( isRenamed ){
83
- blob_appendf(report, "RENAMED %s\n", zPathname);
94
+ blob_appendf(report, "RENAMED %s\n", zDisplayName);
8495
}
8596
free(zFullName);
8697
}
98
+ blob_reset(&rewrittenPathname);
8799
db_finalize(&q);
88100
db_prepare(&q, "SELECT uuid FROM vmerge JOIN blob ON merge=rid"
89101
" WHERE id=0");
90102
while( db_step(&q)==SQLITE_ROW ){
91103
blob_append(report, zPrefix, nPrefix);
@@ -94,33 +106,59 @@
94106
db_finalize(&q);
95107
if( nErr ){
96108
fossil_fatal("aborting due to prior errors");
97109
}
98110
}
111
+
112
+/*
113
+** Use the "relative-paths" setting and the --abs-paths and
114
+** --rel-paths command line options to determine whether the
115
+** status report should be shown relative to the current
116
+** working directory.
117
+*/
118
+static int determine_cwd_relative_option()
119
+{
120
+ int relativePaths = db_get_boolean("relative-paths", 1);
121
+ int absPathOption = find_option("abs-paths", 0, 0)!=0;
122
+ int relPathOption = find_option("rel-paths", 0, 0)!=0;
123
+ if( absPathOption ){ relativePaths = 0; }
124
+ if( relPathOption ){ relativePaths = 1; }
125
+ return relativePaths;
126
+}
99127
100128
/*
101129
** COMMAND: changes
102130
**
103131
** Usage: %fossil changes
104132
**
105133
** Report on the edit status of all files in the current checkout.
106134
** See also the "status" and "extra" commands.
107135
**
136
+** Pathnames are displayed according to the "relative-paths" setting,
137
+** unless overridden by the --abs-paths or --rel-paths options.
138
+**
108139
** Options:
109140
**
110141
** --sha1sum Verify file status using SHA1 hashing rather
111142
** than relying on file mtimes.
143
+**
144
+** --abs-paths Display absolute pathnames.
145
+**
146
+** --rel-paths Display pathnames relative to the current working
147
+** directory.
112148
*/
113149
void changes_cmd(void){
114150
Blob report;
115151
int vid;
116152
int useSha1sum = find_option("sha1sum", 0, 0)!=0;
153
+ int cwdRelative = 0;
117154
db_must_be_within_tree();
155
+ cwdRelative = determine_cwd_relative_option();
118156
blob_zero(&report);
119157
vid = db_lget_int("checkout", 0);
120158
vfile_check_signature(vid, 0, useSha1sum);
121
- status_report(&report, "", 0);
159
+ status_report(&report, "", 0, cwdRelative);
122160
blob_write_to_file(&report, "-");
123161
}
124162
125163
/*
126164
** COMMAND: status
@@ -127,14 +165,22 @@
127165
**
128166
** Usage: %fossil status
129167
**
130168
** Report on the status of the current checkout.
131169
**
170
+** Pathnames are displayed according to the "relative-paths" setting,
171
+** unless overridden by the --abs-paths or --rel-paths options.
172
+**
132173
** Options:
133174
**
134175
** --sha1sum Verify file status using SHA1 hashing rather
135176
** than relying on file mtimes.
177
+**
178
+** --abs-paths Display absolute pathnames.
179
+**
180
+** --rel-paths Display pathnames relative to the current working
181
+** directory.
136182
*/
137183
void status_cmd(void){
138184
int vid;
139185
db_must_be_within_tree();
140186
/* 012345678901234 */
@@ -212,22 +258,41 @@
212258
** ignored but can be included by adding the --dotfiles option.
213259
**
214260
** The GLOBPATTERN is a comma-separated list of GLOB expressions for
215261
** files that are ignored. The GLOBPATTERN specified by the "ignore-glob"
216262
** is used if the --ignore option is omitted.
263
+**
264
+** Pathnames are displayed according to the "relative-paths" setting,
265
+** unless overridden by the --abs-paths or --rel-paths options.
266
+**
267
+** Options:
268
+**
269
+** --dotfiles Include files with names beginning with "."
270
+**
271
+** --ignore GLOBPATTERN
272
+** Override the "ignore-glob" setting.
273
+**
274
+** --abs-paths Display absolute pathnames.
275
+**
276
+** --rel-paths Display pathnames relative to the current working
277
+** directory.
217278
*/
218279
void extra_cmd(void){
219280
Blob path;
220281
Blob repo;
221282
Stmt q;
222283
int n;
223284
const char *zIgnoreFlag = find_option("ignore",0,1);
224285
int allFlag = find_option("dotfiles",0,0)!=0;
286
+ int cwdRelative = 0;
225287
int outputManifest;
226288
Glob *pIgnore;
289
+ Blob rewrittenPathname;
290
+ const char *zPathname, *zDisplayName;
227291
228292
db_must_be_within_tree();
293
+ cwdRelative = determine_cwd_relative_option();
229294
outputManifest = db_get_boolean("manifest",0);
230295
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
231296
n = strlen(g.zLocalRoot);
232297
blob_init(&path, g.zLocalRoot, n-1);
233298
if( zIgnoreFlag==0 ){
@@ -243,13 +308,25 @@
243308
fossil_all_reserved_names()
244309
);
245310
if( file_tree_name(g.zRepositoryName, &repo, 0) ){
246311
db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
247312
}
313
+ blob_zero(&rewrittenPathname);
248314
while( db_step(&q)==SQLITE_ROW ){
249
- fossil_print("%s\n", db_column_text(&q, 0));
315
+ zDisplayName = zPathname = db_column_text(&q, 0);
316
+ if( cwdRelative ) {
317
+ char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
318
+ file_relative_name(zFullName, &rewrittenPathname);
319
+ free(zFullName);
320
+ zDisplayName = blob_str(&rewrittenPathname);
321
+ if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
322
+ zDisplayName += 2; /* no unnecessary ./ prefix */
323
+ }
324
+ }
325
+ fossil_print("%s\n", zDisplayName);
250326
}
327
+ blob_reset(&rewrittenPathname);
251328
db_finalize(&q);
252329
}
253330
254331
/*
255332
** COMMAND: clean
@@ -367,11 +444,11 @@
367444
"# PRIVATE BRANCH: This check-in will be private and will not sync to\n"
368445
"# repositories.\n"
369446
"#\n", -1
370447
);
371448
}
372
- status_report(&text, "# ", 1);
449
+ status_report(&text, "# ", 1, 0);
373450
zEditor = db_get("editor", 0);
374451
if( zEditor==0 ){
375452
zEditor = getenv("VISUAL");
376453
}
377454
if( zEditor==0 ){
378455
--- src/checkin.c
+++ src/checkin.c
@@ -32,60 +32,72 @@
32 ** are not true files results in a fatal error.
33 */
34 static void status_report(
35 Blob *report, /* Append the status report here */
36 const char *zPrefix, /* Prefix on each line of the report */
37 int missingIsFatal /* MISSING and NOT_A_FILE are fatal errors */
 
38 ){
39 Stmt q;
40 int nPrefix = strlen(zPrefix);
41 int nErr = 0;
 
42 db_prepare(&q,
43 "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
44 " FROM vfile "
45 " WHERE file_is_selected(id)"
46 " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1"
47 );
 
48 while( db_step(&q)==SQLITE_ROW ){
49 const char *zPathname = db_column_text(&q,0);
 
50 int isDeleted = db_column_int(&q, 1);
51 int isChnged = db_column_int(&q,2);
52 int isNew = db_column_int(&q,3)==0;
53 int isRenamed = db_column_int(&q,4);
54 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
 
 
 
 
 
 
 
55 blob_append(report, zPrefix, nPrefix);
56 if( isDeleted ){
57 blob_appendf(report, "DELETED %s\n", zPathname);
58 }else if( !file_isfile(zFullName) ){
59 if( file_access(zFullName, 0)==0 ){
60 blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
61 if( missingIsFatal ){
62 fossil_warning("not a file: %s", zPathname);
63 nErr++;
64 }
65 }else{
66 blob_appendf(report, "MISSING %s\n", zPathname);
67 if( missingIsFatal ){
68 fossil_warning("missing file: %s", zPathname);
69 nErr++;
70 }
71 }
72 }else if( isNew ){
73 blob_appendf(report, "ADDED %s\n", zPathname);
74 }else if( isDeleted ){
75 blob_appendf(report, "DELETED %s\n", zPathname);
76 }else if( isChnged==2 ){
77 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zPathname);
78 }else if( isChnged==3 ){
79 blob_appendf(report, "ADDED_BY_MERGE %s\n", zPathname);
80 }else if( isChnged==1 ){
81 blob_appendf(report, "EDITED %s\n", zPathname);
82 }else if( isRenamed ){
83 blob_appendf(report, "RENAMED %s\n", zPathname);
84 }
85 free(zFullName);
86 }
 
87 db_finalize(&q);
88 db_prepare(&q, "SELECT uuid FROM vmerge JOIN blob ON merge=rid"
89 " WHERE id=0");
90 while( db_step(&q)==SQLITE_ROW ){
91 blob_append(report, zPrefix, nPrefix);
@@ -94,33 +106,59 @@
94 db_finalize(&q);
95 if( nErr ){
96 fossil_fatal("aborting due to prior errors");
97 }
98 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
100 /*
101 ** COMMAND: changes
102 **
103 ** Usage: %fossil changes
104 **
105 ** Report on the edit status of all files in the current checkout.
106 ** See also the "status" and "extra" commands.
107 **
 
 
 
108 ** Options:
109 **
110 ** --sha1sum Verify file status using SHA1 hashing rather
111 ** than relying on file mtimes.
 
 
 
 
 
112 */
113 void changes_cmd(void){
114 Blob report;
115 int vid;
116 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
 
117 db_must_be_within_tree();
 
118 blob_zero(&report);
119 vid = db_lget_int("checkout", 0);
120 vfile_check_signature(vid, 0, useSha1sum);
121 status_report(&report, "", 0);
122 blob_write_to_file(&report, "-");
123 }
124
125 /*
126 ** COMMAND: status
@@ -127,14 +165,22 @@
127 **
128 ** Usage: %fossil status
129 **
130 ** Report on the status of the current checkout.
131 **
 
 
 
132 ** Options:
133 **
134 ** --sha1sum Verify file status using SHA1 hashing rather
135 ** than relying on file mtimes.
 
 
 
 
 
136 */
137 void status_cmd(void){
138 int vid;
139 db_must_be_within_tree();
140 /* 012345678901234 */
@@ -212,22 +258,41 @@
212 ** ignored but can be included by adding the --dotfiles option.
213 **
214 ** The GLOBPATTERN is a comma-separated list of GLOB expressions for
215 ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob"
216 ** is used if the --ignore option is omitted.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217 */
218 void extra_cmd(void){
219 Blob path;
220 Blob repo;
221 Stmt q;
222 int n;
223 const char *zIgnoreFlag = find_option("ignore",0,1);
224 int allFlag = find_option("dotfiles",0,0)!=0;
 
225 int outputManifest;
226 Glob *pIgnore;
 
 
227
228 db_must_be_within_tree();
 
229 outputManifest = db_get_boolean("manifest",0);
230 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
231 n = strlen(g.zLocalRoot);
232 blob_init(&path, g.zLocalRoot, n-1);
233 if( zIgnoreFlag==0 ){
@@ -243,13 +308,25 @@
243 fossil_all_reserved_names()
244 );
245 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
246 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
247 }
 
248 while( db_step(&q)==SQLITE_ROW ){
249 fossil_print("%s\n", db_column_text(&q, 0));
 
 
 
 
 
 
 
 
 
 
250 }
 
251 db_finalize(&q);
252 }
253
254 /*
255 ** COMMAND: clean
@@ -367,11 +444,11 @@
367 "# PRIVATE BRANCH: This check-in will be private and will not sync to\n"
368 "# repositories.\n"
369 "#\n", -1
370 );
371 }
372 status_report(&text, "# ", 1);
373 zEditor = db_get("editor", 0);
374 if( zEditor==0 ){
375 zEditor = getenv("VISUAL");
376 }
377 if( zEditor==0 ){
378
--- src/checkin.c
+++ src/checkin.c
@@ -32,60 +32,72 @@
32 ** are not true files results in a fatal error.
33 */
34 static void status_report(
35 Blob *report, /* Append the status report here */
36 const char *zPrefix, /* Prefix on each line of the report */
37 int missingIsFatal, /* MISSING and NOT_A_FILE are fatal errors */
38 int cwdRelative /* Report relative to the current working dir */
39 ){
40 Stmt q;
41 int nPrefix = strlen(zPrefix);
42 int nErr = 0;
43 Blob rewrittenPathname;
44 db_prepare(&q,
45 "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
46 " FROM vfile "
47 " WHERE file_is_selected(id)"
48 " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1"
49 );
50 blob_zero(&rewrittenPathname);
51 while( db_step(&q)==SQLITE_ROW ){
52 const char *zPathname = db_column_text(&q,0);
53 const char *zDisplayName = zPathname;
54 int isDeleted = db_column_int(&q, 1);
55 int isChnged = db_column_int(&q,2);
56 int isNew = db_column_int(&q,3)==0;
57 int isRenamed = db_column_int(&q,4);
58 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
59 if( cwdRelative ){
60 file_relative_name(zFullName, &rewrittenPathname);
61 zDisplayName = blob_str(&rewrittenPathname);
62 if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
63 zDisplayName += 2; /* no unnecessary ./ prefix */
64 }
65 }
66 blob_append(report, zPrefix, nPrefix);
67 if( isDeleted ){
68 blob_appendf(report, "DELETED %s\n", zDisplayName);
69 }else if( !file_isfile(zFullName) ){
70 if( file_access(zFullName, 0)==0 ){
71 blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName);
72 if( missingIsFatal ){
73 fossil_warning("not a file: %s", zDisplayName);
74 nErr++;
75 }
76 }else{
77 blob_appendf(report, "MISSING %s\n", zDisplayName);
78 if( missingIsFatal ){
79 fossil_warning("missing file: %s", zDisplayName);
80 nErr++;
81 }
82 }
83 }else if( isNew ){
84 blob_appendf(report, "ADDED %s\n", zDisplayName);
85 }else if( isDeleted ){
86 blob_appendf(report, "DELETED %s\n", zDisplayName);
87 }else if( isChnged==2 ){
88 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
89 }else if( isChnged==3 ){
90 blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
91 }else if( isChnged==1 ){
92 blob_appendf(report, "EDITED %s\n", zDisplayName);
93 }else if( isRenamed ){
94 blob_appendf(report, "RENAMED %s\n", zDisplayName);
95 }
96 free(zFullName);
97 }
98 blob_reset(&rewrittenPathname);
99 db_finalize(&q);
100 db_prepare(&q, "SELECT uuid FROM vmerge JOIN blob ON merge=rid"
101 " WHERE id=0");
102 while( db_step(&q)==SQLITE_ROW ){
103 blob_append(report, zPrefix, nPrefix);
@@ -94,33 +106,59 @@
106 db_finalize(&q);
107 if( nErr ){
108 fossil_fatal("aborting due to prior errors");
109 }
110 }
111
112 /*
113 ** Use the "relative-paths" setting and the --abs-paths and
114 ** --rel-paths command line options to determine whether the
115 ** status report should be shown relative to the current
116 ** working directory.
117 */
118 static int determine_cwd_relative_option()
119 {
120 int relativePaths = db_get_boolean("relative-paths", 1);
121 int absPathOption = find_option("abs-paths", 0, 0)!=0;
122 int relPathOption = find_option("rel-paths", 0, 0)!=0;
123 if( absPathOption ){ relativePaths = 0; }
124 if( relPathOption ){ relativePaths = 1; }
125 return relativePaths;
126 }
127
128 /*
129 ** COMMAND: changes
130 **
131 ** Usage: %fossil changes
132 **
133 ** Report on the edit status of all files in the current checkout.
134 ** See also the "status" and "extra" commands.
135 **
136 ** Pathnames are displayed according to the "relative-paths" setting,
137 ** unless overridden by the --abs-paths or --rel-paths options.
138 **
139 ** Options:
140 **
141 ** --sha1sum Verify file status using SHA1 hashing rather
142 ** than relying on file mtimes.
143 **
144 ** --abs-paths Display absolute pathnames.
145 **
146 ** --rel-paths Display pathnames relative to the current working
147 ** directory.
148 */
149 void changes_cmd(void){
150 Blob report;
151 int vid;
152 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
153 int cwdRelative = 0;
154 db_must_be_within_tree();
155 cwdRelative = determine_cwd_relative_option();
156 blob_zero(&report);
157 vid = db_lget_int("checkout", 0);
158 vfile_check_signature(vid, 0, useSha1sum);
159 status_report(&report, "", 0, cwdRelative);
160 blob_write_to_file(&report, "-");
161 }
162
163 /*
164 ** COMMAND: status
@@ -127,14 +165,22 @@
165 **
166 ** Usage: %fossil status
167 **
168 ** Report on the status of the current checkout.
169 **
170 ** Pathnames are displayed according to the "relative-paths" setting,
171 ** unless overridden by the --abs-paths or --rel-paths options.
172 **
173 ** Options:
174 **
175 ** --sha1sum Verify file status using SHA1 hashing rather
176 ** than relying on file mtimes.
177 **
178 ** --abs-paths Display absolute pathnames.
179 **
180 ** --rel-paths Display pathnames relative to the current working
181 ** directory.
182 */
183 void status_cmd(void){
184 int vid;
185 db_must_be_within_tree();
186 /* 012345678901234 */
@@ -212,22 +258,41 @@
258 ** ignored but can be included by adding the --dotfiles option.
259 **
260 ** The GLOBPATTERN is a comma-separated list of GLOB expressions for
261 ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob"
262 ** is used if the --ignore option is omitted.
263 **
264 ** Pathnames are displayed according to the "relative-paths" setting,
265 ** unless overridden by the --abs-paths or --rel-paths options.
266 **
267 ** Options:
268 **
269 ** --dotfiles Include files with names beginning with "."
270 **
271 ** --ignore GLOBPATTERN
272 ** Override the "ignore-glob" setting.
273 **
274 ** --abs-paths Display absolute pathnames.
275 **
276 ** --rel-paths Display pathnames relative to the current working
277 ** directory.
278 */
279 void extra_cmd(void){
280 Blob path;
281 Blob repo;
282 Stmt q;
283 int n;
284 const char *zIgnoreFlag = find_option("ignore",0,1);
285 int allFlag = find_option("dotfiles",0,0)!=0;
286 int cwdRelative = 0;
287 int outputManifest;
288 Glob *pIgnore;
289 Blob rewrittenPathname;
290 const char *zPathname, *zDisplayName;
291
292 db_must_be_within_tree();
293 cwdRelative = determine_cwd_relative_option();
294 outputManifest = db_get_boolean("manifest",0);
295 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
296 n = strlen(g.zLocalRoot);
297 blob_init(&path, g.zLocalRoot, n-1);
298 if( zIgnoreFlag==0 ){
@@ -243,13 +308,25 @@
308 fossil_all_reserved_names()
309 );
310 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
311 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
312 }
313 blob_zero(&rewrittenPathname);
314 while( db_step(&q)==SQLITE_ROW ){
315 zDisplayName = zPathname = db_column_text(&q, 0);
316 if( cwdRelative ) {
317 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
318 file_relative_name(zFullName, &rewrittenPathname);
319 free(zFullName);
320 zDisplayName = blob_str(&rewrittenPathname);
321 if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
322 zDisplayName += 2; /* no unnecessary ./ prefix */
323 }
324 }
325 fossil_print("%s\n", zDisplayName);
326 }
327 blob_reset(&rewrittenPathname);
328 db_finalize(&q);
329 }
330
331 /*
332 ** COMMAND: clean
@@ -367,11 +444,11 @@
444 "# PRIVATE BRANCH: This check-in will be private and will not sync to\n"
445 "# repositories.\n"
446 "#\n", -1
447 );
448 }
449 status_report(&text, "# ", 1, 0);
450 zEditor = db_get("editor", 0);
451 if( zEditor==0 ){
452 zEditor = getenv("VISUAL");
453 }
454 if( zEditor==0 ){
455
--- src/checkout.c
+++ src/checkout.c
@@ -232,10 +232,11 @@
232232
if( !keepFlag ){
233233
vfile_to_disk(vid, 0, 1, promptFlag);
234234
}
235235
checkout_set_all_exe(vid);
236236
manifest_to_disk(vid);
237
+ ensure_empty_dirs_created();
237238
db_lset_int("checkout", vid);
238239
undo_reset();
239240
db_multi_exec("DELETE FROM vmerge");
240241
if( !keepFlag && db_get_boolean("repo-cksum",1) ){
241242
vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
242243
--- src/checkout.c
+++ src/checkout.c
@@ -232,10 +232,11 @@
232 if( !keepFlag ){
233 vfile_to_disk(vid, 0, 1, promptFlag);
234 }
235 checkout_set_all_exe(vid);
236 manifest_to_disk(vid);
 
237 db_lset_int("checkout", vid);
238 undo_reset();
239 db_multi_exec("DELETE FROM vmerge");
240 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
241 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
242
--- src/checkout.c
+++ src/checkout.c
@@ -232,10 +232,11 @@
232 if( !keepFlag ){
233 vfile_to_disk(vid, 0, 1, promptFlag);
234 }
235 checkout_set_all_exe(vid);
236 manifest_to_disk(vid);
237 ensure_empty_dirs_created();
238 db_lset_int("checkout", vid);
239 undo_reset();
240 db_multi_exec("DELETE FROM vmerge");
241 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
242 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
243
+17 -3
--- src/clone.c
+++ src/clone.c
@@ -37,15 +37,17 @@
3737
**
3838
** Options:
3939
**
4040
** --admin-user|-A USERNAME Make USERNAME the administrator
4141
** --private Also clone private branches
42
+** --ssl-identity=filename Use the SSL identity if requested by the server
4243
**
4344
*/
4445
void clone_cmd(void){
4546
char *zPassword;
4647
const char *zDefaultUser; /* Optional name of the default user */
48
+ const char *zPw; /* The user clone password */
4749
int nErr = 0;
4850
int bPrivate; /* Also clone private branches */
4951
5052
bPrivate = find_option("private",0,0)!=0;
5153
url_proxy_options();
@@ -76,13 +78,15 @@
7678
"DELETE FROM blob WHERE rid IN private;"
7779
"DELETE FROM delta wHERE rid IN private;"
7880
"DELETE FROM private;"
7981
);
8082
shun_artifacts();
81
- g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
82
- if( g.zLogin==0 ){
83
- db_create_default_users(1,zDefaultUser);
83
+ db_create_default_users(1, zDefaultUser);
84
+ if( zDefaultUser ){
85
+ g.zLogin = zDefaultUser;
86
+ }else{
87
+ g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
8488
}
8589
fossil_print("Repository cloned into %s\n", g.argv[3]);
8690
}else{
8791
db_create_repository(g.argv[3]);
8892
db_open_repository(g.argv[3]);
@@ -91,10 +95,18 @@
9195
db_initial_setup(0, zDefaultUser, 0);
9296
user_select();
9397
db_set("content-schema", CONTENT_SCHEMA, 0);
9498
db_set("aux-schema", AUX_SCHEMA, 0);
9599
db_set("last-sync-url", g.argv[2], 0);
100
+ if( g.zSSLIdentity!=0 ){
101
+ /* If the --ssl-identity option was specified, store it as a setting */
102
+ Blob fn;
103
+ blob_zero(&fn);
104
+ file_canonical_name(g.zSSLIdentity, &fn);
105
+ db_set("ssl-identity", blob_str(&fn), 0);
106
+ blob_reset(&fn);
107
+ }
96108
db_multi_exec(
97109
"REPLACE INTO config(name,value,mtime)"
98110
" VALUES('server-code', lower(hex(randomblob(20))), now());"
99111
);
100112
url_enable_proxy(0);
@@ -116,7 +128,9 @@
116128
rebuild_db(0, 1, 0);
117129
fossil_print("project-id: %s\n", db_get("project-code", 0));
118130
fossil_print("server-id: %s\n", db_get("server-code", 0));
119131
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120132
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
133
+ zPw = g.urlPasswd;
134
+ if( !g.dontKeepUrl && zPw) db_set("last-sync-pw", obscure(zPw), 0);
121135
db_end_transaction(0);
122136
}
123137
--- src/clone.c
+++ src/clone.c
@@ -37,15 +37,17 @@
37 **
38 ** Options:
39 **
40 ** --admin-user|-A USERNAME Make USERNAME the administrator
41 ** --private Also clone private branches
 
42 **
43 */
44 void clone_cmd(void){
45 char *zPassword;
46 const char *zDefaultUser; /* Optional name of the default user */
 
47 int nErr = 0;
48 int bPrivate; /* Also clone private branches */
49
50 bPrivate = find_option("private",0,0)!=0;
51 url_proxy_options();
@@ -76,13 +78,15 @@
76 "DELETE FROM blob WHERE rid IN private;"
77 "DELETE FROM delta wHERE rid IN private;"
78 "DELETE FROM private;"
79 );
80 shun_artifacts();
81 g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
82 if( g.zLogin==0 ){
83 db_create_default_users(1,zDefaultUser);
 
 
84 }
85 fossil_print("Repository cloned into %s\n", g.argv[3]);
86 }else{
87 db_create_repository(g.argv[3]);
88 db_open_repository(g.argv[3]);
@@ -91,10 +95,18 @@
91 db_initial_setup(0, zDefaultUser, 0);
92 user_select();
93 db_set("content-schema", CONTENT_SCHEMA, 0);
94 db_set("aux-schema", AUX_SCHEMA, 0);
95 db_set("last-sync-url", g.argv[2], 0);
 
 
 
 
 
 
 
 
96 db_multi_exec(
97 "REPLACE INTO config(name,value,mtime)"
98 " VALUES('server-code', lower(hex(randomblob(20))), now());"
99 );
100 url_enable_proxy(0);
@@ -116,7 +128,9 @@
116 rebuild_db(0, 1, 0);
117 fossil_print("project-id: %s\n", db_get("project-code", 0));
118 fossil_print("server-id: %s\n", db_get("server-code", 0));
119 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
 
 
121 db_end_transaction(0);
122 }
123
--- src/clone.c
+++ src/clone.c
@@ -37,15 +37,17 @@
37 **
38 ** Options:
39 **
40 ** --admin-user|-A USERNAME Make USERNAME the administrator
41 ** --private Also clone private branches
42 ** --ssl-identity=filename Use the SSL identity if requested by the server
43 **
44 */
45 void clone_cmd(void){
46 char *zPassword;
47 const char *zDefaultUser; /* Optional name of the default user */
48 const char *zPw; /* The user clone password */
49 int nErr = 0;
50 int bPrivate; /* Also clone private branches */
51
52 bPrivate = find_option("private",0,0)!=0;
53 url_proxy_options();
@@ -76,13 +78,15 @@
78 "DELETE FROM blob WHERE rid IN private;"
79 "DELETE FROM delta wHERE rid IN private;"
80 "DELETE FROM private;"
81 );
82 shun_artifacts();
83 db_create_default_users(1, zDefaultUser);
84 if( zDefaultUser ){
85 g.zLogin = zDefaultUser;
86 }else{
87 g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
88 }
89 fossil_print("Repository cloned into %s\n", g.argv[3]);
90 }else{
91 db_create_repository(g.argv[3]);
92 db_open_repository(g.argv[3]);
@@ -91,10 +95,18 @@
95 db_initial_setup(0, zDefaultUser, 0);
96 user_select();
97 db_set("content-schema", CONTENT_SCHEMA, 0);
98 db_set("aux-schema", AUX_SCHEMA, 0);
99 db_set("last-sync-url", g.argv[2], 0);
100 if( g.zSSLIdentity!=0 ){
101 /* If the --ssl-identity option was specified, store it as a setting */
102 Blob fn;
103 blob_zero(&fn);
104 file_canonical_name(g.zSSLIdentity, &fn);
105 db_set("ssl-identity", blob_str(&fn), 0);
106 blob_reset(&fn);
107 }
108 db_multi_exec(
109 "REPLACE INTO config(name,value,mtime)"
110 " VALUES('server-code', lower(hex(randomblob(20))), now());"
111 );
112 url_enable_proxy(0);
@@ -116,7 +128,9 @@
128 rebuild_db(0, 1, 0);
129 fossil_print("project-id: %s\n", db_get("project-code", 0));
130 fossil_print("server-id: %s\n", db_get("server-code", 0));
131 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
132 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
133 zPw = g.urlPasswd;
134 if( !g.dontKeepUrl && zPw) db_set("last-sync-pw", obscure(zPw), 0);
135 db_end_transaction(0);
136 }
137
+5 -1
--- src/config.h
+++ src/config.h
@@ -24,10 +24,14 @@
2424
#define _LARGE_FILE 1
2525
#ifndef _FILE_OFFSET_BITS
2626
# define _FILE_OFFSET_BITS 64
2727
#endif
2828
#define _LARGEFILE_SOURCE 1
29
+
30
+#ifdef HAVE_AUTOCONFIG_H
31
+#include "autoconfig.h"
32
+#endif
2933
3034
#ifndef _RC_COMPILE_
3135
3236
/*
3337
** System header files used by all modules
@@ -85,11 +89,11 @@
8589
#include "sqlite3.h"
8690
8791
/*
8892
** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
8993
*/
90
-#if defined(__sun__) || defined(sun)
94
+#if HAVE_GETPASSPHRASE
9195
#define getpass getpassphrase
9296
#endif
9397
9498
/*
9599
** Typedef for a 64-bit integer
96100
--- src/config.h
+++ src/config.h
@@ -24,10 +24,14 @@
24 #define _LARGE_FILE 1
25 #ifndef _FILE_OFFSET_BITS
26 # define _FILE_OFFSET_BITS 64
27 #endif
28 #define _LARGEFILE_SOURCE 1
 
 
 
 
29
30 #ifndef _RC_COMPILE_
31
32 /*
33 ** System header files used by all modules
@@ -85,11 +89,11 @@
85 #include "sqlite3.h"
86
87 /*
88 ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
89 */
90 #if defined(__sun__) || defined(sun)
91 #define getpass getpassphrase
92 #endif
93
94 /*
95 ** Typedef for a 64-bit integer
96
--- src/config.h
+++ src/config.h
@@ -24,10 +24,14 @@
24 #define _LARGE_FILE 1
25 #ifndef _FILE_OFFSET_BITS
26 # define _FILE_OFFSET_BITS 64
27 #endif
28 #define _LARGEFILE_SOURCE 1
29
30 #ifdef HAVE_AUTOCONFIG_H
31 #include "autoconfig.h"
32 #endif
33
34 #ifndef _RC_COMPILE_
35
36 /*
37 ** System header files used by all modules
@@ -85,11 +89,11 @@
89 #include "sqlite3.h"
90
91 /*
92 ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
93 */
94 #if HAVE_GETPASSPHRASE
95 #define getpass getpassphrase
96 #endif
97
98 /*
99 ** Typedef for a 64-bit integer
100
--- src/configure.c
+++ src/configure.c
@@ -81,10 +81,11 @@
8181
{ "project-name", CONFIGSET_PROJ },
8282
{ "project-description", CONFIGSET_PROJ },
8383
{ "manifest", CONFIGSET_PROJ },
8484
{ "ignore-glob", CONFIGSET_PROJ },
8585
{ "crnl-glob", CONFIGSET_PROJ },
86
+ { "empty-dirs", CONFIGSET_PROJ },
8687
{ "index-page", CONFIGSET_SKIN },
8788
{ "timeline-block-markup", CONFIGSET_SKIN },
8889
{ "timeline-max-comment", CONFIGSET_SKIN },
8990
{ "ticket-table", CONFIGSET_TKT },
9091
{ "ticket-common", CONFIGSET_TKT },
9192
--- src/configure.c
+++ src/configure.c
@@ -81,10 +81,11 @@
81 { "project-name", CONFIGSET_PROJ },
82 { "project-description", CONFIGSET_PROJ },
83 { "manifest", CONFIGSET_PROJ },
84 { "ignore-glob", CONFIGSET_PROJ },
85 { "crnl-glob", CONFIGSET_PROJ },
 
86 { "index-page", CONFIGSET_SKIN },
87 { "timeline-block-markup", CONFIGSET_SKIN },
88 { "timeline-max-comment", CONFIGSET_SKIN },
89 { "ticket-table", CONFIGSET_TKT },
90 { "ticket-common", CONFIGSET_TKT },
91
--- src/configure.c
+++ src/configure.c
@@ -81,10 +81,11 @@
81 { "project-name", CONFIGSET_PROJ },
82 { "project-description", CONFIGSET_PROJ },
83 { "manifest", CONFIGSET_PROJ },
84 { "ignore-glob", CONFIGSET_PROJ },
85 { "crnl-glob", CONFIGSET_PROJ },
86 { "empty-dirs", CONFIGSET_PROJ },
87 { "index-page", CONFIGSET_SKIN },
88 { "timeline-block-markup", CONFIGSET_SKIN },
89 { "timeline-max-comment", CONFIGSET_SKIN },
90 { "ticket-table", CONFIGSET_TKT },
91 { "ticket-common", CONFIGSET_TKT },
92
+201 -52
--- src/db.c
+++ src/db.c
@@ -153,13 +153,17 @@
153153
** Force a rollback and shutdown the database
154154
*/
155155
void db_force_rollback(void){
156156
int i;
157157
static int busy = 0;
158
+ sqlite3_stmt *pStmt = 0;
158159
if( busy || g.db==0 ) return;
159160
busy = 1;
160161
undo_rollback();
162
+ while( (pStmt = sqlite3_next_stmt(g.db,pStmt))!=0 ){
163
+ sqlite3_reset(pStmt);
164
+ }
161165
while( pAllStmt ){
162166
db_finalize(pAllStmt);
163167
}
164168
if( nBegin ){
165169
sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
@@ -809,10 +813,11 @@
809813
static const char *aDbName[] = { "/_FOSSIL_", "/.fos" };
810814
811815
if( g.localOpen) return 1;
812816
file_getcwd(zPwd, sizeof(zPwd)-20);
813817
n = strlen(zPwd);
818
+ if( n==1 && zPwd[0]=='/' ) zPwd[0] = '.';
814819
while( n>0 ){
815820
if( file_access(zPwd, W_OK) ) break;
816821
for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
817822
sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
818823
if( isValidLocalDb(zPwd) ){
@@ -1058,14 +1063,13 @@
10581063
10591064
/*
10601065
** Create the default user accounts in the USER table.
10611066
*/
10621067
void db_create_default_users(int setupUserOnly, const char *zDefaultUser){
1063
- const char *zUser;
1064
- zUser = db_get("default-user", 0);
1068
+ const char *zUser = zDefaultUser;
10651069
if( zUser==0 ){
1066
- zUser = zDefaultUser;
1070
+ zUser = db_get("default-user", 0);
10671071
}
10681072
if( zUser==0 ){
10691073
#if defined(_WIN32)
10701074
zUser = getenv("USERNAME");
10711075
#else
@@ -1074,12 +1078,15 @@
10741078
}
10751079
if( zUser==0 ){
10761080
zUser = "root";
10771081
}
10781082
db_multi_exec(
1079
- "INSERT INTO user(login, pw, cap, info)"
1080
- "VALUES(%Q,lower(hex(randomblob(3))),'s','')", zUser
1083
+ "INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
1084
+ );
1085
+ db_multi_exec(
1086
+ "UPDATE user SET cap='s', pw=lower(hex(randomblob(3)))"
1087
+ " WHERE login=%Q", zUser
10811088
);
10821089
if( !setupUserOnly ){
10831090
db_multi_exec(
10841091
"INSERT INTO user(login,pw,cap,info)"
10851092
" VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');"
@@ -1363,19 +1370,19 @@
13631370
*/
13641371
int is_truth(const char *zVal){
13651372
static const char *azOn[] = { "on", "yes", "true", "1" };
13661373
int i;
13671374
for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
1368
- if( fossil_strcmp(zVal,azOn[i])==0 ) return 1;
1375
+ if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
13691376
}
13701377
return 0;
13711378
}
13721379
int is_false(const char *zVal){
13731380
static const char *azOff[] = { "off", "no", "false", "0" };
13741381
int i;
13751382
for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1376
- if( fossil_strcmp(zVal,azOff[i])==0 ) return 1;
1383
+ if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
13771384
}
13781385
return 0;
13791386
}
13801387
13811388
/*
@@ -1392,24 +1399,114 @@
13921399
sqlite3 *dbTemp = g.db;
13931400
g.db = g.dbConfig;
13941401
g.dbConfig = dbTemp;
13951402
}
13961403
}
1404
+
1405
+/*
1406
+** Logic for reading potentially versioned settings from
1407
+** .fossil-settings/<name> , and emits warnings if necessary.
1408
+** Returns the non-versioned value without modification if there is no
1409
+** versioned value.
1410
+*/
1411
+static char *db_get_do_versionable(const char *zName, char *zNonVersionedSetting){
1412
+ char *zVersionedSetting = 0;
1413
+ int noWarn = 0;
1414
+ struct _cacheEntry {
1415
+ struct _cacheEntry *next;
1416
+ const char *zName, *zValue;
1417
+ } *cacheEntry = 0;
1418
+ static struct _cacheEntry *cache = 0;
1419
+
1420
+ /* Look up name in cache */
1421
+ cacheEntry = cache;
1422
+ while( cacheEntry!=0 ){
1423
+ if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
1424
+ zVersionedSetting = fossil_strdup(cacheEntry->zValue);
1425
+ break;
1426
+ }
1427
+ cacheEntry = cacheEntry->next;
1428
+ }
1429
+ /* Attempt to read value from file in checkout if there wasn't a cache hit
1430
+ ** and a checkout is open. */
1431
+ if( cacheEntry==0 ){
1432
+ Blob versionedPathname;
1433
+ char *zVersionedPathname;
1434
+ blob_zero(&versionedPathname);
1435
+ blob_appendf(&versionedPathname, "%s/.fossil-settings/%s",
1436
+ g.zLocalRoot, zName);
1437
+ zVersionedPathname = blob_str(&versionedPathname);
1438
+ if( file_size(zVersionedPathname)>=0 ){
1439
+ /* File exists, and contains the value for this setting. Load from
1440
+ ** the file. */
1441
+ Blob setting;
1442
+ blob_zero(&setting);
1443
+ if( blob_read_from_file(&setting, zVersionedPathname) >= 0 ){
1444
+ blob_trim(&setting); /* Avoid non-obvious problems with line endings
1445
+ ** on boolean properties */
1446
+ zVersionedSetting = strdup(blob_str(&setting));
1447
+ }
1448
+ blob_reset(&setting);
1449
+ /* See if there's a no-warn flag */
1450
+ blob_append(&versionedPathname, ".no-warn", -1);
1451
+ if( file_size(blob_str(&versionedPathname))>=0 ){
1452
+ noWarn = 1;
1453
+ }
1454
+ }
1455
+ blob_reset(&versionedPathname);
1456
+ /* Store result in cache, which can be the value or 0 if not found */
1457
+ cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry));
1458
+ cacheEntry->next = cache;
1459
+ cacheEntry->zName = zName;
1460
+ cacheEntry->zValue = fossil_strdup(zVersionedSetting);
1461
+ cache = cacheEntry;
1462
+ }
1463
+ /* Display a warning? */
1464
+ if( zVersionedSetting!=0 && zNonVersionedSetting!=0
1465
+ && zNonVersionedSetting[0]!='\0' && !noWarn
1466
+ ){
1467
+ /* There's a versioned setting, and a non-versioned setting. Tell
1468
+ ** the user about the conflict */
1469
+ fossil_warning(
1470
+ "setting %s has both versioned and non-versioned values: using "
1471
+ "versioned value from file .fossil-settings/%s (to silence this "
1472
+ "warning, either create an empty file named "
1473
+ ".fossil-settings/%s.no-warn or delete the non-versioned setting "
1474
+ " with \"fossil unset %s\")", zName, zName, zName, zName
1475
+ );
1476
+ }
1477
+ /* Prefer the versioned setting */
1478
+ return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting;
1479
+}
1480
+
13971481
13981482
/*
13991483
** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
14001484
** repository and local databases.
14011485
*/
14021486
char *db_get(const char *zName, char *zDefault){
14031487
char *z = 0;
1488
+ int i;
1489
+ const struct stControlSettings *ctrlSetting = 0;
1490
+ /* Is this a setting? */
1491
+ for(i=0; ctrlSettings[i].name; i++){
1492
+ if( strcmp(ctrlSettings[i].name, zName)==0 ){
1493
+ ctrlSetting = &(ctrlSettings[i]);
1494
+ break;
1495
+ }
1496
+ }
14041497
if( g.repositoryOpen ){
14051498
z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
14061499
}
14071500
if( z==0 && g.configOpen ){
14081501
db_swap_connections();
14091502
z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
14101503
db_swap_connections();
1504
+ }
1505
+ if( ctrlSetting!=0 && ctrlSetting->versionable && g.localOpen ){
1506
+ /* This is a versionable setting, try and get the info from a checked out file */
1507
+ z = db_get_do_versionable(zName, z);
14111508
}
14121509
if( z==0 ){
14131510
z = zDefault;
14141511
}
14151512
return z;
@@ -1596,30 +1693,39 @@
15961693
}
15971694
15981695
/*
15991696
** Print the value of a setting named zName
16001697
*/
1601
-static void print_setting(const char *zName){
1698
+static void print_setting(const struct stControlSettings *ctrlSetting, int localOpen){
16021699
Stmt q;
16031700
if( g.repositoryOpen ){
16041701
db_prepare(&q,
16051702
"SELECT '(local)', value FROM config WHERE name=%Q"
16061703
" UNION ALL "
16071704
"SELECT '(global)', value FROM global_config WHERE name=%Q",
1608
- zName, zName
1705
+ ctrlSetting->name, ctrlSetting->name
16091706
);
16101707
}else{
16111708
db_prepare(&q,
16121709
"SELECT '(global)', value FROM global_config WHERE name=%Q",
1613
- zName
1710
+ ctrlSetting->name
16141711
);
16151712
}
16161713
if( db_step(&q)==SQLITE_ROW ){
1617
- fossil_print("%-20s %-8s %s\n", zName, db_column_text(&q, 0),
1714
+ fossil_print("%-20s %-8s %s\n", ctrlSetting->name, db_column_text(&q, 0),
16181715
db_column_text(&q, 1));
16191716
}else{
1620
- fossil_print("%-20s\n", zName);
1717
+ fossil_print("%-20s\n", ctrlSetting->name);
1718
+ }
1719
+ if( ctrlSetting->versionable && localOpen ){
1720
+ /* Check to see if this is overridden by a versionable settings file */
1721
+ Blob versionedPathname;
1722
+ blob_zero(&versionedPathname);
1723
+ blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", g.zLocalRoot, ctrlSetting->name);
1724
+ if( file_size(blob_str(&versionedPathname))>=0 ){
1725
+ fossil_print(" (overridden by contents of file .fossil-settings/%s)\n", ctrlSetting->name);
1726
+ }
16211727
}
16221728
db_finalize(&q);
16231729
}
16241730
16251731
@@ -1635,42 +1741,49 @@
16351741
#if INTERFACE
16361742
struct stControlSettings {
16371743
char const *name; /* Name of the setting */
16381744
char const *var; /* Internal variable name used by db_set() */
16391745
int width; /* Width of display. 0 for boolean values */
1746
+ int versionable; /* Is this setting versionable? */
16401747
char const *def; /* Default value */
16411748
};
16421749
#endif /* INTERFACE */
16431750
struct stControlSettings const ctrlSettings[] = {
1644
- { "access-log", 0, 0, "off" },
1645
- { "auto-captcha", "autocaptcha", 0, "on" },
1646
- { "auto-shun", 0, 0, "on" },
1647
- { "autosync", 0, 0, "on" },
1648
- { "binary-glob", 0, 32, "" },
1649
- { "clearsign", 0, 0, "off" },
1650
- { "crnl-glob", 0, 16, "" },
1651
- { "default-perms", 0, 16, "u" },
1652
- { "diff-command", 0, 16, "" },
1653
- { "dont-push", 0, 0, "off" },
1654
- { "editor", 0, 16, "" },
1655
- { "gdiff-command", 0, 16, "gdiff" },
1656
- { "gmerge-command",0, 40, "" },
1657
- { "https-login", 0, 0, "off" },
1658
- { "ignore-glob", 0, 40, "" },
1659
- { "http-port", 0, 16, "8080" },
1660
- { "localauth", 0, 0, "off" },
1661
- { "main-branch", 0, 40, "trunk" },
1662
- { "manifest", 0, 0, "off" },
1663
- { "max-upload", 0, 25, "250000" },
1664
- { "mtime-changes", 0, 0, "on" },
1665
- { "pgp-command", 0, 32, "gpg --clearsign -o " },
1666
- { "proxy", 0, 32, "off" },
1667
- { "repo-cksum", 0, 0, "on" },
1668
- { "self-register", 0, 0, "off" },
1669
- { "ssh-command", 0, 32, "" },
1670
- { "web-browser", 0, 32, "" },
1671
- { 0,0,0,0 }
1751
+ { "access-log", 0, 0, 0, "off" },
1752
+ { "auto-captcha", "autocaptcha", 0, 0, "on" },
1753
+ { "auto-shun", 0, 0, 0, "on" },
1754
+ { "autosync", 0, 0, 0, "on" },
1755
+ { "binary-glob", 0, 32, 1, "" },
1756
+ { "clearsign", 0, 0, 0, "off" },
1757
+ { "case-sensitive",0, 0, 0, "on" },
1758
+ { "crnl-glob", 0, 16, 1, "" },
1759
+ { "default-perms", 0, 16, 0, "u" },
1760
+ { "diff-command", 0, 16, 0, "" },
1761
+ { "dont-push", 0, 0, 0, "off" },
1762
+ { "editor", 0, 16, 0, "" },
1763
+ { "gdiff-command", 0, 16, 0, "gdiff" },
1764
+ { "gmerge-command",0, 40, 0, "" },
1765
+ { "https-login", 0, 0, 0, "off" },
1766
+ { "ignore-glob", 0, 40, 1, "" },
1767
+ { "empty-dirs", 0, 40, 1, "" },
1768
+ { "http-port", 0, 16, 0, "8080" },
1769
+ { "localauth", 0, 0, 0, "off" },
1770
+ { "main-branch", 0, 40, 0, "trunk" },
1771
+ { "manifest", 0, 0, 1, "off" },
1772
+ { "max-upload", 0, 25, 0, "250000" },
1773
+ { "mtime-changes", 0, 0, 0, "on" },
1774
+ { "pgp-command", 0, 32, 0, "gpg --clearsign -o " },
1775
+ { "proxy", 0, 32, 0, "off" },
1776
+ { "relative-paths",0, 0, 0, "on" },
1777
+ { "repo-cksum", 0, 0, 0, "on" },
1778
+ { "self-register", 0, 0, 0, "off" },
1779
+ { "ssl-ca-location",0, 40, 0, "" },
1780
+ { "ssl-identity", 0, 40, 0, "" },
1781
+ { "ssh-command", 0, 32, 0, "" },
1782
+ { "web-browser", 0, 32, 0, "" },
1783
+ { "white-foreground", 0, 0, 0, "off" },
1784
+ { 0,0,0,0,0 }
16721785
};
16731786
16741787
/*
16751788
** COMMAND: settings
16761789
** COMMAND: unset
@@ -1679,10 +1792,14 @@
16791792
** %fossil unset PROPERTY ?-global?
16801793
**
16811794
** The "settings" command with no arguments lists all properties and their
16821795
** values. With just a property name it shows the value of that property.
16831796
** With a value argument it changes the property for the current repository.
1797
+**
1798
+** Settings marked as versionable are overridden by the contents of the
1799
+** file named .fossil-settings/PROPERTY in the checked out files, if that
1800
+** file exists.
16841801
**
16851802
** The "unset" command clears a property setting.
16861803
**
16871804
**
16881805
** auto-captcha If enabled, the Login page provides a button to
@@ -1696,20 +1813,25 @@
16961813
** or update and automatically push after commit or
16971814
** tag or branch creation. If the value is "pullonly"
16981815
** then only pull operations occur automatically.
16991816
** Default: on
17001817
**
1701
-** binary-glob The VALUE is a comma-separated list of GLOB patterns
1702
-** that should be treated as binary files for merging
1703
-** purposes. Example: *.xml
1818
+** binary-glob The VALUE is a comma or newline-separated list of
1819
+** (versionable) GLOB patterns that should be treated as binary files
1820
+** for merging purposes. Example: *.xml
1821
+**
1822
+** case-sensitive If TRUE, the files whose names differ only in case
1823
+** care considered distinct. If FALSE files whose names
1824
+** differ only in case are the same file. Defaults to
1825
+** TRUE for unix and FALSE for windows and mac.
17041826
**
17051827
** clearsign When enabled, fossil will attempt to sign all commits
17061828
** with gpg. When disabled (the default), commits will
17071829
** be unsigned. Default: off
17081830
**
1709
-** crnl-glob A comma-separated list of GLOB patterns for text files
1710
-** in which it is ok to have CR+NL line endings.
1831
+** crnl-glob A comma or newline-separated list of GLOB patterns for
1832
+** (versionable) text files in which it is ok to have CR+NL line endings.
17111833
** Set to "*" to disable CR+NL checking.
17121834
**
17131835
** default-perms Permissions given automatically to new users. For more
17141836
** information on permissions see Users page in Server
17151837
** Administration of the HTTP UI. Default: u.
@@ -1717,10 +1839,15 @@
17171839
** diff-command External command to run when performing a diff.
17181840
** If undefined, the internal text diff will be used.
17191841
**
17201842
** dont-push Prevent this repository from pushing from client to
17211843
** server. Useful when setting up a private branch.
1844
+**
1845
+** empty-dirs A comma or newline-separated list of pathnames. On
1846
+** (versionable) update and checkout commands, if no file or directory
1847
+** exists with that name, an empty directory will be
1848
+** created.
17221849
**
17231850
** editor Text editor command used for check-in comments.
17241851
**
17251852
** gdiff-command External command to run when performing a graphical
17261853
** diff. If undefined, text diff will be used.
@@ -1735,23 +1862,23 @@
17351862
** and "ui" commands. Default: 8080
17361863
**
17371864
** https-login Send login creditials using HTTPS instead of HTTP
17381865
** even if the login page request came via HTTP.
17391866
**
1740
-** ignore-glob The VALUE is a comma-separated list of GLOB patterns
1741
-** specifying files that the "extra" command will ignore.
1742
-** Example: *.o,*.obj,*.exe
1867
+** ignore-glob The VALUE is a comma or newline-separated list of GLOB
1868
+** (versionable) patterns specifying files that the "extra" command will
1869
+** ignore. Example: *.o,*.obj,*.exe
17431870
**
17441871
** localauth If enabled, require that HTTP connections from
17451872
** 127.0.0.1 be authenticated by password. If
17461873
** false, all HTTP requests from localhost have
17471874
** unrestricted access to the repository.
17481875
**
17491876
** main-branch The primary branch for the project. Default: trunk
17501877
**
17511878
** manifest If enabled, automatically create files "manifest" and
1752
-** "manifest.uuid" in every checkout. The SQLite and
1879
+** (versionable) "manifest.uuid" in every checkout. The SQLite and
17531880
** Fossil repositories both require this. Default: off.
17541881
**
17551882
** max-upload A limit on the size of uplink HTTP requests. The
17561883
** default is 250000 bytes.
17571884
**
@@ -1763,10 +1890,13 @@
17631890
**
17641891
** proxy URL of the HTTP proxy. If undefined or "off" then
17651892
** the "http_proxy" environment variable is consulted.
17661893
** If the http_proxy environment variable is undefined
17671894
** then a direct HTTP connection is used.
1895
+**
1896
+** relative-paths When showing changes and extras, report paths relative
1897
+** to the current working directory. Default: "on"
17681898
**
17691899
** repo-cksum Compute checksums over all files in each checkout
17701900
** as a double-check of correctness. Defaults to "on".
17711901
** Disable on large repositories for a performance
17721902
** improvement.
@@ -1773,10 +1903,28 @@
17731903
**
17741904
** self-register Allow users to register themselves through the HTTP UI.
17751905
** This is useful if you want to see other names than
17761906
** "Anonymous" in e.g. ticketing system. On the other hand
17771907
** users can not be deleted. Default: off.
1908
+**
1909
+** ssl-ca-location The full pathname to a file containing PEM encoded
1910
+** CA root certificates, or a directory of certificates
1911
+** with filenames formed from the certificate hashes as
1912
+** required by OpenSSL.
1913
+** If set, this will override the OS default list of
1914
+** OpenSSL CAs. If unset, the default list will be used.
1915
+** Some platforms may add additional certificates.
1916
+** Check your platform behaviour is as required if the
1917
+** exact contents of the CA root is critical for your
1918
+** application.
1919
+**
1920
+** ssl-identity The full pathname to a file containing a certificate
1921
+** and private key in PEM format. Create by concatenating
1922
+** the certificate and private key files.
1923
+** This identity will be presented to SSL servers to
1924
+** authenticate this client, in addition to the normal
1925
+** password authentication.
17781926
**
17791927
** ssh-command Command used to talk to a remote machine with
17801928
** the "ssh://" protocol.
17811929
**
17821930
** web-browser A shell command used to launch your preferred
@@ -1797,12 +1945,13 @@
17971945
}
17981946
if( unsetFlag && g.argc!=3 ){
17991947
usage("PROPERTY ?-global?");
18001948
}
18011949
if( g.argc==2 ){
1950
+ int openLocal = db_open_local();
18021951
for(i=0; ctrlSettings[i].name; i++){
1803
- print_setting(ctrlSettings[i].name);
1952
+ print_setting(&ctrlSettings[i], openLocal);
18041953
}
18051954
}else if( g.argc==3 || g.argc==4 ){
18061955
const char *zName = g.argv[2];
18071956
int isManifest;
18081957
int n = strlen(zName);
@@ -1820,13 +1969,13 @@
18201969
db_unset(ctrlSettings[i].name, globalFlag);
18211970
}else if( g.argc==4 ){
18221971
db_set(ctrlSettings[i].name, g.argv[3], globalFlag);
18231972
}else{
18241973
isManifest = 0;
1825
- print_setting(ctrlSettings[i].name);
1974
+ print_setting(&ctrlSettings[i], db_open_local());
18261975
}
1827
- if( isManifest ){
1976
+ if( isManifest && g.localOpen ){
18281977
manifest_to_disk(db_lget_int("checkout", 0));
18291978
}
18301979
}else{
18311980
usage("?PROPERTY? ?VALUE?");
18321981
}
18331982
--- src/db.c
+++ src/db.c
@@ -153,13 +153,17 @@
153 ** Force a rollback and shutdown the database
154 */
155 void db_force_rollback(void){
156 int i;
157 static int busy = 0;
 
158 if( busy || g.db==0 ) return;
159 busy = 1;
160 undo_rollback();
 
 
 
161 while( pAllStmt ){
162 db_finalize(pAllStmt);
163 }
164 if( nBegin ){
165 sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
@@ -809,10 +813,11 @@
809 static const char *aDbName[] = { "/_FOSSIL_", "/.fos" };
810
811 if( g.localOpen) return 1;
812 file_getcwd(zPwd, sizeof(zPwd)-20);
813 n = strlen(zPwd);
 
814 while( n>0 ){
815 if( file_access(zPwd, W_OK) ) break;
816 for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
817 sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
818 if( isValidLocalDb(zPwd) ){
@@ -1058,14 +1063,13 @@
1058
1059 /*
1060 ** Create the default user accounts in the USER table.
1061 */
1062 void db_create_default_users(int setupUserOnly, const char *zDefaultUser){
1063 const char *zUser;
1064 zUser = db_get("default-user", 0);
1065 if( zUser==0 ){
1066 zUser = zDefaultUser;
1067 }
1068 if( zUser==0 ){
1069 #if defined(_WIN32)
1070 zUser = getenv("USERNAME");
1071 #else
@@ -1074,12 +1078,15 @@
1074 }
1075 if( zUser==0 ){
1076 zUser = "root";
1077 }
1078 db_multi_exec(
1079 "INSERT INTO user(login, pw, cap, info)"
1080 "VALUES(%Q,lower(hex(randomblob(3))),'s','')", zUser
 
 
 
1081 );
1082 if( !setupUserOnly ){
1083 db_multi_exec(
1084 "INSERT INTO user(login,pw,cap,info)"
1085 " VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');"
@@ -1363,19 +1370,19 @@
1363 */
1364 int is_truth(const char *zVal){
1365 static const char *azOn[] = { "on", "yes", "true", "1" };
1366 int i;
1367 for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
1368 if( fossil_strcmp(zVal,azOn[i])==0 ) return 1;
1369 }
1370 return 0;
1371 }
1372 int is_false(const char *zVal){
1373 static const char *azOff[] = { "off", "no", "false", "0" };
1374 int i;
1375 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1376 if( fossil_strcmp(zVal,azOff[i])==0 ) return 1;
1377 }
1378 return 0;
1379 }
1380
1381 /*
@@ -1392,24 +1399,114 @@
1392 sqlite3 *dbTemp = g.db;
1393 g.db = g.dbConfig;
1394 g.dbConfig = dbTemp;
1395 }
1396 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1397
1398 /*
1399 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
1400 ** repository and local databases.
1401 */
1402 char *db_get(const char *zName, char *zDefault){
1403 char *z = 0;
 
 
 
 
 
 
 
 
 
1404 if( g.repositoryOpen ){
1405 z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
1406 }
1407 if( z==0 && g.configOpen ){
1408 db_swap_connections();
1409 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
1410 db_swap_connections();
 
 
 
 
1411 }
1412 if( z==0 ){
1413 z = zDefault;
1414 }
1415 return z;
@@ -1596,30 +1693,39 @@
1596 }
1597
1598 /*
1599 ** Print the value of a setting named zName
1600 */
1601 static void print_setting(const char *zName){
1602 Stmt q;
1603 if( g.repositoryOpen ){
1604 db_prepare(&q,
1605 "SELECT '(local)', value FROM config WHERE name=%Q"
1606 " UNION ALL "
1607 "SELECT '(global)', value FROM global_config WHERE name=%Q",
1608 zName, zName
1609 );
1610 }else{
1611 db_prepare(&q,
1612 "SELECT '(global)', value FROM global_config WHERE name=%Q",
1613 zName
1614 );
1615 }
1616 if( db_step(&q)==SQLITE_ROW ){
1617 fossil_print("%-20s %-8s %s\n", zName, db_column_text(&q, 0),
1618 db_column_text(&q, 1));
1619 }else{
1620 fossil_print("%-20s\n", zName);
 
 
 
 
 
 
 
 
 
1621 }
1622 db_finalize(&q);
1623 }
1624
1625
@@ -1635,42 +1741,49 @@
1635 #if INTERFACE
1636 struct stControlSettings {
1637 char const *name; /* Name of the setting */
1638 char const *var; /* Internal variable name used by db_set() */
1639 int width; /* Width of display. 0 for boolean values */
 
1640 char const *def; /* Default value */
1641 };
1642 #endif /* INTERFACE */
1643 struct stControlSettings const ctrlSettings[] = {
1644 { "access-log", 0, 0, "off" },
1645 { "auto-captcha", "autocaptcha", 0, "on" },
1646 { "auto-shun", 0, 0, "on" },
1647 { "autosync", 0, 0, "on" },
1648 { "binary-glob", 0, 32, "" },
1649 { "clearsign", 0, 0, "off" },
1650 { "crnl-glob", 0, 16, "" },
1651 { "default-perms", 0, 16, "u" },
1652 { "diff-command", 0, 16, "" },
1653 { "dont-push", 0, 0, "off" },
1654 { "editor", 0, 16, "" },
1655 { "gdiff-command", 0, 16, "gdiff" },
1656 { "gmerge-command",0, 40, "" },
1657 { "https-login", 0, 0, "off" },
1658 { "ignore-glob", 0, 40, "" },
1659 { "http-port", 0, 16, "8080" },
1660 { "localauth", 0, 0, "off" },
1661 { "main-branch", 0, 40, "trunk" },
1662 { "manifest", 0, 0, "off" },
1663 { "max-upload", 0, 25, "250000" },
1664 { "mtime-changes", 0, 0, "on" },
1665 { "pgp-command", 0, 32, "gpg --clearsign -o " },
1666 { "proxy", 0, 32, "off" },
1667 { "repo-cksum", 0, 0, "on" },
1668 { "self-register", 0, 0, "off" },
1669 { "ssh-command", 0, 32, "" },
1670 { "web-browser", 0, 32, "" },
1671 { 0,0,0,0 }
 
 
 
 
 
 
1672 };
1673
1674 /*
1675 ** COMMAND: settings
1676 ** COMMAND: unset
@@ -1679,10 +1792,14 @@
1679 ** %fossil unset PROPERTY ?-global?
1680 **
1681 ** The "settings" command with no arguments lists all properties and their
1682 ** values. With just a property name it shows the value of that property.
1683 ** With a value argument it changes the property for the current repository.
 
 
 
 
1684 **
1685 ** The "unset" command clears a property setting.
1686 **
1687 **
1688 ** auto-captcha If enabled, the Login page provides a button to
@@ -1696,20 +1813,25 @@
1696 ** or update and automatically push after commit or
1697 ** tag or branch creation. If the value is "pullonly"
1698 ** then only pull operations occur automatically.
1699 ** Default: on
1700 **
1701 ** binary-glob The VALUE is a comma-separated list of GLOB patterns
1702 ** that should be treated as binary files for merging
1703 ** purposes. Example: *.xml
 
 
 
 
 
1704 **
1705 ** clearsign When enabled, fossil will attempt to sign all commits
1706 ** with gpg. When disabled (the default), commits will
1707 ** be unsigned. Default: off
1708 **
1709 ** crnl-glob A comma-separated list of GLOB patterns for text files
1710 ** in which it is ok to have CR+NL line endings.
1711 ** Set to "*" to disable CR+NL checking.
1712 **
1713 ** default-perms Permissions given automatically to new users. For more
1714 ** information on permissions see Users page in Server
1715 ** Administration of the HTTP UI. Default: u.
@@ -1717,10 +1839,15 @@
1717 ** diff-command External command to run when performing a diff.
1718 ** If undefined, the internal text diff will be used.
1719 **
1720 ** dont-push Prevent this repository from pushing from client to
1721 ** server. Useful when setting up a private branch.
 
 
 
 
 
1722 **
1723 ** editor Text editor command used for check-in comments.
1724 **
1725 ** gdiff-command External command to run when performing a graphical
1726 ** diff. If undefined, text diff will be used.
@@ -1735,23 +1862,23 @@
1735 ** and "ui" commands. Default: 8080
1736 **
1737 ** https-login Send login creditials using HTTPS instead of HTTP
1738 ** even if the login page request came via HTTP.
1739 **
1740 ** ignore-glob The VALUE is a comma-separated list of GLOB patterns
1741 ** specifying files that the "extra" command will ignore.
1742 ** Example: *.o,*.obj,*.exe
1743 **
1744 ** localauth If enabled, require that HTTP connections from
1745 ** 127.0.0.1 be authenticated by password. If
1746 ** false, all HTTP requests from localhost have
1747 ** unrestricted access to the repository.
1748 **
1749 ** main-branch The primary branch for the project. Default: trunk
1750 **
1751 ** manifest If enabled, automatically create files "manifest" and
1752 ** "manifest.uuid" in every checkout. The SQLite and
1753 ** Fossil repositories both require this. Default: off.
1754 **
1755 ** max-upload A limit on the size of uplink HTTP requests. The
1756 ** default is 250000 bytes.
1757 **
@@ -1763,10 +1890,13 @@
1763 **
1764 ** proxy URL of the HTTP proxy. If undefined or "off" then
1765 ** the "http_proxy" environment variable is consulted.
1766 ** If the http_proxy environment variable is undefined
1767 ** then a direct HTTP connection is used.
 
 
 
1768 **
1769 ** repo-cksum Compute checksums over all files in each checkout
1770 ** as a double-check of correctness. Defaults to "on".
1771 ** Disable on large repositories for a performance
1772 ** improvement.
@@ -1773,10 +1903,28 @@
1773 **
1774 ** self-register Allow users to register themselves through the HTTP UI.
1775 ** This is useful if you want to see other names than
1776 ** "Anonymous" in e.g. ticketing system. On the other hand
1777 ** users can not be deleted. Default: off.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1778 **
1779 ** ssh-command Command used to talk to a remote machine with
1780 ** the "ssh://" protocol.
1781 **
1782 ** web-browser A shell command used to launch your preferred
@@ -1797,12 +1945,13 @@
1797 }
1798 if( unsetFlag && g.argc!=3 ){
1799 usage("PROPERTY ?-global?");
1800 }
1801 if( g.argc==2 ){
 
1802 for(i=0; ctrlSettings[i].name; i++){
1803 print_setting(ctrlSettings[i].name);
1804 }
1805 }else if( g.argc==3 || g.argc==4 ){
1806 const char *zName = g.argv[2];
1807 int isManifest;
1808 int n = strlen(zName);
@@ -1820,13 +1969,13 @@
1820 db_unset(ctrlSettings[i].name, globalFlag);
1821 }else if( g.argc==4 ){
1822 db_set(ctrlSettings[i].name, g.argv[3], globalFlag);
1823 }else{
1824 isManifest = 0;
1825 print_setting(ctrlSettings[i].name);
1826 }
1827 if( isManifest ){
1828 manifest_to_disk(db_lget_int("checkout", 0));
1829 }
1830 }else{
1831 usage("?PROPERTY? ?VALUE?");
1832 }
1833
--- src/db.c
+++ src/db.c
@@ -153,13 +153,17 @@
153 ** Force a rollback and shutdown the database
154 */
155 void db_force_rollback(void){
156 int i;
157 static int busy = 0;
158 sqlite3_stmt *pStmt = 0;
159 if( busy || g.db==0 ) return;
160 busy = 1;
161 undo_rollback();
162 while( (pStmt = sqlite3_next_stmt(g.db,pStmt))!=0 ){
163 sqlite3_reset(pStmt);
164 }
165 while( pAllStmt ){
166 db_finalize(pAllStmt);
167 }
168 if( nBegin ){
169 sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
@@ -809,10 +813,11 @@
813 static const char *aDbName[] = { "/_FOSSIL_", "/.fos" };
814
815 if( g.localOpen) return 1;
816 file_getcwd(zPwd, sizeof(zPwd)-20);
817 n = strlen(zPwd);
818 if( n==1 && zPwd[0]=='/' ) zPwd[0] = '.';
819 while( n>0 ){
820 if( file_access(zPwd, W_OK) ) break;
821 for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
822 sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
823 if( isValidLocalDb(zPwd) ){
@@ -1058,14 +1063,13 @@
1063
1064 /*
1065 ** Create the default user accounts in the USER table.
1066 */
1067 void db_create_default_users(int setupUserOnly, const char *zDefaultUser){
1068 const char *zUser = zDefaultUser;
 
1069 if( zUser==0 ){
1070 zUser = db_get("default-user", 0);
1071 }
1072 if( zUser==0 ){
1073 #if defined(_WIN32)
1074 zUser = getenv("USERNAME");
1075 #else
@@ -1074,12 +1078,15 @@
1078 }
1079 if( zUser==0 ){
1080 zUser = "root";
1081 }
1082 db_multi_exec(
1083 "INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
1084 );
1085 db_multi_exec(
1086 "UPDATE user SET cap='s', pw=lower(hex(randomblob(3)))"
1087 " WHERE login=%Q", zUser
1088 );
1089 if( !setupUserOnly ){
1090 db_multi_exec(
1091 "INSERT INTO user(login,pw,cap,info)"
1092 " VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');"
@@ -1363,19 +1370,19 @@
1370 */
1371 int is_truth(const char *zVal){
1372 static const char *azOn[] = { "on", "yes", "true", "1" };
1373 int i;
1374 for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
1375 if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
1376 }
1377 return 0;
1378 }
1379 int is_false(const char *zVal){
1380 static const char *azOff[] = { "off", "no", "false", "0" };
1381 int i;
1382 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1383 if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
1384 }
1385 return 0;
1386 }
1387
1388 /*
@@ -1392,24 +1399,114 @@
1399 sqlite3 *dbTemp = g.db;
1400 g.db = g.dbConfig;
1401 g.dbConfig = dbTemp;
1402 }
1403 }
1404
1405 /*
1406 ** Logic for reading potentially versioned settings from
1407 ** .fossil-settings/<name> , and emits warnings if necessary.
1408 ** Returns the non-versioned value without modification if there is no
1409 ** versioned value.
1410 */
1411 static char *db_get_do_versionable(const char *zName, char *zNonVersionedSetting){
1412 char *zVersionedSetting = 0;
1413 int noWarn = 0;
1414 struct _cacheEntry {
1415 struct _cacheEntry *next;
1416 const char *zName, *zValue;
1417 } *cacheEntry = 0;
1418 static struct _cacheEntry *cache = 0;
1419
1420 /* Look up name in cache */
1421 cacheEntry = cache;
1422 while( cacheEntry!=0 ){
1423 if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
1424 zVersionedSetting = fossil_strdup(cacheEntry->zValue);
1425 break;
1426 }
1427 cacheEntry = cacheEntry->next;
1428 }
1429 /* Attempt to read value from file in checkout if there wasn't a cache hit
1430 ** and a checkout is open. */
1431 if( cacheEntry==0 ){
1432 Blob versionedPathname;
1433 char *zVersionedPathname;
1434 blob_zero(&versionedPathname);
1435 blob_appendf(&versionedPathname, "%s/.fossil-settings/%s",
1436 g.zLocalRoot, zName);
1437 zVersionedPathname = blob_str(&versionedPathname);
1438 if( file_size(zVersionedPathname)>=0 ){
1439 /* File exists, and contains the value for this setting. Load from
1440 ** the file. */
1441 Blob setting;
1442 blob_zero(&setting);
1443 if( blob_read_from_file(&setting, zVersionedPathname) >= 0 ){
1444 blob_trim(&setting); /* Avoid non-obvious problems with line endings
1445 ** on boolean properties */
1446 zVersionedSetting = strdup(blob_str(&setting));
1447 }
1448 blob_reset(&setting);
1449 /* See if there's a no-warn flag */
1450 blob_append(&versionedPathname, ".no-warn", -1);
1451 if( file_size(blob_str(&versionedPathname))>=0 ){
1452 noWarn = 1;
1453 }
1454 }
1455 blob_reset(&versionedPathname);
1456 /* Store result in cache, which can be the value or 0 if not found */
1457 cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry));
1458 cacheEntry->next = cache;
1459 cacheEntry->zName = zName;
1460 cacheEntry->zValue = fossil_strdup(zVersionedSetting);
1461 cache = cacheEntry;
1462 }
1463 /* Display a warning? */
1464 if( zVersionedSetting!=0 && zNonVersionedSetting!=0
1465 && zNonVersionedSetting[0]!='\0' && !noWarn
1466 ){
1467 /* There's a versioned setting, and a non-versioned setting. Tell
1468 ** the user about the conflict */
1469 fossil_warning(
1470 "setting %s has both versioned and non-versioned values: using "
1471 "versioned value from file .fossil-settings/%s (to silence this "
1472 "warning, either create an empty file named "
1473 ".fossil-settings/%s.no-warn or delete the non-versioned setting "
1474 " with \"fossil unset %s\")", zName, zName, zName, zName
1475 );
1476 }
1477 /* Prefer the versioned setting */
1478 return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting;
1479 }
1480
1481
1482 /*
1483 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
1484 ** repository and local databases.
1485 */
1486 char *db_get(const char *zName, char *zDefault){
1487 char *z = 0;
1488 int i;
1489 const struct stControlSettings *ctrlSetting = 0;
1490 /* Is this a setting? */
1491 for(i=0; ctrlSettings[i].name; i++){
1492 if( strcmp(ctrlSettings[i].name, zName)==0 ){
1493 ctrlSetting = &(ctrlSettings[i]);
1494 break;
1495 }
1496 }
1497 if( g.repositoryOpen ){
1498 z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
1499 }
1500 if( z==0 && g.configOpen ){
1501 db_swap_connections();
1502 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
1503 db_swap_connections();
1504 }
1505 if( ctrlSetting!=0 && ctrlSetting->versionable && g.localOpen ){
1506 /* This is a versionable setting, try and get the info from a checked out file */
1507 z = db_get_do_versionable(zName, z);
1508 }
1509 if( z==0 ){
1510 z = zDefault;
1511 }
1512 return z;
@@ -1596,30 +1693,39 @@
1693 }
1694
1695 /*
1696 ** Print the value of a setting named zName
1697 */
1698 static void print_setting(const struct stControlSettings *ctrlSetting, int localOpen){
1699 Stmt q;
1700 if( g.repositoryOpen ){
1701 db_prepare(&q,
1702 "SELECT '(local)', value FROM config WHERE name=%Q"
1703 " UNION ALL "
1704 "SELECT '(global)', value FROM global_config WHERE name=%Q",
1705 ctrlSetting->name, ctrlSetting->name
1706 );
1707 }else{
1708 db_prepare(&q,
1709 "SELECT '(global)', value FROM global_config WHERE name=%Q",
1710 ctrlSetting->name
1711 );
1712 }
1713 if( db_step(&q)==SQLITE_ROW ){
1714 fossil_print("%-20s %-8s %s\n", ctrlSetting->name, db_column_text(&q, 0),
1715 db_column_text(&q, 1));
1716 }else{
1717 fossil_print("%-20s\n", ctrlSetting->name);
1718 }
1719 if( ctrlSetting->versionable && localOpen ){
1720 /* Check to see if this is overridden by a versionable settings file */
1721 Blob versionedPathname;
1722 blob_zero(&versionedPathname);
1723 blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", g.zLocalRoot, ctrlSetting->name);
1724 if( file_size(blob_str(&versionedPathname))>=0 ){
1725 fossil_print(" (overridden by contents of file .fossil-settings/%s)\n", ctrlSetting->name);
1726 }
1727 }
1728 db_finalize(&q);
1729 }
1730
1731
@@ -1635,42 +1741,49 @@
1741 #if INTERFACE
1742 struct stControlSettings {
1743 char const *name; /* Name of the setting */
1744 char const *var; /* Internal variable name used by db_set() */
1745 int width; /* Width of display. 0 for boolean values */
1746 int versionable; /* Is this setting versionable? */
1747 char const *def; /* Default value */
1748 };
1749 #endif /* INTERFACE */
1750 struct stControlSettings const ctrlSettings[] = {
1751 { "access-log", 0, 0, 0, "off" },
1752 { "auto-captcha", "autocaptcha", 0, 0, "on" },
1753 { "auto-shun", 0, 0, 0, "on" },
1754 { "autosync", 0, 0, 0, "on" },
1755 { "binary-glob", 0, 32, 1, "" },
1756 { "clearsign", 0, 0, 0, "off" },
1757 { "case-sensitive",0, 0, 0, "on" },
1758 { "crnl-glob", 0, 16, 1, "" },
1759 { "default-perms", 0, 16, 0, "u" },
1760 { "diff-command", 0, 16, 0, "" },
1761 { "dont-push", 0, 0, 0, "off" },
1762 { "editor", 0, 16, 0, "" },
1763 { "gdiff-command", 0, 16, 0, "gdiff" },
1764 { "gmerge-command",0, 40, 0, "" },
1765 { "https-login", 0, 0, 0, "off" },
1766 { "ignore-glob", 0, 40, 1, "" },
1767 { "empty-dirs", 0, 40, 1, "" },
1768 { "http-port", 0, 16, 0, "8080" },
1769 { "localauth", 0, 0, 0, "off" },
1770 { "main-branch", 0, 40, 0, "trunk" },
1771 { "manifest", 0, 0, 1, "off" },
1772 { "max-upload", 0, 25, 0, "250000" },
1773 { "mtime-changes", 0, 0, 0, "on" },
1774 { "pgp-command", 0, 32, 0, "gpg --clearsign -o " },
1775 { "proxy", 0, 32, 0, "off" },
1776 { "relative-paths",0, 0, 0, "on" },
1777 { "repo-cksum", 0, 0, 0, "on" },
1778 { "self-register", 0, 0, 0, "off" },
1779 { "ssl-ca-location",0, 40, 0, "" },
1780 { "ssl-identity", 0, 40, 0, "" },
1781 { "ssh-command", 0, 32, 0, "" },
1782 { "web-browser", 0, 32, 0, "" },
1783 { "white-foreground", 0, 0, 0, "off" },
1784 { 0,0,0,0,0 }
1785 };
1786
1787 /*
1788 ** COMMAND: settings
1789 ** COMMAND: unset
@@ -1679,10 +1792,14 @@
1792 ** %fossil unset PROPERTY ?-global?
1793 **
1794 ** The "settings" command with no arguments lists all properties and their
1795 ** values. With just a property name it shows the value of that property.
1796 ** With a value argument it changes the property for the current repository.
1797 **
1798 ** Settings marked as versionable are overridden by the contents of the
1799 ** file named .fossil-settings/PROPERTY in the checked out files, if that
1800 ** file exists.
1801 **
1802 ** The "unset" command clears a property setting.
1803 **
1804 **
1805 ** auto-captcha If enabled, the Login page provides a button to
@@ -1696,20 +1813,25 @@
1813 ** or update and automatically push after commit or
1814 ** tag or branch creation. If the value is "pullonly"
1815 ** then only pull operations occur automatically.
1816 ** Default: on
1817 **
1818 ** binary-glob The VALUE is a comma or newline-separated list of
1819 ** (versionable) GLOB patterns that should be treated as binary files
1820 ** for merging purposes. Example: *.xml
1821 **
1822 ** case-sensitive If TRUE, the files whose names differ only in case
1823 ** care considered distinct. If FALSE files whose names
1824 ** differ only in case are the same file. Defaults to
1825 ** TRUE for unix and FALSE for windows and mac.
1826 **
1827 ** clearsign When enabled, fossil will attempt to sign all commits
1828 ** with gpg. When disabled (the default), commits will
1829 ** be unsigned. Default: off
1830 **
1831 ** crnl-glob A comma or newline-separated list of GLOB patterns for
1832 ** (versionable) text files in which it is ok to have CR+NL line endings.
1833 ** Set to "*" to disable CR+NL checking.
1834 **
1835 ** default-perms Permissions given automatically to new users. For more
1836 ** information on permissions see Users page in Server
1837 ** Administration of the HTTP UI. Default: u.
@@ -1717,10 +1839,15 @@
1839 ** diff-command External command to run when performing a diff.
1840 ** If undefined, the internal text diff will be used.
1841 **
1842 ** dont-push Prevent this repository from pushing from client to
1843 ** server. Useful when setting up a private branch.
1844 **
1845 ** empty-dirs A comma or newline-separated list of pathnames. On
1846 ** (versionable) update and checkout commands, if no file or directory
1847 ** exists with that name, an empty directory will be
1848 ** created.
1849 **
1850 ** editor Text editor command used for check-in comments.
1851 **
1852 ** gdiff-command External command to run when performing a graphical
1853 ** diff. If undefined, text diff will be used.
@@ -1735,23 +1862,23 @@
1862 ** and "ui" commands. Default: 8080
1863 **
1864 ** https-login Send login creditials using HTTPS instead of HTTP
1865 ** even if the login page request came via HTTP.
1866 **
1867 ** ignore-glob The VALUE is a comma or newline-separated list of GLOB
1868 ** (versionable) patterns specifying files that the "extra" command will
1869 ** ignore. Example: *.o,*.obj,*.exe
1870 **
1871 ** localauth If enabled, require that HTTP connections from
1872 ** 127.0.0.1 be authenticated by password. If
1873 ** false, all HTTP requests from localhost have
1874 ** unrestricted access to the repository.
1875 **
1876 ** main-branch The primary branch for the project. Default: trunk
1877 **
1878 ** manifest If enabled, automatically create files "manifest" and
1879 ** (versionable) "manifest.uuid" in every checkout. The SQLite and
1880 ** Fossil repositories both require this. Default: off.
1881 **
1882 ** max-upload A limit on the size of uplink HTTP requests. The
1883 ** default is 250000 bytes.
1884 **
@@ -1763,10 +1890,13 @@
1890 **
1891 ** proxy URL of the HTTP proxy. If undefined or "off" then
1892 ** the "http_proxy" environment variable is consulted.
1893 ** If the http_proxy environment variable is undefined
1894 ** then a direct HTTP connection is used.
1895 **
1896 ** relative-paths When showing changes and extras, report paths relative
1897 ** to the current working directory. Default: "on"
1898 **
1899 ** repo-cksum Compute checksums over all files in each checkout
1900 ** as a double-check of correctness. Defaults to "on".
1901 ** Disable on large repositories for a performance
1902 ** improvement.
@@ -1773,10 +1903,28 @@
1903 **
1904 ** self-register Allow users to register themselves through the HTTP UI.
1905 ** This is useful if you want to see other names than
1906 ** "Anonymous" in e.g. ticketing system. On the other hand
1907 ** users can not be deleted. Default: off.
1908 **
1909 ** ssl-ca-location The full pathname to a file containing PEM encoded
1910 ** CA root certificates, or a directory of certificates
1911 ** with filenames formed from the certificate hashes as
1912 ** required by OpenSSL.
1913 ** If set, this will override the OS default list of
1914 ** OpenSSL CAs. If unset, the default list will be used.
1915 ** Some platforms may add additional certificates.
1916 ** Check your platform behaviour is as required if the
1917 ** exact contents of the CA root is critical for your
1918 ** application.
1919 **
1920 ** ssl-identity The full pathname to a file containing a certificate
1921 ** and private key in PEM format. Create by concatenating
1922 ** the certificate and private key files.
1923 ** This identity will be presented to SSL servers to
1924 ** authenticate this client, in addition to the normal
1925 ** password authentication.
1926 **
1927 ** ssh-command Command used to talk to a remote machine with
1928 ** the "ssh://" protocol.
1929 **
1930 ** web-browser A shell command used to launch your preferred
@@ -1797,12 +1945,13 @@
1945 }
1946 if( unsetFlag && g.argc!=3 ){
1947 usage("PROPERTY ?-global?");
1948 }
1949 if( g.argc==2 ){
1950 int openLocal = db_open_local();
1951 for(i=0; ctrlSettings[i].name; i++){
1952 print_setting(&ctrlSettings[i], openLocal);
1953 }
1954 }else if( g.argc==3 || g.argc==4 ){
1955 const char *zName = g.argv[2];
1956 int isManifest;
1957 int n = strlen(zName);
@@ -1820,13 +1969,13 @@
1969 db_unset(ctrlSettings[i].name, globalFlag);
1970 }else if( g.argc==4 ){
1971 db_set(ctrlSettings[i].name, g.argv[3], globalFlag);
1972 }else{
1973 isManifest = 0;
1974 print_setting(&ctrlSettings[i], db_open_local());
1975 }
1976 if( isManifest && g.localOpen ){
1977 manifest_to_disk(db_lget_int("checkout", 0));
1978 }
1979 }else{
1980 usage("?PROPERTY? ?VALUE?");
1981 }
1982
--- src/descendants.c
+++ src/descendants.c
@@ -287,11 +287,11 @@
287287
"%s"
288288
" AND event.objid IN (SELECT rid FROM leaves)"
289289
" ORDER BY event.mtime DESC",
290290
timeline_query_for_tty()
291291
);
292
- print_timeline(&q, 20);
292
+ print_timeline(&q, 20, 0);
293293
db_finalize(&q);
294294
}
295295
296296
/*
297297
** COMMAND: leaves
@@ -322,11 +322,11 @@
322322
}else if( !showAll ){
323323
blob_appendf(&sql," AND NOT %z", leaf_is_closed_sql("blob.rid"));
324324
}
325325
db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_str(&sql));
326326
blob_reset(&sql);
327
- print_timeline(&q, 2000);
327
+ print_timeline(&q, 2000, 0);
328328
db_finalize(&q);
329329
}
330330
331331
/*
332332
** WEBPAGE: leaves
333333
--- src/descendants.c
+++ src/descendants.c
@@ -287,11 +287,11 @@
287 "%s"
288 " AND event.objid IN (SELECT rid FROM leaves)"
289 " ORDER BY event.mtime DESC",
290 timeline_query_for_tty()
291 );
292 print_timeline(&q, 20);
293 db_finalize(&q);
294 }
295
296 /*
297 ** COMMAND: leaves
@@ -322,11 +322,11 @@
322 }else if( !showAll ){
323 blob_appendf(&sql," AND NOT %z", leaf_is_closed_sql("blob.rid"));
324 }
325 db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_str(&sql));
326 blob_reset(&sql);
327 print_timeline(&q, 2000);
328 db_finalize(&q);
329 }
330
331 /*
332 ** WEBPAGE: leaves
333
--- src/descendants.c
+++ src/descendants.c
@@ -287,11 +287,11 @@
287 "%s"
288 " AND event.objid IN (SELECT rid FROM leaves)"
289 " ORDER BY event.mtime DESC",
290 timeline_query_for_tty()
291 );
292 print_timeline(&q, 20, 0);
293 db_finalize(&q);
294 }
295
296 /*
297 ** COMMAND: leaves
@@ -322,11 +322,11 @@
322 }else if( !showAll ){
323 blob_appendf(&sql," AND NOT %z", leaf_is_closed_sql("blob.rid"));
324 }
325 db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_str(&sql));
326 blob_reset(&sql);
327 print_timeline(&q, 2000, 0);
328 db_finalize(&q);
329 }
330
331 /*
332 ** WEBPAGE: leaves
333
+22 -16
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -175,23 +175,24 @@
175175
blob_reset(&cmd);
176176
}
177177
}
178178
179179
/*
180
-** Do a diff against a single file named in g.argv[2] from version zFrom
180
+** Do a diff against a single file named in zFileTreeName from version zFrom
181181
** against the same file on disk.
182182
*/
183183
static void diff_one_against_disk(
184184
const char *zFrom, /* Name of file */
185185
const char *zDiffCmd, /* Use this "diff" command */
186
- int ignoreEolWs /* Ignore whitespace changes at end of lines */
186
+ int ignoreEolWs, /* Ignore whitespace changes at end of lines */
187
+ const char *zFileTreeName
187188
){
188189
Blob fname;
189190
Blob content;
190
- file_tree_name(g.argv[2], &fname, 1);
191
+ file_tree_name(zFileTreeName, &fname, 1);
191192
historical_version_of_file(zFrom, blob_str(&fname), &content, 0, 0);
192
- diff_file(&content, g.argv[2], g.argv[2], zDiffCmd, ignoreEolWs);
193
+ diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, ignoreEolWs);
193194
blob_reset(&content);
194195
blob_reset(&fname);
195196
}
196197
197198
/*
@@ -295,22 +296,22 @@
295296
}
296297
297298
/*
298299
** Output the differences between two versions of a single file.
299300
** zFrom and zTo are the check-ins containing the two file versions.
300
-** The filename is contained in g.argv[2].
301301
*/
302302
static void diff_one_two_versions(
303303
const char *zFrom,
304304
const char *zTo,
305305
const char *zDiffCmd,
306
- int ignoreEolWs
306
+ int ignoreEolWs,
307
+ const char *zFileTreeName
307308
){
308309
char *zName;
309310
Blob fname;
310311
Blob v1, v2;
311
- file_tree_name(g.argv[2], &fname, 1);
312
+ file_tree_name(zFileTreeName, &fname, 1);
312313
zName = blob_str(&fname);
313314
historical_version_of_file(zFrom, zName, &v1, 0, 0);
314315
historical_version_of_file(zTo, zName, &v2, 0, 0);
315316
diff_file_mem(&v1, &v2, zName, zDiffCmd, ignoreEolWs);
316317
blob_reset(&v1);
@@ -408,16 +409,16 @@
408409
409410
/*
410411
** COMMAND: diff
411412
** COMMAND: gdiff
412413
**
413
-** Usage: %fossil diff|gdiff ?options? ?FILE?
414
+** Usage: %fossil diff|gdiff ?options? ?FILE1? ?FILE2 ...?
414415
**
415
-** Show the difference between the current version of FILE (as it
416
-** exists on disk) and that same file as it was checked out. Or
417
-** if the FILE argument is omitted, show the unsaved changed currently
418
-** in the working check-out.
416
+** Show the difference between the current version of each of the FILEs
417
+** specified (as they exist on disk) and that same file as it was checked
418
+** out. Or if the FILE arguments are omitted, show the unsaved changed
419
+** currently in the working check-out.
419420
**
420421
** If the "--from VERSION" or "-r VERSION" option is used it specifies
421422
** the source check-in for the diff operation. If not specified, the
422423
** source check-in is the base check-in for the current check-out.
423424
**
@@ -440,10 +441,11 @@
440441
int hasNFlag; /* True if -N or --new-file flag is used */
441442
const char *zFrom; /* Source version number */
442443
const char *zTo; /* Target version number */
443444
const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */
444445
int diffFlags = 0; /* Flags to control the DIFF */
446
+ int f;
445447
446448
isGDiff = g.argv[1][0]=='g';
447449
isInternDiff = find_option("internal","i",0)!=0;
448450
zFrom = find_option("from", "r", 1);
449451
zTo = find_option("to", 0, 1);
@@ -455,12 +457,14 @@
455457
db_must_be_within_tree();
456458
verify_all_options();
457459
if( !isInternDiff ){
458460
zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
459461
}
460
- if( g.argc==3 ){
461
- diff_one_against_disk(zFrom, zDiffCmd, 0);
462
+ if( g.argc>=3 ){
463
+ for(f=2; f<g.argc; ++f){
464
+ diff_one_against_disk(zFrom, zDiffCmd, 0, g.argv[f]);
465
+ }
462466
}else{
463467
diff_all_against_disk(zFrom, zDiffCmd, diffFlags);
464468
}
465469
}else if( zFrom==0 ){
466470
fossil_fatal("must use --from if --to is present");
@@ -468,12 +472,14 @@
468472
db_find_and_open_repository(0, 0);
469473
verify_all_options();
470474
if( !isInternDiff ){
471475
zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
472476
}
473
- if( g.argc==3 ){
474
- diff_one_two_versions(zFrom, zTo, zDiffCmd, 0);
477
+ if( g.argc>=3 ){
478
+ for(f=2; f<g.argc; ++f){
479
+ diff_one_two_versions(zFrom, zTo, zDiffCmd, 0, g.argv[f]);
480
+ }
475481
}else{
476482
diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
477483
}
478484
}
479485
}
480486
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -175,23 +175,24 @@
175 blob_reset(&cmd);
176 }
177 }
178
179 /*
180 ** Do a diff against a single file named in g.argv[2] from version zFrom
181 ** against the same file on disk.
182 */
183 static void diff_one_against_disk(
184 const char *zFrom, /* Name of file */
185 const char *zDiffCmd, /* Use this "diff" command */
186 int ignoreEolWs /* Ignore whitespace changes at end of lines */
 
187 ){
188 Blob fname;
189 Blob content;
190 file_tree_name(g.argv[2], &fname, 1);
191 historical_version_of_file(zFrom, blob_str(&fname), &content, 0, 0);
192 diff_file(&content, g.argv[2], g.argv[2], zDiffCmd, ignoreEolWs);
193 blob_reset(&content);
194 blob_reset(&fname);
195 }
196
197 /*
@@ -295,22 +296,22 @@
295 }
296
297 /*
298 ** Output the differences between two versions of a single file.
299 ** zFrom and zTo are the check-ins containing the two file versions.
300 ** The filename is contained in g.argv[2].
301 */
302 static void diff_one_two_versions(
303 const char *zFrom,
304 const char *zTo,
305 const char *zDiffCmd,
306 int ignoreEolWs
 
307 ){
308 char *zName;
309 Blob fname;
310 Blob v1, v2;
311 file_tree_name(g.argv[2], &fname, 1);
312 zName = blob_str(&fname);
313 historical_version_of_file(zFrom, zName, &v1, 0, 0);
314 historical_version_of_file(zTo, zName, &v2, 0, 0);
315 diff_file_mem(&v1, &v2, zName, zDiffCmd, ignoreEolWs);
316 blob_reset(&v1);
@@ -408,16 +409,16 @@
408
409 /*
410 ** COMMAND: diff
411 ** COMMAND: gdiff
412 **
413 ** Usage: %fossil diff|gdiff ?options? ?FILE?
414 **
415 ** Show the difference between the current version of FILE (as it
416 ** exists on disk) and that same file as it was checked out. Or
417 ** if the FILE argument is omitted, show the unsaved changed currently
418 ** in the working check-out.
419 **
420 ** If the "--from VERSION" or "-r VERSION" option is used it specifies
421 ** the source check-in for the diff operation. If not specified, the
422 ** source check-in is the base check-in for the current check-out.
423 **
@@ -440,10 +441,11 @@
440 int hasNFlag; /* True if -N or --new-file flag is used */
441 const char *zFrom; /* Source version number */
442 const char *zTo; /* Target version number */
443 const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */
444 int diffFlags = 0; /* Flags to control the DIFF */
 
445
446 isGDiff = g.argv[1][0]=='g';
447 isInternDiff = find_option("internal","i",0)!=0;
448 zFrom = find_option("from", "r", 1);
449 zTo = find_option("to", 0, 1);
@@ -455,12 +457,14 @@
455 db_must_be_within_tree();
456 verify_all_options();
457 if( !isInternDiff ){
458 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
459 }
460 if( g.argc==3 ){
461 diff_one_against_disk(zFrom, zDiffCmd, 0);
 
 
462 }else{
463 diff_all_against_disk(zFrom, zDiffCmd, diffFlags);
464 }
465 }else if( zFrom==0 ){
466 fossil_fatal("must use --from if --to is present");
@@ -468,12 +472,14 @@
468 db_find_and_open_repository(0, 0);
469 verify_all_options();
470 if( !isInternDiff ){
471 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
472 }
473 if( g.argc==3 ){
474 diff_one_two_versions(zFrom, zTo, zDiffCmd, 0);
 
 
475 }else{
476 diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
477 }
478 }
479 }
480
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -175,23 +175,24 @@
175 blob_reset(&cmd);
176 }
177 }
178
179 /*
180 ** Do a diff against a single file named in zFileTreeName from version zFrom
181 ** against the same file on disk.
182 */
183 static void diff_one_against_disk(
184 const char *zFrom, /* Name of file */
185 const char *zDiffCmd, /* Use this "diff" command */
186 int ignoreEolWs, /* Ignore whitespace changes at end of lines */
187 const char *zFileTreeName
188 ){
189 Blob fname;
190 Blob content;
191 file_tree_name(zFileTreeName, &fname, 1);
192 historical_version_of_file(zFrom, blob_str(&fname), &content, 0, 0);
193 diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, ignoreEolWs);
194 blob_reset(&content);
195 blob_reset(&fname);
196 }
197
198 /*
@@ -295,22 +296,22 @@
296 }
297
298 /*
299 ** Output the differences between two versions of a single file.
300 ** zFrom and zTo are the check-ins containing the two file versions.
 
301 */
302 static void diff_one_two_versions(
303 const char *zFrom,
304 const char *zTo,
305 const char *zDiffCmd,
306 int ignoreEolWs,
307 const char *zFileTreeName
308 ){
309 char *zName;
310 Blob fname;
311 Blob v1, v2;
312 file_tree_name(zFileTreeName, &fname, 1);
313 zName = blob_str(&fname);
314 historical_version_of_file(zFrom, zName, &v1, 0, 0);
315 historical_version_of_file(zTo, zName, &v2, 0, 0);
316 diff_file_mem(&v1, &v2, zName, zDiffCmd, ignoreEolWs);
317 blob_reset(&v1);
@@ -408,16 +409,16 @@
409
410 /*
411 ** COMMAND: diff
412 ** COMMAND: gdiff
413 **
414 ** Usage: %fossil diff|gdiff ?options? ?FILE1? ?FILE2 ...?
415 **
416 ** Show the difference between the current version of each of the FILEs
417 ** specified (as they exist on disk) and that same file as it was checked
418 ** out. Or if the FILE arguments are omitted, show the unsaved changed
419 ** currently in the working check-out.
420 **
421 ** If the "--from VERSION" or "-r VERSION" option is used it specifies
422 ** the source check-in for the diff operation. If not specified, the
423 ** source check-in is the base check-in for the current check-out.
424 **
@@ -440,10 +441,11 @@
441 int hasNFlag; /* True if -N or --new-file flag is used */
442 const char *zFrom; /* Source version number */
443 const char *zTo; /* Target version number */
444 const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */
445 int diffFlags = 0; /* Flags to control the DIFF */
446 int f;
447
448 isGDiff = g.argv[1][0]=='g';
449 isInternDiff = find_option("internal","i",0)!=0;
450 zFrom = find_option("from", "r", 1);
451 zTo = find_option("to", 0, 1);
@@ -455,12 +457,14 @@
457 db_must_be_within_tree();
458 verify_all_options();
459 if( !isInternDiff ){
460 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
461 }
462 if( g.argc>=3 ){
463 for(f=2; f<g.argc; ++f){
464 diff_one_against_disk(zFrom, zDiffCmd, 0, g.argv[f]);
465 }
466 }else{
467 diff_all_against_disk(zFrom, zDiffCmd, diffFlags);
468 }
469 }else if( zFrom==0 ){
470 fossil_fatal("must use --from if --to is present");
@@ -468,12 +472,14 @@
472 db_find_and_open_repository(0, 0);
473 verify_all_options();
474 if( !isInternDiff ){
475 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
476 }
477 if( g.argc>=3 ){
478 for(f=2; f<g.argc; ++f){
479 diff_one_two_versions(zFrom, zTo, zDiffCmd, 0, g.argv[f]);
480 }
481 }else{
482 diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
483 }
484 }
485 }
486
+151 -36
--- src/export.c
+++ src/export.c
@@ -78,15 +78,17 @@
7878
free(zName);
7979
free(zEmail);
8080
db_reset(&q);
8181
}
8282
83
+#define BLOBMARK(rid) ((rid) * 2)
84
+#define COMMITMARK(rid) ((rid) * 2 + 1)
8385
8486
/*
8587
** COMMAND: export
8688
**
87
-** Usage: %fossil export --git ?REPOSITORY?
89
+** Usage: %fossil export --git ?options? ?REPOSITORY?
8890
**
8991
** Write an export of all check-ins to standard output. The export is
9092
** written in the git-fast-export file format assuming the --git option is
9193
** provided. The git-fast-export format is currently the only VCS
9294
** interchange format supported, though other formats may be added in
@@ -95,98 +97,190 @@
9597
** Run this command within a checkout. Or use the -R or --repository
9698
** option to specify a Fossil repository to be exported.
9799
**
98100
** Only check-ins are exported using --git. Git does not support tickets
99101
** or wiki or events or attachments, so none of those are exported.
102
+**
103
+** If the "--import-marks FILE" option is used, it contains a list of
104
+** rids to skip.
105
+**
106
+** If the "--export-marks FILE" option is used, the rid of all commits and
107
+** blobs written on exit for use with "--import-marks" on the next run.
100108
*/
101109
void export_cmd(void){
102
- Stmt q;
110
+ Stmt q, q2, q3;
103111
int i;
104
- int firstCkin; /* Integer offset to check-in marks */
105112
Bag blobs, vers;
113
+ const char *markfile_in;
114
+ const char *markfile_out;
115
+
106116
bag_init(&blobs);
107117
bag_init(&vers);
108118
109119
find_option("git", 0, 0); /* Ignore the --git option for now */
120
+ markfile_in = find_option("import-marks", 0, 1);
121
+ markfile_out = find_option("export-marks", 0, 1);
122
+
110123
db_find_and_open_repository(0, 2);
111124
verify_all_options();
112125
if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
126
+
127
+ db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
128
+ db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
129
+ if( markfile_in!=0 ){
130
+ Stmt qb,qc;
131
+ char line[100];
132
+ FILE *f;
133
+
134
+ f = fopen(markfile_in, "r");
135
+ if( f==0 ){
136
+ fossil_panic("cannot open %s for reading", markfile_in);
137
+ }
138
+ db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
139
+ db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
140
+ while( fgets(line, sizeof(line), f)!=0 ){
141
+ if( *line == 'b' ){
142
+ db_bind_text(&qb, ":rid", line + 1);
143
+ db_step(&qb);
144
+ db_reset(&qb);
145
+ bag_insert(&blobs, atoi(line + 1));
146
+ }else if( *line == 'c' ){
147
+ db_bind_text(&qc, ":rid", line + 1);
148
+ db_step(&qc);
149
+ db_reset(&qc);
150
+ bag_insert(&vers, atoi(line + 1));
151
+ }else{
152
+ fossil_panic("bad input from %s: %s", markfile_in, line);
153
+ }
154
+ }
155
+ db_finalize(&qb);
156
+ db_finalize(&qc);
157
+ fclose(f);
158
+ }
113159
114160
/* Step 1: Generate "blob" records for every artifact that is part
115161
** of a check-in
116162
*/
117163
fossil_binary_mode(stdout);
118
- db_prepare(&q, "SELECT DISTINCT fid FROM mlink WHERE fid>0");
164
+ db_multi_exec("CREATE TEMPORARY TABLE newblob(rid INTEGER KEY, srcid INTEGER)");
165
+ db_multi_exec("CREATE INDEX newblob_src ON newblob(srcid)");
166
+ db_multi_exec(
167
+ "INSERT INTO newblob"
168
+ " SELECT DISTINCT fid,"
169
+ " CASE WHEN EXISTS(SELECT 1 FROM delta WHERE rid=fid AND NOT EXISTS(SELECT 1 FROM oldblob WHERE srcid=fid))"
170
+ " THEN (SELECT srcid FROM delta WHERE rid=fid)"
171
+ " ELSE 0"
172
+ " END"
173
+ " FROM mlink"
174
+ " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)");
175
+ db_prepare(&q,
176
+ "SELECT DISTINCT fid FROM mlink"
177
+ " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)");
178
+ db_prepare(&q2, "INSERT INTO oldblob VALUES (:rid)");
179
+ db_prepare(&q3, "SELECT rid FROM newblob WHERE srcid= (:srcid)");
119180
while( db_step(&q)==SQLITE_ROW ){
120181
int rid = db_column_int(&q, 0);
121182
Blob content;
122
- content_get(rid, &content);
123
- printf("blob\nmark :%d\ndata %d\n", rid, blob_size(&content));
124
- bag_insert(&blobs, rid);
125
- fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
126
- printf("\n");
127
- blob_reset(&content);
183
+
184
+ while( !bag_find(&blobs, rid) ){
185
+ content_get(rid, &content);
186
+ db_bind_int(&q2, ":rid", rid);
187
+ db_step(&q2);
188
+ db_reset(&q2);
189
+ printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content));
190
+ bag_insert(&blobs, rid);
191
+ fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
192
+ printf("\n");
193
+ blob_reset(&content);
194
+
195
+ db_bind_int(&q3, ":srcid", rid);
196
+ if( db_step(&q3) != SQLITE_ROW ){
197
+ db_reset(&q3);
198
+ break;
199
+ }
200
+ rid = db_column_int(&q3, 0);
201
+ db_reset(&q3);
202
+ }
128203
}
129204
db_finalize(&q);
205
+ db_finalize(&q2);
206
+ db_finalize(&q3);
130207
131208
/* Output the commit records.
132209
*/
133
- firstCkin = db_int(0, "SELECT max(rid) FROM blob")+1;
134210
db_prepare(&q,
135211
"SELECT strftime('%%s',mtime), objid, coalesce(comment,ecomment),"
136212
" coalesce(user,euser),"
137213
" (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)"
138214
" FROM event"
139
- " WHERE type='ci'"
215
+ " WHERE type='ci' AND NOT EXISTS (SELECT 1 FROM oldcommit WHERE objid=rid)"
140216
" ORDER BY mtime ASC",
141217
TAG_BRANCH
142218
);
219
+ db_prepare(&q2, "INSERT INTO oldcommit VALUES (:rid)");
143220
while( db_step(&q)==SQLITE_ROW ){
221
+ Stmt q4;
144222
const char *zSecondsSince1970 = db_column_text(&q, 0);
145223
int ckinId = db_column_int(&q, 1);
146224
const char *zComment = db_column_text(&q, 2);
147225
const char *zUser = db_column_text(&q, 3);
148226
const char *zBranch = db_column_text(&q, 4);
149227
char *zBr;
150
- Manifest *p;
151
- ManifestFile *pFile;
152
- const char *zFromType;
153228
154229
bag_insert(&vers, ckinId);
230
+ db_bind_int(&q2, ":rid", ckinId);
231
+ db_step(&q2);
232
+ db_reset(&q2);
155233
if( zBranch==0 ) zBranch = "trunk";
156234
zBr = mprintf("%s", zBranch);
157235
for(i=0; zBr[i]; i++){
158236
if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
159237
}
160
- printf("commit refs/heads/%s\nmark :%d\n", zBr, ckinId+firstCkin);
238
+ printf("commit refs/heads/%s\nmark :%d\n", zBr, COMMITMARK(ckinId));
161239
free(zBr);
162240
printf("committer");
163241
print_person(zUser);
164242
printf(" %s +0000\n", zSecondsSince1970);
165243
if( zComment==0 ) zComment = "null comment";
166244
printf("data %d\n%s\n", (int)strlen(zComment), zComment);
167
- p = manifest_get(ckinId, CFTYPE_ANY);
168
- zFromType = "from";
169
- for(i=0; i<p->nParent; i++){
170
- int pid = fast_uuid_to_rid(p->azParent[i]);
171
- if( pid==0 || !bag_find(&vers, pid) ) continue;
172
- printf("%s :%d\n", zFromType, fast_uuid_to_rid(p->azParent[i])+firstCkin);
173
- zFromType = "merge";
174
- }
175
- printf("deleteall\n");
176
- manifest_file_rewind(p);
177
- while( (pFile=manifest_file_next(p, 0))!=0 ){
178
- int fid = fast_uuid_to_rid(pFile->zUuid);
179
- const char *zPerm = "100644";
180
- if( fid==0 ) continue;
181
- if( pFile->zPerm && strstr(pFile->zPerm,"x") ) zPerm = "100755";
182
- if( !bag_find(&blobs, fid) ) continue;
183
- printf("M %s :%d %s\n", zPerm, fid, pFile->zName);
184
- }
185
- manifest_cache_insert(p);
245
+ db_prepare(&q3, "SELECT pid FROM plink WHERE cid=%d AND isprim", ckinId);
246
+ if( db_step(&q3) == SQLITE_ROW ){
247
+ printf("from :%d\n", COMMITMARK(db_column_int(&q3, 0)));
248
+ db_prepare(&q4,
249
+ "SELECT pid FROM plink"
250
+ " WHERE cid=%d AND NOT isprim"
251
+ " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
252
+ " ORDER BY pid",
253
+ ckinId);
254
+ while( db_step(&q4)==SQLITE_ROW ){
255
+ printf("merge :%d\n", COMMITMARK(db_column_int(&q4,0)));
256
+ }
257
+ db_finalize(&q4);
258
+ }else{
259
+ printf("deleteall\n");
260
+ }
261
+
262
+ db_prepare(&q4,
263
+ "SELECT filename.name, mlink.fid, mlink.mperm FROM mlink"
264
+ " JOIN filename ON filename.fnid=mlink.fnid"
265
+ " WHERE mlink.mid=%d",
266
+ ckinId
267
+ );
268
+ while( db_step(&q4)==SQLITE_ROW ){
269
+ const char *zName = db_column_text(&q4,0);
270
+ int zNew = db_column_int(&q4,1);
271
+ int mPerm = db_column_int(&q4,2);
272
+ if( zNew==0)
273
+ printf("D %s\n", zName);
274
+ else if( bag_find(&blobs, zNew) )
275
+ printf("M %s :%d %s\n", mPerm ? "100755" : "100644", BLOBMARK(zNew), zName);
276
+ }
277
+ db_finalize(&q4);
278
+ db_finalize(&q3);
186279
printf("\n");
187280
}
281
+ db_finalize(&q2);
188282
db_finalize(&q);
189283
bag_clear(&blobs);
190284
manifest_cache_clear();
191285
192286
@@ -207,13 +301,34 @@
207301
zEncoded = mprintf("%s", zTagname);
208302
for(i=0; zEncoded[i]; i++){
209303
if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
210304
}
211305
printf("tag %s\n", zEncoded);
212
- printf("from :%d\n", rid+firstCkin);
306
+ printf("from :%d\n", COMMITMARK(rid));
213307
printf("tagger <tagger> %s +0000\n", zSecSince1970);
214308
printf("data 0\n");
215309
fossil_free(zEncoded);
216310
}
217311
db_finalize(&q);
218312
bag_clear(&vers);
313
+
314
+ if( markfile_out!=0 ){
315
+ FILE *f;
316
+ f = fopen(markfile_out, "w");
317
+ if( f == 0 ){
318
+ fossil_panic("cannot open %s for writing", markfile_out);
319
+ }
320
+ db_prepare(&q, "SELECT rid FROM oldblob");
321
+ while( db_step(&q)==SQLITE_ROW ){
322
+ fprintf(f, "b%d\n", db_column_int(&q, 0));
323
+ }
324
+ db_finalize(&q);
325
+ db_prepare(&q, "SELECT rid FROM oldcommit");
326
+ while( db_step(&q)==SQLITE_ROW ){
327
+ fprintf(f, "c%d\n", db_column_int(&q, 0));
328
+ }
329
+ db_finalize(&q);
330
+ if( ferror(f)!=0 || fclose(f)!=0 ) {
331
+ fossil_panic("error while writing %s", markfile_out);
332
+ }
333
+ }
219334
}
220335
--- src/export.c
+++ src/export.c
@@ -78,15 +78,17 @@
78 free(zName);
79 free(zEmail);
80 db_reset(&q);
81 }
82
 
 
83
84 /*
85 ** COMMAND: export
86 **
87 ** Usage: %fossil export --git ?REPOSITORY?
88 **
89 ** Write an export of all check-ins to standard output. The export is
90 ** written in the git-fast-export file format assuming the --git option is
91 ** provided. The git-fast-export format is currently the only VCS
92 ** interchange format supported, though other formats may be added in
@@ -95,98 +97,190 @@
95 ** Run this command within a checkout. Or use the -R or --repository
96 ** option to specify a Fossil repository to be exported.
97 **
98 ** Only check-ins are exported using --git. Git does not support tickets
99 ** or wiki or events or attachments, so none of those are exported.
 
 
 
 
 
 
100 */
101 void export_cmd(void){
102 Stmt q;
103 int i;
104 int firstCkin; /* Integer offset to check-in marks */
105 Bag blobs, vers;
 
 
 
106 bag_init(&blobs);
107 bag_init(&vers);
108
109 find_option("git", 0, 0); /* Ignore the --git option for now */
 
 
 
110 db_find_and_open_repository(0, 2);
111 verify_all_options();
112 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
114 /* Step 1: Generate "blob" records for every artifact that is part
115 ** of a check-in
116 */
117 fossil_binary_mode(stdout);
118 db_prepare(&q, "SELECT DISTINCT fid FROM mlink WHERE fid>0");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119 while( db_step(&q)==SQLITE_ROW ){
120 int rid = db_column_int(&q, 0);
121 Blob content;
122 content_get(rid, &content);
123 printf("blob\nmark :%d\ndata %d\n", rid, blob_size(&content));
124 bag_insert(&blobs, rid);
125 fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
126 printf("\n");
127 blob_reset(&content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128 }
129 db_finalize(&q);
 
 
130
131 /* Output the commit records.
132 */
133 firstCkin = db_int(0, "SELECT max(rid) FROM blob")+1;
134 db_prepare(&q,
135 "SELECT strftime('%%s',mtime), objid, coalesce(comment,ecomment),"
136 " coalesce(user,euser),"
137 " (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)"
138 " FROM event"
139 " WHERE type='ci'"
140 " ORDER BY mtime ASC",
141 TAG_BRANCH
142 );
 
143 while( db_step(&q)==SQLITE_ROW ){
 
144 const char *zSecondsSince1970 = db_column_text(&q, 0);
145 int ckinId = db_column_int(&q, 1);
146 const char *zComment = db_column_text(&q, 2);
147 const char *zUser = db_column_text(&q, 3);
148 const char *zBranch = db_column_text(&q, 4);
149 char *zBr;
150 Manifest *p;
151 ManifestFile *pFile;
152 const char *zFromType;
153
154 bag_insert(&vers, ckinId);
 
 
 
155 if( zBranch==0 ) zBranch = "trunk";
156 zBr = mprintf("%s", zBranch);
157 for(i=0; zBr[i]; i++){
158 if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
159 }
160 printf("commit refs/heads/%s\nmark :%d\n", zBr, ckinId+firstCkin);
161 free(zBr);
162 printf("committer");
163 print_person(zUser);
164 printf(" %s +0000\n", zSecondsSince1970);
165 if( zComment==0 ) zComment = "null comment";
166 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
167 p = manifest_get(ckinId, CFTYPE_ANY);
168 zFromType = "from";
169 for(i=0; i<p->nParent; i++){
170 int pid = fast_uuid_to_rid(p->azParent[i]);
171 if( pid==0 || !bag_find(&vers, pid) ) continue;
172 printf("%s :%d\n", zFromType, fast_uuid_to_rid(p->azParent[i])+firstCkin);
173 zFromType = "merge";
174 }
175 printf("deleteall\n");
176 manifest_file_rewind(p);
177 while( (pFile=manifest_file_next(p, 0))!=0 ){
178 int fid = fast_uuid_to_rid(pFile->zUuid);
179 const char *zPerm = "100644";
180 if( fid==0 ) continue;
181 if( pFile->zPerm && strstr(pFile->zPerm,"x") ) zPerm = "100755";
182 if( !bag_find(&blobs, fid) ) continue;
183 printf("M %s :%d %s\n", zPerm, fid, pFile->zName);
184 }
185 manifest_cache_insert(p);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186 printf("\n");
187 }
 
188 db_finalize(&q);
189 bag_clear(&blobs);
190 manifest_cache_clear();
191
192
@@ -207,13 +301,34 @@
207 zEncoded = mprintf("%s", zTagname);
208 for(i=0; zEncoded[i]; i++){
209 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
210 }
211 printf("tag %s\n", zEncoded);
212 printf("from :%d\n", rid+firstCkin);
213 printf("tagger <tagger> %s +0000\n", zSecSince1970);
214 printf("data 0\n");
215 fossil_free(zEncoded);
216 }
217 db_finalize(&q);
218 bag_clear(&vers);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219 }
220
--- src/export.c
+++ src/export.c
@@ -78,15 +78,17 @@
78 free(zName);
79 free(zEmail);
80 db_reset(&q);
81 }
82
83 #define BLOBMARK(rid) ((rid) * 2)
84 #define COMMITMARK(rid) ((rid) * 2 + 1)
85
86 /*
87 ** COMMAND: export
88 **
89 ** Usage: %fossil export --git ?options? ?REPOSITORY?
90 **
91 ** Write an export of all check-ins to standard output. The export is
92 ** written in the git-fast-export file format assuming the --git option is
93 ** provided. The git-fast-export format is currently the only VCS
94 ** interchange format supported, though other formats may be added in
@@ -95,98 +97,190 @@
97 ** Run this command within a checkout. Or use the -R or --repository
98 ** option to specify a Fossil repository to be exported.
99 **
100 ** Only check-ins are exported using --git. Git does not support tickets
101 ** or wiki or events or attachments, so none of those are exported.
102 **
103 ** If the "--import-marks FILE" option is used, it contains a list of
104 ** rids to skip.
105 **
106 ** If the "--export-marks FILE" option is used, the rid of all commits and
107 ** blobs written on exit for use with "--import-marks" on the next run.
108 */
109 void export_cmd(void){
110 Stmt q, q2, q3;
111 int i;
 
112 Bag blobs, vers;
113 const char *markfile_in;
114 const char *markfile_out;
115
116 bag_init(&blobs);
117 bag_init(&vers);
118
119 find_option("git", 0, 0); /* Ignore the --git option for now */
120 markfile_in = find_option("import-marks", 0, 1);
121 markfile_out = find_option("export-marks", 0, 1);
122
123 db_find_and_open_repository(0, 2);
124 verify_all_options();
125 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
126
127 db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
128 db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
129 if( markfile_in!=0 ){
130 Stmt qb,qc;
131 char line[100];
132 FILE *f;
133
134 f = fopen(markfile_in, "r");
135 if( f==0 ){
136 fossil_panic("cannot open %s for reading", markfile_in);
137 }
138 db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
139 db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
140 while( fgets(line, sizeof(line), f)!=0 ){
141 if( *line == 'b' ){
142 db_bind_text(&qb, ":rid", line + 1);
143 db_step(&qb);
144 db_reset(&qb);
145 bag_insert(&blobs, atoi(line + 1));
146 }else if( *line == 'c' ){
147 db_bind_text(&qc, ":rid", line + 1);
148 db_step(&qc);
149 db_reset(&qc);
150 bag_insert(&vers, atoi(line + 1));
151 }else{
152 fossil_panic("bad input from %s: %s", markfile_in, line);
153 }
154 }
155 db_finalize(&qb);
156 db_finalize(&qc);
157 fclose(f);
158 }
159
160 /* Step 1: Generate "blob" records for every artifact that is part
161 ** of a check-in
162 */
163 fossil_binary_mode(stdout);
164 db_multi_exec("CREATE TEMPORARY TABLE newblob(rid INTEGER KEY, srcid INTEGER)");
165 db_multi_exec("CREATE INDEX newblob_src ON newblob(srcid)");
166 db_multi_exec(
167 "INSERT INTO newblob"
168 " SELECT DISTINCT fid,"
169 " CASE WHEN EXISTS(SELECT 1 FROM delta WHERE rid=fid AND NOT EXISTS(SELECT 1 FROM oldblob WHERE srcid=fid))"
170 " THEN (SELECT srcid FROM delta WHERE rid=fid)"
171 " ELSE 0"
172 " END"
173 " FROM mlink"
174 " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)");
175 db_prepare(&q,
176 "SELECT DISTINCT fid FROM mlink"
177 " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)");
178 db_prepare(&q2, "INSERT INTO oldblob VALUES (:rid)");
179 db_prepare(&q3, "SELECT rid FROM newblob WHERE srcid= (:srcid)");
180 while( db_step(&q)==SQLITE_ROW ){
181 int rid = db_column_int(&q, 0);
182 Blob content;
183
184 while( !bag_find(&blobs, rid) ){
185 content_get(rid, &content);
186 db_bind_int(&q2, ":rid", rid);
187 db_step(&q2);
188 db_reset(&q2);
189 printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content));
190 bag_insert(&blobs, rid);
191 fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
192 printf("\n");
193 blob_reset(&content);
194
195 db_bind_int(&q3, ":srcid", rid);
196 if( db_step(&q3) != SQLITE_ROW ){
197 db_reset(&q3);
198 break;
199 }
200 rid = db_column_int(&q3, 0);
201 db_reset(&q3);
202 }
203 }
204 db_finalize(&q);
205 db_finalize(&q2);
206 db_finalize(&q3);
207
208 /* Output the commit records.
209 */
 
210 db_prepare(&q,
211 "SELECT strftime('%%s',mtime), objid, coalesce(comment,ecomment),"
212 " coalesce(user,euser),"
213 " (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)"
214 " FROM event"
215 " WHERE type='ci' AND NOT EXISTS (SELECT 1 FROM oldcommit WHERE objid=rid)"
216 " ORDER BY mtime ASC",
217 TAG_BRANCH
218 );
219 db_prepare(&q2, "INSERT INTO oldcommit VALUES (:rid)");
220 while( db_step(&q)==SQLITE_ROW ){
221 Stmt q4;
222 const char *zSecondsSince1970 = db_column_text(&q, 0);
223 int ckinId = db_column_int(&q, 1);
224 const char *zComment = db_column_text(&q, 2);
225 const char *zUser = db_column_text(&q, 3);
226 const char *zBranch = db_column_text(&q, 4);
227 char *zBr;
 
 
 
228
229 bag_insert(&vers, ckinId);
230 db_bind_int(&q2, ":rid", ckinId);
231 db_step(&q2);
232 db_reset(&q2);
233 if( zBranch==0 ) zBranch = "trunk";
234 zBr = mprintf("%s", zBranch);
235 for(i=0; zBr[i]; i++){
236 if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
237 }
238 printf("commit refs/heads/%s\nmark :%d\n", zBr, COMMITMARK(ckinId));
239 free(zBr);
240 printf("committer");
241 print_person(zUser);
242 printf(" %s +0000\n", zSecondsSince1970);
243 if( zComment==0 ) zComment = "null comment";
244 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
245 db_prepare(&q3, "SELECT pid FROM plink WHERE cid=%d AND isprim", ckinId);
246 if( db_step(&q3) == SQLITE_ROW ){
247 printf("from :%d\n", COMMITMARK(db_column_int(&q3, 0)));
248 db_prepare(&q4,
249 "SELECT pid FROM plink"
250 " WHERE cid=%d AND NOT isprim"
251 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
252 " ORDER BY pid",
253 ckinId);
254 while( db_step(&q4)==SQLITE_ROW ){
255 printf("merge :%d\n", COMMITMARK(db_column_int(&q4,0)));
256 }
257 db_finalize(&q4);
258 }else{
259 printf("deleteall\n");
260 }
261
262 db_prepare(&q4,
263 "SELECT filename.name, mlink.fid, mlink.mperm FROM mlink"
264 " JOIN filename ON filename.fnid=mlink.fnid"
265 " WHERE mlink.mid=%d",
266 ckinId
267 );
268 while( db_step(&q4)==SQLITE_ROW ){
269 const char *zName = db_column_text(&q4,0);
270 int zNew = db_column_int(&q4,1);
271 int mPerm = db_column_int(&q4,2);
272 if( zNew==0)
273 printf("D %s\n", zName);
274 else if( bag_find(&blobs, zNew) )
275 printf("M %s :%d %s\n", mPerm ? "100755" : "100644", BLOBMARK(zNew), zName);
276 }
277 db_finalize(&q4);
278 db_finalize(&q3);
279 printf("\n");
280 }
281 db_finalize(&q2);
282 db_finalize(&q);
283 bag_clear(&blobs);
284 manifest_cache_clear();
285
286
@@ -207,13 +301,34 @@
301 zEncoded = mprintf("%s", zTagname);
302 for(i=0; zEncoded[i]; i++){
303 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
304 }
305 printf("tag %s\n", zEncoded);
306 printf("from :%d\n", COMMITMARK(rid));
307 printf("tagger <tagger> %s +0000\n", zSecSince1970);
308 printf("data 0\n");
309 fossil_free(zEncoded);
310 }
311 db_finalize(&q);
312 bag_clear(&vers);
313
314 if( markfile_out!=0 ){
315 FILE *f;
316 f = fopen(markfile_out, "w");
317 if( f == 0 ){
318 fossil_panic("cannot open %s for writing", markfile_out);
319 }
320 db_prepare(&q, "SELECT rid FROM oldblob");
321 while( db_step(&q)==SQLITE_ROW ){
322 fprintf(f, "b%d\n", db_column_int(&q, 0));
323 }
324 db_finalize(&q);
325 db_prepare(&q, "SELECT rid FROM oldcommit");
326 while( db_step(&q)==SQLITE_ROW ){
327 fprintf(f, "c%d\n", db_column_int(&q, 0));
328 }
329 db_finalize(&q);
330 if( ferror(f)!=0 || fclose(f)!=0 ) {
331 fossil_panic("error while writing %s", markfile_out);
332 }
333 }
334 }
335
+32 -6
--- src/file.c
+++ src/file.c
@@ -19,10 +19,12 @@
1919
*/
2020
#include "config.h"
2121
#include <sys/types.h>
2222
#include <sys/stat.h>
2323
#include <unistd.h>
24
+#include <string.h>
25
+#include <errno.h>
2426
#include "file.h"
2527
2628
/*
2729
** The file status information from the most recent stat() call.
2830
**
@@ -397,11 +399,11 @@
397399
char *zPwdUtf8;
398400
int nPwd;
399401
int i;
400402
char zPwd[2000];
401403
if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
402
- fossil_fatal("pwd too big: max %d\n", (int)sizeof(zPwd)-1);
404
+ fossil_fatal("cannot find the current working directory.");
403405
}
404406
zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
405407
nPwd = strlen(zPwdUtf8);
406408
if( nPwd > nBuf-1 ){
407409
fossil_fatal("pwd too big: max %d\n", nBuf-1);
@@ -409,11 +411,16 @@
409411
for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
410412
memcpy(zBuf, zPwdUtf8, nPwd+1);
411413
fossil_mbcs_free(zPwdUtf8);
412414
#else
413415
if( getcwd(zBuf, nBuf-1)==0 ){
414
- fossil_fatal("pwd too big: max %d\n", nBuf-1);
416
+ if( errno==ERANGE ){
417
+ fossil_fatal("pwd too big: max %d\n", nBuf-1);
418
+ }else{
419
+ fossil_fatal("cannot find current working directory; %s",
420
+ strerror(errno));
421
+ }
415422
}
416423
#endif
417424
}
418425
419426
/*
@@ -492,26 +499,45 @@
492499
}
493500
}
494501
}
495502
return 1;
496503
}
504
+
505
+/*
506
+** Return a pointer to the first character in a pathname past the
507
+** drive letter. This routine is a no-op on unix.
508
+*/
509
+char *file_without_drive_letter(char *zIn){
510
+#ifdef _WIN32
511
+ if( fossil_isalpha(zIn[0]) && zIn[1]==':' ) zIn += 2;
512
+#endif
513
+ return zIn;
514
+}
497515
498516
/*
499517
** Compute a pathname for a file or directory that is relative
500518
** to the current directory.
501519
*/
502520
void file_relative_name(const char *zOrigName, Blob *pOut){
503521
char *zPath;
504522
blob_set(pOut, zOrigName);
505523
blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
506
- zPath = blob_buffer(pOut);
524
+ zPath = file_without_drive_letter(blob_buffer(pOut));
507525
if( zPath[0]=='/' ){
508526
int i, j;
509527
Blob tmp;
510
- char zPwd[2000];
511
- file_getcwd(zPwd, sizeof(zPwd)-20);
512
- for(i=1; zPath[i] && zPwd[i]==zPath[i]; i++){}
528
+ char *zPwd;
529
+ char zBuf[2000];
530
+ zPwd = zBuf;
531
+ file_getcwd(zBuf, sizeof(zBuf)-20);
532
+ zPwd = file_without_drive_letter(zBuf);
533
+ i = 1;
534
+#ifdef _WIN32
535
+ while( zPath[i] && fossil_tolower(zPwd[i])==fossil_tolower(zPath[i]) ) i++;
536
+#else
537
+ while( zPath[i] && zPwd[i]==zPath[i] ) i++;
538
+#endif
513539
if( zPath[i]==0 ){
514540
blob_reset(pOut);
515541
if( zPwd[i]==0 ){
516542
blob_append(pOut, ".", 1);
517543
}else{
518544
--- src/file.c
+++ src/file.c
@@ -19,10 +19,12 @@
19 */
20 #include "config.h"
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
 
 
24 #include "file.h"
25
26 /*
27 ** The file status information from the most recent stat() call.
28 **
@@ -397,11 +399,11 @@
397 char *zPwdUtf8;
398 int nPwd;
399 int i;
400 char zPwd[2000];
401 if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
402 fossil_fatal("pwd too big: max %d\n", (int)sizeof(zPwd)-1);
403 }
404 zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
405 nPwd = strlen(zPwdUtf8);
406 if( nPwd > nBuf-1 ){
407 fossil_fatal("pwd too big: max %d\n", nBuf-1);
@@ -409,11 +411,16 @@
409 for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
410 memcpy(zBuf, zPwdUtf8, nPwd+1);
411 fossil_mbcs_free(zPwdUtf8);
412 #else
413 if( getcwd(zBuf, nBuf-1)==0 ){
414 fossil_fatal("pwd too big: max %d\n", nBuf-1);
 
 
 
 
 
415 }
416 #endif
417 }
418
419 /*
@@ -492,26 +499,45 @@
492 }
493 }
494 }
495 return 1;
496 }
 
 
 
 
 
 
 
 
 
 
 
497
498 /*
499 ** Compute a pathname for a file or directory that is relative
500 ** to the current directory.
501 */
502 void file_relative_name(const char *zOrigName, Blob *pOut){
503 char *zPath;
504 blob_set(pOut, zOrigName);
505 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
506 zPath = blob_buffer(pOut);
507 if( zPath[0]=='/' ){
508 int i, j;
509 Blob tmp;
510 char zPwd[2000];
511 file_getcwd(zPwd, sizeof(zPwd)-20);
512 for(i=1; zPath[i] && zPwd[i]==zPath[i]; i++){}
 
 
 
 
 
 
 
 
513 if( zPath[i]==0 ){
514 blob_reset(pOut);
515 if( zPwd[i]==0 ){
516 blob_append(pOut, ".", 1);
517 }else{
518
--- src/file.c
+++ src/file.c
@@ -19,10 +19,12 @@
19 */
20 #include "config.h"
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "file.h"
27
28 /*
29 ** The file status information from the most recent stat() call.
30 **
@@ -397,11 +399,11 @@
399 char *zPwdUtf8;
400 int nPwd;
401 int i;
402 char zPwd[2000];
403 if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
404 fossil_fatal("cannot find the current working directory.");
405 }
406 zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
407 nPwd = strlen(zPwdUtf8);
408 if( nPwd > nBuf-1 ){
409 fossil_fatal("pwd too big: max %d\n", nBuf-1);
@@ -409,11 +411,16 @@
411 for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
412 memcpy(zBuf, zPwdUtf8, nPwd+1);
413 fossil_mbcs_free(zPwdUtf8);
414 #else
415 if( getcwd(zBuf, nBuf-1)==0 ){
416 if( errno==ERANGE ){
417 fossil_fatal("pwd too big: max %d\n", nBuf-1);
418 }else{
419 fossil_fatal("cannot find current working directory; %s",
420 strerror(errno));
421 }
422 }
423 #endif
424 }
425
426 /*
@@ -492,26 +499,45 @@
499 }
500 }
501 }
502 return 1;
503 }
504
505 /*
506 ** Return a pointer to the first character in a pathname past the
507 ** drive letter. This routine is a no-op on unix.
508 */
509 char *file_without_drive_letter(char *zIn){
510 #ifdef _WIN32
511 if( fossil_isalpha(zIn[0]) && zIn[1]==':' ) zIn += 2;
512 #endif
513 return zIn;
514 }
515
516 /*
517 ** Compute a pathname for a file or directory that is relative
518 ** to the current directory.
519 */
520 void file_relative_name(const char *zOrigName, Blob *pOut){
521 char *zPath;
522 blob_set(pOut, zOrigName);
523 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
524 zPath = file_without_drive_letter(blob_buffer(pOut));
525 if( zPath[0]=='/' ){
526 int i, j;
527 Blob tmp;
528 char *zPwd;
529 char zBuf[2000];
530 zPwd = zBuf;
531 file_getcwd(zBuf, sizeof(zBuf)-20);
532 zPwd = file_without_drive_letter(zBuf);
533 i = 1;
534 #ifdef _WIN32
535 while( zPath[i] && fossil_tolower(zPwd[i])==fossil_tolower(zPath[i]) ) i++;
536 #else
537 while( zPath[i] && zPwd[i]==zPath[i] ) i++;
538 #endif
539 if( zPath[i]==0 ){
540 blob_reset(pOut);
541 if( zPwd[i]==0 ){
542 blob_append(pOut, ".", 1);
543 }else{
544
--- src/finfo.c
+++ src/finfo.c
@@ -193,10 +193,12 @@
193193
** Additional query parameters:
194194
**
195195
** a=DATE Only show changes after DATE
196196
** b=DATE Only show changes before DATE
197197
** n=NUM Show the first NUM changes only
198
+** brbg Background color by branch name
199
+** ubg Background color by user name
198200
*/
199201
void finfo_page(void){
200202
Stmt q;
201203
const char *zFilename;
202204
char zPrevDate[20];
@@ -204,10 +206,12 @@
204206
const char *zB;
205207
int n;
206208
Blob title;
207209
Blob sql;
208210
GraphContext *pGraph;
211
+ int brBg = P("brbg")!=0;
212
+ int uBg = P("ubg")!=0;
209213
210214
login_check_credentials();
211215
if( !g.okRead ){ login_needed(); return; }
212216
style_header("File History");
213217
login_anonymous_available();
@@ -268,10 +272,15 @@
268272
int gidx;
269273
char zTime[10];
270274
char zShort[20];
271275
char zShortCkin[20];
272276
if( zBr==0 ) zBr = "trunk";
277
+ if( uBg ){
278
+ zBgClr = hash_color(zUser);
279
+ }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
280
+ zBgClr = strcmp(zBr,"trunk")==0 ? "white" : hash_color(zBr);
281
+ }
273282
gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
274283
if( memcmp(zDate, zPrevDate, 10) ){
275284
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
276285
@ <tr><td>
277286
@ <div class="divider">%s(zPrevDate)</div>
278287
--- src/finfo.c
+++ src/finfo.c
@@ -193,10 +193,12 @@
193 ** Additional query parameters:
194 **
195 ** a=DATE Only show changes after DATE
196 ** b=DATE Only show changes before DATE
197 ** n=NUM Show the first NUM changes only
 
 
198 */
199 void finfo_page(void){
200 Stmt q;
201 const char *zFilename;
202 char zPrevDate[20];
@@ -204,10 +206,12 @@
204 const char *zB;
205 int n;
206 Blob title;
207 Blob sql;
208 GraphContext *pGraph;
 
 
209
210 login_check_credentials();
211 if( !g.okRead ){ login_needed(); return; }
212 style_header("File History");
213 login_anonymous_available();
@@ -268,10 +272,15 @@
268 int gidx;
269 char zTime[10];
270 char zShort[20];
271 char zShortCkin[20];
272 if( zBr==0 ) zBr = "trunk";
 
 
 
 
 
273 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
274 if( memcmp(zDate, zPrevDate, 10) ){
275 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
276 @ <tr><td>
277 @ <div class="divider">%s(zPrevDate)</div>
278
--- src/finfo.c
+++ src/finfo.c
@@ -193,10 +193,12 @@
193 ** Additional query parameters:
194 **
195 ** a=DATE Only show changes after DATE
196 ** b=DATE Only show changes before DATE
197 ** n=NUM Show the first NUM changes only
198 ** brbg Background color by branch name
199 ** ubg Background color by user name
200 */
201 void finfo_page(void){
202 Stmt q;
203 const char *zFilename;
204 char zPrevDate[20];
@@ -204,10 +206,12 @@
206 const char *zB;
207 int n;
208 Blob title;
209 Blob sql;
210 GraphContext *pGraph;
211 int brBg = P("brbg")!=0;
212 int uBg = P("ubg")!=0;
213
214 login_check_credentials();
215 if( !g.okRead ){ login_needed(); return; }
216 style_header("File History");
217 login_anonymous_available();
@@ -268,10 +272,15 @@
272 int gidx;
273 char zTime[10];
274 char zShort[20];
275 char zShortCkin[20];
276 if( zBr==0 ) zBr = "trunk";
277 if( uBg ){
278 zBgClr = hash_color(zUser);
279 }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
280 zBgClr = strcmp(zBr,"trunk")==0 ? "white" : hash_color(zBr);
281 }
282 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
283 if( memcmp(zDate, zPrevDate, 10) ){
284 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
285 @ <tr><td>
286 @ <div class="divider">%s(zPrevDate)</div>
287
+4 -4
--- src/glob.c
+++ src/glob.c
@@ -110,24 +110,24 @@
110110
p = fossil_malloc( sizeof(*p) + nList+1 );
111111
memset(p, 0, sizeof(*p));
112112
z = (char*)&p[1];
113113
memcpy(z, zPatternList, nList+1);
114114
while( z[0] ){
115
- while( z[0]==',' || z[0]==' ' ) z++; /* Skip leading spaces */
115
+ while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ) z++; /* Skip leading spaces and newlines */
116116
if( z[0]=='\'' || z[0]=='"' ){
117117
delimiter = z[0];
118118
z++;
119119
}else{
120120
delimiter = ',';
121121
}
122122
if( z[0]==0 ) break;
123123
p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) );
124124
p->azPattern[p->nPattern++] = z;
125
- for(i=0; z[i] && z[i]!=delimiter; i++){}
125
+ for(i=0; z[i] && z[i]!=delimiter && z[i]!='\n' && z[i]!='\r'; i++){}
126126
if( delimiter==',' ){
127
- /* Remove trailing spaces on a comma-delimited pattern */
128
- for(j=i; j>1 && z[j-1]==' '; j--){}
127
+ /* Remove trailing spaces / newlines on a comma-delimited pattern */
128
+ for(j=i; j>1 && (z[j-1]==' ' || z[j-1]=='\n' || z[j-1]=='\r'); j--){}
129129
if( j<i ) z[j] = 0;
130130
}
131131
if( z[i]==0 ) break;
132132
z[i] = 0;
133133
z += i+1;
134134
--- src/glob.c
+++ src/glob.c
@@ -110,24 +110,24 @@
110 p = fossil_malloc( sizeof(*p) + nList+1 );
111 memset(p, 0, sizeof(*p));
112 z = (char*)&p[1];
113 memcpy(z, zPatternList, nList+1);
114 while( z[0] ){
115 while( z[0]==',' || z[0]==' ' ) z++; /* Skip leading spaces */
116 if( z[0]=='\'' || z[0]=='"' ){
117 delimiter = z[0];
118 z++;
119 }else{
120 delimiter = ',';
121 }
122 if( z[0]==0 ) break;
123 p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) );
124 p->azPattern[p->nPattern++] = z;
125 for(i=0; z[i] && z[i]!=delimiter; i++){}
126 if( delimiter==',' ){
127 /* Remove trailing spaces on a comma-delimited pattern */
128 for(j=i; j>1 && z[j-1]==' '; j--){}
129 if( j<i ) z[j] = 0;
130 }
131 if( z[i]==0 ) break;
132 z[i] = 0;
133 z += i+1;
134
--- src/glob.c
+++ src/glob.c
@@ -110,24 +110,24 @@
110 p = fossil_malloc( sizeof(*p) + nList+1 );
111 memset(p, 0, sizeof(*p));
112 z = (char*)&p[1];
113 memcpy(z, zPatternList, nList+1);
114 while( z[0] ){
115 while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ) z++; /* Skip leading spaces and newlines */
116 if( z[0]=='\'' || z[0]=='"' ){
117 delimiter = z[0];
118 z++;
119 }else{
120 delimiter = ',';
121 }
122 if( z[0]==0 ) break;
123 p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) );
124 p->azPattern[p->nPattern++] = z;
125 for(i=0; z[i] && z[i]!=delimiter && z[i]!='\n' && z[i]!='\r'; i++){}
126 if( delimiter==',' ){
127 /* Remove trailing spaces / newlines on a comma-delimited pattern */
128 for(j=i; j>1 && (z[j-1]==' ' || z[j-1]=='\n' || z[j-1]=='\r'); j--){}
129 if( j<i ) z[j] = 0;
130 }
131 if( z[i]==0 ) break;
132 z[i] = 0;
133 z += i+1;
134
+2 -1
--- src/http.c
+++ src/http.c
@@ -110,11 +110,12 @@
110110
blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111111
fossil_free(zEncoded);
112112
fossil_free(zCredentials);
113113
}
114114
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115
- blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
115
+ blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116
+ "-" MANIFEST_VERSION "\r\n");
116117
if( g.fHttpTrace ){
117118
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
118119
}else{
119120
blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
120121
}
121122
--- src/http.c
+++ src/http.c
@@ -110,11 +110,12 @@
110 blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111 fossil_free(zEncoded);
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
 
116 if( g.fHttpTrace ){
117 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
118 }else{
119 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
120 }
121
--- src/http.c
+++ src/http.c
@@ -110,11 +110,12 @@
110 blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111 fossil_free(zEncoded);
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116 "-" MANIFEST_VERSION "\r\n");
117 if( g.fHttpTrace ){
118 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
119 }else{
120 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
121 }
122
+61 -1
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -78,23 +78,76 @@
7878
** Return the current SSL error message
7979
*/
8080
const char *ssl_errmsg(void){
8181
return sslErrMsg;
8282
}
83
+
84
+/*
85
+** When a server requests a client certificate that hasn't been provided,
86
+** display a warning message explaining what to do next.
87
+*/
88
+static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
89
+ fossil_warning("The remote server requested a client certificate for "
90
+ "authentication. Specify the pathname to a file containing the PEM "
91
+ "encoded certificate and private key with the --ssl-identity option "
92
+ "or the ssl-identity setting.");
93
+ return 0; /* no cert available */
94
+}
8395
8496
/*
8597
** Call this routine once before any other use of the SSL interface.
8698
** This routine does initial configuration of the SSL module.
8799
*/
88100
void ssl_global_init(void){
101
+ const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
102
+
89103
if( sslIsInit==0 ){
90104
SSL_library_init();
91105
SSL_load_error_strings();
92106
ERR_load_BIO_strings();
93107
OpenSSL_add_all_algorithms();
94108
sslCtx = SSL_CTX_new(SSLv23_client_method());
95
- X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
109
+
110
+ /* Set up acceptable CA root certificates */
111
+ zCaSetting = db_get("ssl-ca-location", 0);
112
+ if( zCaSetting==0 || zCaSetting[0]=='\0' ){
113
+ /* CA location not specified, use platform's default certificate store */
114
+ X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
115
+ }else{
116
+ /* User has specified a CA location, make sure it exists and use it */
117
+ switch( file_isdir(zCaSetting) ){
118
+ case 0: { /* doesn't exist */
119
+ fossil_fatal("ssl-ca-location is set to '%s', "
120
+ "but is not a file or directory", zCaSetting);
121
+ break;
122
+ }
123
+ case 1: { /* directory */
124
+ zCaDirectory = zCaSetting;
125
+ break;
126
+ }
127
+ case 2: { /* file */
128
+ zCaFile = zCaSetting;
129
+ break;
130
+ }
131
+ }
132
+ if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
133
+ fossil_fatal("Failed to use CA root certificates from "
134
+ "ssl-ca-location '%s'", zCaSetting);
135
+ }
136
+ }
137
+
138
+ /* Load client SSL identity, preferring the filename specified on the command line */
139
+ const char *identityFile = ( g.zSSLIdentity!= 0) ? g.zSSLIdentity : db_get("ssl-identity", 0);
140
+ if( identityFile!=0 && identityFile[0]!='\0' ){
141
+ if( SSL_CTX_use_certificate_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!= 1
142
+ || SSL_CTX_use_PrivateKey_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!=1 ){
143
+ fossil_fatal("Could not load SSL identity from %s", identityFile);
144
+ }
145
+ }
146
+ /* Register a callback to tell the user what to do when the server asks for a cert */
147
+ SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
148
+
96149
sslIsInit = 1;
97150
}
98151
}
99152
100153
/*
@@ -204,10 +257,17 @@
204257
if( hasSavedCertificate ){
205258
warning = "WARNING: Certificate doesn't match the "
206259
"saved certificate for this host!";
207260
}
208261
prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n"
262
+ "Either:\n"
263
+ " * verify the certificate is correct using the "
264
+ "SHA1 fingerprint above\n"
265
+ " * use the global ssl-ca-location setting to specify your CA root\n"
266
+ " certificates list\n\n"
267
+ "If you are not expecting this message, answer no and "
268
+ "contact your server\nadministrator.\n\n"
209269
"Accept certificate [a=always/y/N]? ", desc, warning);
210270
BIO_free(mem);
211271
212272
prompt_user(prompt, &ans);
213273
free(prompt);
214274
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -78,23 +78,76 @@
78 ** Return the current SSL error message
79 */
80 const char *ssl_errmsg(void){
81 return sslErrMsg;
82 }
 
 
 
 
 
 
 
 
 
 
 
 
83
84 /*
85 ** Call this routine once before any other use of the SSL interface.
86 ** This routine does initial configuration of the SSL module.
87 */
88 void ssl_global_init(void){
 
 
89 if( sslIsInit==0 ){
90 SSL_library_init();
91 SSL_load_error_strings();
92 ERR_load_BIO_strings();
93 OpenSSL_add_all_algorithms();
94 sslCtx = SSL_CTX_new(SSLv23_client_method());
95 X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96 sslIsInit = 1;
97 }
98 }
99
100 /*
@@ -204,10 +257,17 @@
204 if( hasSavedCertificate ){
205 warning = "WARNING: Certificate doesn't match the "
206 "saved certificate for this host!";
207 }
208 prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n"
 
 
 
 
 
 
 
209 "Accept certificate [a=always/y/N]? ", desc, warning);
210 BIO_free(mem);
211
212 prompt_user(prompt, &ans);
213 free(prompt);
214
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -78,23 +78,76 @@
78 ** Return the current SSL error message
79 */
80 const char *ssl_errmsg(void){
81 return sslErrMsg;
82 }
83
84 /*
85 ** When a server requests a client certificate that hasn't been provided,
86 ** display a warning message explaining what to do next.
87 */
88 static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
89 fossil_warning("The remote server requested a client certificate for "
90 "authentication. Specify the pathname to a file containing the PEM "
91 "encoded certificate and private key with the --ssl-identity option "
92 "or the ssl-identity setting.");
93 return 0; /* no cert available */
94 }
95
96 /*
97 ** Call this routine once before any other use of the SSL interface.
98 ** This routine does initial configuration of the SSL module.
99 */
100 void ssl_global_init(void){
101 const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
102
103 if( sslIsInit==0 ){
104 SSL_library_init();
105 SSL_load_error_strings();
106 ERR_load_BIO_strings();
107 OpenSSL_add_all_algorithms();
108 sslCtx = SSL_CTX_new(SSLv23_client_method());
109
110 /* Set up acceptable CA root certificates */
111 zCaSetting = db_get("ssl-ca-location", 0);
112 if( zCaSetting==0 || zCaSetting[0]=='\0' ){
113 /* CA location not specified, use platform's default certificate store */
114 X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
115 }else{
116 /* User has specified a CA location, make sure it exists and use it */
117 switch( file_isdir(zCaSetting) ){
118 case 0: { /* doesn't exist */
119 fossil_fatal("ssl-ca-location is set to '%s', "
120 "but is not a file or directory", zCaSetting);
121 break;
122 }
123 case 1: { /* directory */
124 zCaDirectory = zCaSetting;
125 break;
126 }
127 case 2: { /* file */
128 zCaFile = zCaSetting;
129 break;
130 }
131 }
132 if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
133 fossil_fatal("Failed to use CA root certificates from "
134 "ssl-ca-location '%s'", zCaSetting);
135 }
136 }
137
138 /* Load client SSL identity, preferring the filename specified on the command line */
139 const char *identityFile = ( g.zSSLIdentity!= 0) ? g.zSSLIdentity : db_get("ssl-identity", 0);
140 if( identityFile!=0 && identityFile[0]!='\0' ){
141 if( SSL_CTX_use_certificate_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!= 1
142 || SSL_CTX_use_PrivateKey_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!=1 ){
143 fossil_fatal("Could not load SSL identity from %s", identityFile);
144 }
145 }
146 /* Register a callback to tell the user what to do when the server asks for a cert */
147 SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
148
149 sslIsInit = 1;
150 }
151 }
152
153 /*
@@ -204,10 +257,17 @@
257 if( hasSavedCertificate ){
258 warning = "WARNING: Certificate doesn't match the "
259 "saved certificate for this host!";
260 }
261 prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n"
262 "Either:\n"
263 " * verify the certificate is correct using the "
264 "SHA1 fingerprint above\n"
265 " * use the global ssl-ca-location setting to specify your CA root\n"
266 " certificates list\n\n"
267 "If you are not expecting this message, answer no and "
268 "contact your server\nadministrator.\n\n"
269 "Accept certificate [a=always/y/N]? ", desc, warning);
270 BIO_free(mem);
271
272 prompt_user(prompt, &ans);
273 free(prompt);
274
+11 -5
--- src/info.c
+++ src/info.c
@@ -1213,12 +1213,18 @@
12131213
}
12141214
12151215
12161216
/*
12171217
** WEBPAGE: artifact
1218
-** URL: /artifact?name=ARTIFACTID
1218
+** URL: /artifact/ARTIFACTID
12191219
** URL: /artifact?ci=CHECKIN&filename=PATH
1220
+**
1221
+** Additional query parameters:
1222
+**
1223
+** ln - show line numbers
1224
+** ln=N - highlight line number N
1225
+** ln=M-N - highlight lines M through N inclusive
12201226
**
12211227
** Show the complete content of a file identified by ARTIFACTID
12221228
** as preformatted text.
12231229
*/
12241230
void artifact_page(void){
@@ -1260,24 +1266,24 @@
12601266
zMime = mimetype_from_name(blob_str(&downloadName));
12611267
if( zMime ){
12621268
if( fossil_strcmp(zMime, "text/html")==0 ){
12631269
if( P("txt") ){
12641270
style_submenu_element("Html", "Html",
1265
- "%s/artifact?name=%s", g.zTop, zUuid);
1271
+ "%s/artifact/%s", g.zTop, zUuid);
12661272
}else{
12671273
renderAsHtml = 1;
12681274
style_submenu_element("Text", "Text",
1269
- "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
1275
+ "%s/artifact/%s?txt=1", g.zTop, zUuid);
12701276
}
12711277
}else if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
12721278
if( P("txt") ){
12731279
style_submenu_element("Wiki", "Wiki",
1274
- "%s/artifact?name=%s", g.zTop, zUuid);
1280
+ "%s/artifact/%s", g.zTop, zUuid);
12751281
}else{
12761282
renderAsWiki = 1;
12771283
style_submenu_element("Text", "Text",
1278
- "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
1284
+ "%s/artifact/%s?txt=1", g.zTop, zUuid);
12791285
}
12801286
}
12811287
}
12821288
@ </p></blockquote>
12831289
@ <hr />
12841290
--- src/info.c
+++ src/info.c
@@ -1213,12 +1213,18 @@
1213 }
1214
1215
1216 /*
1217 ** WEBPAGE: artifact
1218 ** URL: /artifact?name=ARTIFACTID
1219 ** URL: /artifact?ci=CHECKIN&filename=PATH
 
 
 
 
 
 
1220 **
1221 ** Show the complete content of a file identified by ARTIFACTID
1222 ** as preformatted text.
1223 */
1224 void artifact_page(void){
@@ -1260,24 +1266,24 @@
1260 zMime = mimetype_from_name(blob_str(&downloadName));
1261 if( zMime ){
1262 if( fossil_strcmp(zMime, "text/html")==0 ){
1263 if( P("txt") ){
1264 style_submenu_element("Html", "Html",
1265 "%s/artifact?name=%s", g.zTop, zUuid);
1266 }else{
1267 renderAsHtml = 1;
1268 style_submenu_element("Text", "Text",
1269 "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
1270 }
1271 }else if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
1272 if( P("txt") ){
1273 style_submenu_element("Wiki", "Wiki",
1274 "%s/artifact?name=%s", g.zTop, zUuid);
1275 }else{
1276 renderAsWiki = 1;
1277 style_submenu_element("Text", "Text",
1278 "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
1279 }
1280 }
1281 }
1282 @ </p></blockquote>
1283 @ <hr />
1284
--- src/info.c
+++ src/info.c
@@ -1213,12 +1213,18 @@
1213 }
1214
1215
1216 /*
1217 ** WEBPAGE: artifact
1218 ** URL: /artifact/ARTIFACTID
1219 ** URL: /artifact?ci=CHECKIN&filename=PATH
1220 **
1221 ** Additional query parameters:
1222 **
1223 ** ln - show line numbers
1224 ** ln=N - highlight line number N
1225 ** ln=M-N - highlight lines M through N inclusive
1226 **
1227 ** Show the complete content of a file identified by ARTIFACTID
1228 ** as preformatted text.
1229 */
1230 void artifact_page(void){
@@ -1260,24 +1266,24 @@
1266 zMime = mimetype_from_name(blob_str(&downloadName));
1267 if( zMime ){
1268 if( fossil_strcmp(zMime, "text/html")==0 ){
1269 if( P("txt") ){
1270 style_submenu_element("Html", "Html",
1271 "%s/artifact/%s", g.zTop, zUuid);
1272 }else{
1273 renderAsHtml = 1;
1274 style_submenu_element("Text", "Text",
1275 "%s/artifact/%s?txt=1", g.zTop, zUuid);
1276 }
1277 }else if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
1278 if( P("txt") ){
1279 style_submenu_element("Wiki", "Wiki",
1280 "%s/artifact/%s", g.zTop, zUuid);
1281 }else{
1282 renderAsWiki = 1;
1283 style_submenu_element("Text", "Text",
1284 "%s/artifact/%s?txt=1", g.zTop, zUuid);
1285 }
1286 }
1287 }
1288 @ </p></blockquote>
1289 @ <hr />
1290
+9 -3
--- src/main.c
+++ src/main.c
@@ -105,10 +105,11 @@
105105
char *urlProxyAuth; /* Proxy-Authorizer: string */
106106
char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
107107
int dontKeepUrl; /* Do not persist the URL */
108108
109109
const char *zLogin; /* Login name. "" if not logged in. */
110
+ const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
110111
int useLocalauth; /* No login required if from 127.0.0.1 */
111112
int noPswd; /* Logged in without password (on 127.0.0.1) */
112113
int userUid; /* Integer user id */
113114
114115
/* Information used to populate the RCVFROM table */
@@ -251,10 +252,11 @@
251252
g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
252253
if( g.fSqlTrace ) g.fSqlStats = 1;
253254
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
254255
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
255256
g.zLogin = find_option("user", "U", 1);
257
+ g.zSSLIdentity = find_option("ssl-identity", 0, 1);
256258
if( find_option("help",0,0)!=0 ){
257259
/* --help anywhere on the command line is translated into
258260
** "fossil help argv[1] argv[2]..." */
259261
int i;
260262
char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
@@ -644,11 +646,11 @@
644646
** Usage: %fossil version
645647
**
646648
** Print the source code version number for the fossil executable.
647649
*/
648650
void version_cmd(void){
649
- fossil_print("This is fossil version "
651
+ fossil_print("This is fossil version " RELEASE_VERSION " "
650652
MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
651653
}
652654
653655
654656
/*
@@ -1102,11 +1104,12 @@
11021104
if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
11031105
cgi_setenv("HOME", blob_str(&value));
11041106
blob_reset(&value);
11051107
continue;
11061108
}
1107
- if( blob_eq(&key, "repository:") && blob_token(&line, &value) ){
1109
+ if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
1110
+ blob_trim(&value);
11081111
db_open_repository(blob_str(&value));
11091112
blob_reset(&value);
11101113
continue;
11111114
}
11121115
if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
@@ -1437,11 +1440,14 @@
14371440
if( isUiCmd ){
14381441
zBrowser = db_get("web-browser", "start");
14391442
zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
14401443
}
14411444
db_close(1);
1442
- win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile, zNotFound, flags);
1445
+ if( win32_http_service(iPort, zNotFound, flags) ){
1446
+ win32_http_server(iPort, mxPort, zBrowserCmd,
1447
+ zStopperFile, zNotFound, flags);
1448
+ }
14431449
#endif
14441450
}
14451451
14461452
/*
14471453
** COMMAND: test-echo
14481454
--- src/main.c
+++ src/main.c
@@ -105,10 +105,11 @@
105 char *urlProxyAuth; /* Proxy-Authorizer: string */
106 char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
107 int dontKeepUrl; /* Do not persist the URL */
108
109 const char *zLogin; /* Login name. "" if not logged in. */
 
110 int useLocalauth; /* No login required if from 127.0.0.1 */
111 int noPswd; /* Logged in without password (on 127.0.0.1) */
112 int userUid; /* Integer user id */
113
114 /* Information used to populate the RCVFROM table */
@@ -251,10 +252,11 @@
251 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
252 if( g.fSqlTrace ) g.fSqlStats = 1;
253 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
254 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
255 g.zLogin = find_option("user", "U", 1);
 
256 if( find_option("help",0,0)!=0 ){
257 /* --help anywhere on the command line is translated into
258 ** "fossil help argv[1] argv[2]..." */
259 int i;
260 char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
@@ -644,11 +646,11 @@
644 ** Usage: %fossil version
645 **
646 ** Print the source code version number for the fossil executable.
647 */
648 void version_cmd(void){
649 fossil_print("This is fossil version "
650 MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
651 }
652
653
654 /*
@@ -1102,11 +1104,12 @@
1102 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
1103 cgi_setenv("HOME", blob_str(&value));
1104 blob_reset(&value);
1105 continue;
1106 }
1107 if( blob_eq(&key, "repository:") && blob_token(&line, &value) ){
 
1108 db_open_repository(blob_str(&value));
1109 blob_reset(&value);
1110 continue;
1111 }
1112 if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
@@ -1437,11 +1440,14 @@
1437 if( isUiCmd ){
1438 zBrowser = db_get("web-browser", "start");
1439 zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
1440 }
1441 db_close(1);
1442 win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile, zNotFound, flags);
 
 
 
1443 #endif
1444 }
1445
1446 /*
1447 ** COMMAND: test-echo
1448
--- src/main.c
+++ src/main.c
@@ -105,10 +105,11 @@
105 char *urlProxyAuth; /* Proxy-Authorizer: string */
106 char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
107 int dontKeepUrl; /* Do not persist the URL */
108
109 const char *zLogin; /* Login name. "" if not logged in. */
110 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
111 int useLocalauth; /* No login required if from 127.0.0.1 */
112 int noPswd; /* Logged in without password (on 127.0.0.1) */
113 int userUid; /* Integer user id */
114
115 /* Information used to populate the RCVFROM table */
@@ -251,10 +252,11 @@
252 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
253 if( g.fSqlTrace ) g.fSqlStats = 1;
254 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
255 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
256 g.zLogin = find_option("user", "U", 1);
257 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
258 if( find_option("help",0,0)!=0 ){
259 /* --help anywhere on the command line is translated into
260 ** "fossil help argv[1] argv[2]..." */
261 int i;
262 char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
@@ -644,11 +646,11 @@
646 ** Usage: %fossil version
647 **
648 ** Print the source code version number for the fossil executable.
649 */
650 void version_cmd(void){
651 fossil_print("This is fossil version " RELEASE_VERSION " "
652 MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
653 }
654
655
656 /*
@@ -1102,11 +1104,12 @@
1104 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
1105 cgi_setenv("HOME", blob_str(&value));
1106 blob_reset(&value);
1107 continue;
1108 }
1109 if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
1110 blob_trim(&value);
1111 db_open_repository(blob_str(&value));
1112 blob_reset(&value);
1113 continue;
1114 }
1115 if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
@@ -1437,11 +1440,14 @@
1440 if( isUiCmd ){
1441 zBrowser = db_get("web-browser", "start");
1442 zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
1443 }
1444 db_close(1);
1445 if( win32_http_service(iPort, zNotFound, flags) ){
1446 win32_http_server(iPort, mxPort, zBrowserCmd,
1447 zStopperFile, zNotFound, flags);
1448 }
1449 #endif
1450 }
1451
1452 /*
1453 ** COMMAND: test-echo
1454
+16 -7
--- src/main.mk
+++ src/main.mk
@@ -281,22 +281,31 @@
281281
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
282282
283283
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
284284
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
285285
286
+$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
287
+ $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
288
+
286289
# WARNING. DANGER. Running the testsuite modifies the repository the
287290
# build is done from, i.e. the checkout belongs to. Do not sync/push
288291
# the repository after running the tests.
289292
test: $(APPNAME)
290293
$(TCLSH) test/tester.tcl $(APPNAME)
291294
292
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
293
- awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
294
- awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
295
- awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n", substr($$2,1,10),substr($$2,12,8)}' $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
295
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
296
+ $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
296297
297
-EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
298
+# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
299
+# to 1. If it is set to 1, then there is no need to build or link
300
+# the sqlite3.o object. Instead, the system sqlite will be linked
301
+# using -lsqlite3.
302
+SQLITE3_OBJ.1 =
303
+SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
304
+SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
305
+
306
+EXTRAOBJ = $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
298307
299308
$(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
300309
$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)
301310
302311
# This rule prevents make from using its default rules to try build
@@ -889,16 +898,16 @@
889898
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
890899
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
891900
892901
$(OBJDIR)/zip.h: $(OBJDIR)/headers
893902
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
894
- $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
903
+ $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
895904
896
-$(OBJDIR)/shell.o: $(SRCDIR)/shell.c
905
+$(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
897906
$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
898907
899908
$(OBJDIR)/th.o: $(SRCDIR)/th.c
900909
$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
901910
902911
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
903912
$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
904913
905914
--- src/main.mk
+++ src/main.mk
@@ -281,22 +281,31 @@
281 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
282
283 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
284 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
285
 
 
 
286 # WARNING. DANGER. Running the testsuite modifies the repository the
287 # build is done from, i.e. the checkout belongs to. Do not sync/push
288 # the repository after running the tests.
289 test: $(APPNAME)
290 $(TCLSH) test/tester.tcl $(APPNAME)
291
292 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
293 awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
294 awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
295 awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n", substr($$2,1,10),substr($$2,12,8)}' $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
296
297 EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
 
 
 
 
 
 
 
 
298
299 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
300 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)
301
302 # This rule prevents make from using its default rules to try build
@@ -889,16 +898,16 @@
889 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
890 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
891
892 $(OBJDIR)/zip.h: $(OBJDIR)/headers
893 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
894 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
895
896 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c
897 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
898
899 $(OBJDIR)/th.o: $(SRCDIR)/th.c
900 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
901
902 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
903 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
904
905
--- src/main.mk
+++ src/main.mk
@@ -281,22 +281,31 @@
281 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
282
283 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
284 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
285
286 $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
287 $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
288
289 # WARNING. DANGER. Running the testsuite modifies the repository the
290 # build is done from, i.e. the checkout belongs to. Do not sync/push
291 # the repository after running the tests.
292 test: $(APPNAME)
293 $(TCLSH) test/tester.tcl $(APPNAME)
294
295 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
296 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
 
 
297
298 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
299 # to 1. If it is set to 1, then there is no need to build or link
300 # the sqlite3.o object. Instead, the system sqlite will be linked
301 # using -lsqlite3.
302 SQLITE3_OBJ.1 =
303 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
304 SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
305
306 EXTRAOBJ = $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
307
308 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
309 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)
310
311 # This rule prevents make from using its default rules to try build
@@ -889,16 +898,16 @@
898 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
899 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
900
901 $(OBJDIR)/zip.h: $(OBJDIR)/headers
902 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
903 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
904
905 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
906 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
907
908 $(OBJDIR)/th.o: $(SRCDIR)/th.c
909 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
910
911 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
912 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
913
914
+32 -25
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -176,27 +176,34 @@
176176
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
177177
178178
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
179179
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
180180
181
+$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
182
+ $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
183
+
181184
# WARNING. DANGER. Running the testsuite modifies the repository the
182185
# build is done from, i.e. the checkout belongs to. Do not sync/push
183186
# the repository after running the tests.
184187
test: $(APPNAME)
185188
$(TCLSH) test/tester.tcl $(APPNAME)
186189
187
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
188
- awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' \
189
- $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
190
- awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' \
191
- $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
192
- awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n",\
193
- substr($$2,1,10),substr($$2,12,8)}' \
194
- $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
190
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
191
+ $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
192
+ $(SRCDIR)/../manifest \
193
+ $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
194
+
195
+# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
196
+# to 1. If it is set to 1, then there is no need to build or link
197
+# the sqlite3.o object. Instead, the system sqlite will be linked
198
+# using -lsqlite3.
199
+SQLITE3_OBJ.1 =
200
+SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
201
+SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
195202
196203
EXTRAOBJ = \
197
- $(OBJDIR)/sqlite3.o \
204
+ $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
198205
$(OBJDIR)/shell.o \
199206
$(OBJDIR)/th.o \
200207
$(OBJDIR)/th_lang.o
201208
202209
$(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
@@ -241,17 +248,17 @@
241248
242249
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
243250
set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1}
244251
append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4"
245252
#append opt " -DSQLITE_ENABLE_FTS3=1"
246
-append opt " -DSQLITE_ENABLE_STAT2"
253
+append opt " -DSQLITE_ENABLE_STAT3"
247254
append opt " -Dlocaltime=fossil_localtime"
248255
append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0"
249256
set SQLITE_OPTIONS $opt
250257
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
251258
252
-writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c"
259
+writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
253260
set opt {-Dmain=sqlite3_shell}
254261
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
255262
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
256263
257264
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
@@ -389,21 +396,21 @@
389396
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
390397
391398
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
392399
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
393400
394
-$(VERSION): $(SRCDIR)/../win/version.c
395
- $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
401
+$(VERSION): $(SRCDIR)/mkversion.c
402
+ $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
396403
397404
# WARNING. DANGER. Running the testsuite modifies the repository the
398405
# build is done from, i.e. the checkout belongs to. Do not sync/push
399406
# the repository after running the tests.
400407
test: $(APPNAME)
401408
$(TCLSH) test/tester.tcl $(APPNAME)
402409
403410
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
404
- $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest >$(OBJDIR)/VERSION.h
411
+ $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
405412
406413
EXTRAOBJ = \
407414
$(OBJDIR)/sqlite3.o \
408415
$(OBJDIR)/shell.o \
409416
$(OBJDIR)/th.o \
@@ -459,11 +466,11 @@
459466
460467
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
461468
set opt $SQLITE_OPTIONS
462469
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
463470
464
-writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c"
471
+writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
465472
set opt {-Dmain=sqlite3_shell}
466473
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
467474
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
468475
469476
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
@@ -556,11 +563,11 @@
556563
$(BCC) -o$@ $**
557564
558565
mkindex$E: $(SRCDIR)\mkindex.c
559566
$(BCC) -o$@ $**
560567
561
-version$E: $B\win\version.c
568
+version$E: $B\src\mkversion.c
562569
$(BCC) -o$@ $**
563570
564571
$(OBJDIR)\shell$O : $(SRCDIR)\shell.c
565572
$(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
566573
@@ -571,11 +578,11 @@
571578
$(TCC) -o$@ -c $**
572579
573580
$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
574581
$(TCC) -o$@ -c $**
575582
576
-VERSION.h : version$E $B\manifest.uuid $B\manifest
583
+VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
577584
+$** > $@
578585
579586
page_index.h: mkindex$E $(SRC)
580587
+$** > $@
581588
@@ -582,11 +589,11 @@
582589
clean:
583590
-del $(OBJDIR)\*.obj
584591
-del *.obj *_.c *.h *.map
585592
586593
realclean:
587
- -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
594
+ -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
588595
589596
}
590597
foreach s [lsort $src] {
591598
writeln "\$(OBJDIR)\\$s\$O : ${s}_.c ${s}.h"
592599
writeln "\t\$(TCC) -o\$@ -c ${s}_.c\n"
@@ -646,11 +653,11 @@
646653
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
647654
648655
CFLAGS = -nologo -MT -O2
649656
BCC = $(CC) $(CFLAGS)
650657
TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
651
-LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
658
+LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
652659
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
653660
}
654661
regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
655662
writeln "SQLITE_OPTIONS = $MSC_SQLITE_OPTIONS\n"
656663
writeln -nonewline "SRC = "
@@ -693,11 +700,11 @@
693700
$(BCC) $**
694701
695702
mkindex$E: $(SRCDIR)\mkindex.c
696703
$(BCC) $**
697704
698
-version$E: $B\win\version.c
705
+mkversion$E: $B\src\mkversion.c
699706
$(BCC) $**
700707
701708
$(OX)\shell$O : $(SRCDIR)\shell.c
702709
$(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
703710
@@ -708,11 +715,11 @@
708715
$(TCC) /Fo$@ -c $**
709716
710717
$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
711718
$(TCC) /Fo$@ -c $**
712719
713
-VERSION.h : version$E $B\manifest.uuid $B\manifest
720
+VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
714721
$** > $@
715722
716723
page_index.h: mkindex$E $(SRC)
717724
$** > $@
718725
@@ -720,11 +727,11 @@
720727
-del $(OX)\*.obj
721728
-del *.obj *_.c *.h *.map
722729
-del headers linkopts
723730
724731
realclean:
725
- -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
732
+ -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
726733
727734
}
728735
foreach s [lsort $src] {
729736
writeln "\$(OX)\\$s\$O : ${s}_.c ${s}.h"
730737
writeln "\t\$(TCC) /Fo\$@ -c ${s}_.c\n"
@@ -880,11 +887,11 @@
880887
# compiling standard fossil utils
881888
$(UTILS_OBJ): %.obj: $(SRCDIR)%.c
882889
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
883890
884891
# compile special windows utils
885
-version.obj: $(WINDIR)version.c
892
+version.obj: $(SRCDIR)mkversion.c
886893
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
887894
888895
# generate the translated c-source files
889896
$(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
890897
translate.exe $< >$@
@@ -892,12 +899,12 @@
892899
# generate the index source, containing all web references,..
893900
page_index.h: $(TRANSLATEDSRC) mkindex.exe
894901
mkindex.exe $(TRANSLATEDSRC) >$@
895902
896903
# extracting version info from manifest
897
-VERSION.h: version.exe ..\manifest.uuid ..\manifest
898
- version.exe ..\manifest.uuid ..\manifest > $@
904
+VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
905
+ version.exe ..\manifest.uuid ..\manifest ..\VERSION > $@
899906
900907
# generate the simplified headers
901908
headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h
902909
makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h
903910
echo Done >$@
904911
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -176,27 +176,34 @@
176 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
177
178 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
179 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
180
 
 
 
181 # WARNING. DANGER. Running the testsuite modifies the repository the
182 # build is done from, i.e. the checkout belongs to. Do not sync/push
183 # the repository after running the tests.
184 test: $(APPNAME)
185 $(TCLSH) test/tester.tcl $(APPNAME)
186
187 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest
188 awk '{ printf "#define MANIFEST_UUID \"%s\"\n", $$1}' \
189 $(SRCDIR)/../manifest.uuid >$(OBJDIR)/VERSION.h
190 awk '{ printf "#define MANIFEST_VERSION \"[%.10s]\"\n", $$1}' \
191 $(SRCDIR)/../manifest.uuid >>$(OBJDIR)/VERSION.h
192 awk '$$1=="D"{printf "#define MANIFEST_DATE \"%s %s\"\n",\
193 substr($$2,1,10),substr($$2,12,8)}' \
194 $(SRCDIR)/../manifest >>$(OBJDIR)/VERSION.h
 
 
 
 
195
196 EXTRAOBJ = \
197 $(OBJDIR)/sqlite3.o \
198 $(OBJDIR)/shell.o \
199 $(OBJDIR)/th.o \
200 $(OBJDIR)/th_lang.o
201
202 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
@@ -241,17 +248,17 @@
241
242 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
243 set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1}
244 append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4"
245 #append opt " -DSQLITE_ENABLE_FTS3=1"
246 append opt " -DSQLITE_ENABLE_STAT2"
247 append opt " -Dlocaltime=fossil_localtime"
248 append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0"
249 set SQLITE_OPTIONS $opt
250 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
251
252 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c"
253 set opt {-Dmain=sqlite3_shell}
254 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
255 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
256
257 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
@@ -389,21 +396,21 @@
389 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
390
391 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
392 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
393
394 $(VERSION): $(SRCDIR)/../win/version.c
395 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
396
397 # WARNING. DANGER. Running the testsuite modifies the repository the
398 # build is done from, i.e. the checkout belongs to. Do not sync/push
399 # the repository after running the tests.
400 test: $(APPNAME)
401 $(TCLSH) test/tester.tcl $(APPNAME)
402
403 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
404 $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest >$(OBJDIR)/VERSION.h
405
406 EXTRAOBJ = \
407 $(OBJDIR)/sqlite3.o \
408 $(OBJDIR)/shell.o \
409 $(OBJDIR)/th.o \
@@ -459,11 +466,11 @@
459
460 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
461 set opt $SQLITE_OPTIONS
462 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
463
464 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c"
465 set opt {-Dmain=sqlite3_shell}
466 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
467 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
468
469 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
@@ -556,11 +563,11 @@
556 $(BCC) -o$@ $**
557
558 mkindex$E: $(SRCDIR)\mkindex.c
559 $(BCC) -o$@ $**
560
561 version$E: $B\win\version.c
562 $(BCC) -o$@ $**
563
564 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
565 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
566
@@ -571,11 +578,11 @@
571 $(TCC) -o$@ -c $**
572
573 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
574 $(TCC) -o$@ -c $**
575
576 VERSION.h : version$E $B\manifest.uuid $B\manifest
577 +$** > $@
578
579 page_index.h: mkindex$E $(SRC)
580 +$** > $@
581
@@ -582,11 +589,11 @@
582 clean:
583 -del $(OBJDIR)\*.obj
584 -del *.obj *_.c *.h *.map
585
586 realclean:
587 -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
588
589 }
590 foreach s [lsort $src] {
591 writeln "\$(OBJDIR)\\$s\$O : ${s}_.c ${s}.h"
592 writeln "\t\$(TCC) -o\$@ -c ${s}_.c\n"
@@ -646,11 +653,11 @@
646 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
647
648 CFLAGS = -nologo -MT -O2
649 BCC = $(CC) $(CFLAGS)
650 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
651 LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
652 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
653 }
654 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
655 writeln "SQLITE_OPTIONS = $MSC_SQLITE_OPTIONS\n"
656 writeln -nonewline "SRC = "
@@ -693,11 +700,11 @@
693 $(BCC) $**
694
695 mkindex$E: $(SRCDIR)\mkindex.c
696 $(BCC) $**
697
698 version$E: $B\win\version.c
699 $(BCC) $**
700
701 $(OX)\shell$O : $(SRCDIR)\shell.c
702 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
703
@@ -708,11 +715,11 @@
708 $(TCC) /Fo$@ -c $**
709
710 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
711 $(TCC) /Fo$@ -c $**
712
713 VERSION.h : version$E $B\manifest.uuid $B\manifest
714 $** > $@
715
716 page_index.h: mkindex$E $(SRC)
717 $** > $@
718
@@ -720,11 +727,11 @@
720 -del $(OX)\*.obj
721 -del *.obj *_.c *.h *.map
722 -del headers linkopts
723
724 realclean:
725 -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
726
727 }
728 foreach s [lsort $src] {
729 writeln "\$(OX)\\$s\$O : ${s}_.c ${s}.h"
730 writeln "\t\$(TCC) /Fo\$@ -c ${s}_.c\n"
@@ -880,11 +887,11 @@
880 # compiling standard fossil utils
881 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
882 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
883
884 # compile special windows utils
885 version.obj: $(WINDIR)version.c
886 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
887
888 # generate the translated c-source files
889 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
890 translate.exe $< >$@
@@ -892,12 +899,12 @@
892 # generate the index source, containing all web references,..
893 page_index.h: $(TRANSLATEDSRC) mkindex.exe
894 mkindex.exe $(TRANSLATEDSRC) >$@
895
896 # extracting version info from manifest
897 VERSION.h: version.exe ..\manifest.uuid ..\manifest
898 version.exe ..\manifest.uuid ..\manifest > $@
899
900 # generate the simplified headers
901 headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h
902 makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h
903 echo Done >$@
904
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -176,27 +176,34 @@
176 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
177
178 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
179 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
180
181 $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
182 $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
183
184 # WARNING. DANGER. Running the testsuite modifies the repository the
185 # build is done from, i.e. the checkout belongs to. Do not sync/push
186 # the repository after running the tests.
187 test: $(APPNAME)
188 $(TCLSH) test/tester.tcl $(APPNAME)
189
190 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
191 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
192 $(SRCDIR)/../manifest \
193 $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
194
195 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
196 # to 1. If it is set to 1, then there is no need to build or link
197 # the sqlite3.o object. Instead, the system sqlite will be linked
198 # using -lsqlite3.
199 SQLITE3_OBJ.1 =
200 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
201 SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
202
203 EXTRAOBJ = \
204 $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
205 $(OBJDIR)/shell.o \
206 $(OBJDIR)/th.o \
207 $(OBJDIR)/th_lang.o
208
209 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
@@ -241,17 +248,17 @@
248
249 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
250 set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1}
251 append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4"
252 #append opt " -DSQLITE_ENABLE_FTS3=1"
253 append opt " -DSQLITE_ENABLE_STAT3"
254 append opt " -Dlocaltime=fossil_localtime"
255 append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0"
256 set SQLITE_OPTIONS $opt
257 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
258
259 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
260 set opt {-Dmain=sqlite3_shell}
261 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
262 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
263
264 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
@@ -389,21 +396,21 @@
396 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
397
398 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
399 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
400
401 $(VERSION): $(SRCDIR)/mkversion.c
402 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
403
404 # WARNING. DANGER. Running the testsuite modifies the repository the
405 # build is done from, i.e. the checkout belongs to. Do not sync/push
406 # the repository after running the tests.
407 test: $(APPNAME)
408 $(TCLSH) test/tester.tcl $(APPNAME)
409
410 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
411 $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
412
413 EXTRAOBJ = \
414 $(OBJDIR)/sqlite3.o \
415 $(OBJDIR)/shell.o \
416 $(OBJDIR)/th.o \
@@ -459,11 +466,11 @@
466
467 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
468 set opt $SQLITE_OPTIONS
469 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
470
471 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
472 set opt {-Dmain=sqlite3_shell}
473 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
474 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
475
476 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
@@ -556,11 +563,11 @@
563 $(BCC) -o$@ $**
564
565 mkindex$E: $(SRCDIR)\mkindex.c
566 $(BCC) -o$@ $**
567
568 version$E: $B\src\mkversion.c
569 $(BCC) -o$@ $**
570
571 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
572 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
573
@@ -571,11 +578,11 @@
578 $(TCC) -o$@ -c $**
579
580 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
581 $(TCC) -o$@ -c $**
582
583 VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
584 +$** > $@
585
586 page_index.h: mkindex$E $(SRC)
587 +$** > $@
588
@@ -582,11 +589,11 @@
589 clean:
590 -del $(OBJDIR)\*.obj
591 -del *.obj *_.c *.h *.map
592
593 realclean:
594 -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
595
596 }
597 foreach s [lsort $src] {
598 writeln "\$(OBJDIR)\\$s\$O : ${s}_.c ${s}.h"
599 writeln "\t\$(TCC) -o\$@ -c ${s}_.c\n"
@@ -646,11 +653,11 @@
653 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
654
655 CFLAGS = -nologo -MT -O2
656 BCC = $(CC) $(CFLAGS)
657 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
658 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
659 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
660 }
661 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
662 writeln "SQLITE_OPTIONS = $MSC_SQLITE_OPTIONS\n"
663 writeln -nonewline "SRC = "
@@ -693,11 +700,11 @@
700 $(BCC) $**
701
702 mkindex$E: $(SRCDIR)\mkindex.c
703 $(BCC) $**
704
705 mkversion$E: $B\src\mkversion.c
706 $(BCC) $**
707
708 $(OX)\shell$O : $(SRCDIR)\shell.c
709 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
710
@@ -708,11 +715,11 @@
715 $(TCC) /Fo$@ -c $**
716
717 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
718 $(TCC) /Fo$@ -c $**
719
720 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
721 $** > $@
722
723 page_index.h: mkindex$E $(SRC)
724 $** > $@
725
@@ -720,11 +727,11 @@
727 -del $(OX)\*.obj
728 -del *.obj *_.c *.h *.map
729 -del headers linkopts
730
731 realclean:
732 -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
733
734 }
735 foreach s [lsort $src] {
736 writeln "\$(OX)\\$s\$O : ${s}_.c ${s}.h"
737 writeln "\t\$(TCC) /Fo\$@ -c ${s}_.c\n"
@@ -880,11 +887,11 @@
887 # compiling standard fossil utils
888 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
889 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
890
891 # compile special windows utils
892 version.obj: $(SRCDIR)mkversion.c
893 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
894
895 # generate the translated c-source files
896 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
897 translate.exe $< >$@
@@ -892,12 +899,12 @@
899 # generate the index source, containing all web references,..
900 page_index.h: $(TRANSLATEDSRC) mkindex.exe
901 mkindex.exe $(TRANSLATEDSRC) >$@
902
903 # extracting version info from manifest
904 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
905 version.exe ..\manifest.uuid ..\manifest ..\VERSION > $@
906
907 # generate the simplified headers
908 headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h
909 makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h
910 echo Done >$@
911
+3 -4
--- src/manifest.c
+++ src/manifest.c
@@ -1323,14 +1323,13 @@
13231323
if( pChildFile ){
13241324
add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
13251325
isPublic, manifest_file_mperm(pChildFile));
13261326
}
13271327
}
1328
- }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1329
- /* Parent is a delta but pChild is a baseline. Look for files that are
1330
- ** present in pParent but which are missing from pChild and mark them
1331
- ** has having been deleted. */
1328
+ }else if( pChild->zBaseline==0 ){
1329
+ /* pChild is a baseline. Look for files that are present in pParent
1330
+ ** but are missing from pChild and mark them as having been deleted. */
13321331
manifest_file_rewind(pParent);
13331332
while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
13341333
pChildFile = manifest_file_seek(pChild, pParentFile->zName);
13351334
if( pChildFile==0 && pParentFile->zUuid!=0 ){
13361335
add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
13371336
--- src/manifest.c
+++ src/manifest.c
@@ -1323,14 +1323,13 @@
1323 if( pChildFile ){
1324 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1325 isPublic, manifest_file_mperm(pChildFile));
1326 }
1327 }
1328 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1329 /* Parent is a delta but pChild is a baseline. Look for files that are
1330 ** present in pParent but which are missing from pChild and mark them
1331 ** has having been deleted. */
1332 manifest_file_rewind(pParent);
1333 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1334 pChildFile = manifest_file_seek(pChild, pParentFile->zName);
1335 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1336 add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1337
--- src/manifest.c
+++ src/manifest.c
@@ -1323,14 +1323,13 @@
1323 if( pChildFile ){
1324 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1325 isPublic, manifest_file_mperm(pChildFile));
1326 }
1327 }
1328 }else if( pChild->zBaseline==0 ){
1329 /* pChild is a baseline. Look for files that are present in pParent
1330 ** but are missing from pChild and mark them as having been deleted. */
 
1331 manifest_file_rewind(pParent);
1332 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1333 pChildFile = manifest_file_seek(pChild, pParentFile->zName);
1334 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1335 add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1336
+10 -2
--- src/merge.c
+++ src/merge.c
@@ -53,10 +53,14 @@
5353
** and do not try to merge parallel changes. This
5454
** option overrides the "binary-glob" setting.
5555
**
5656
** --nochange | -n Dryrun: do not actually make any changes; just
5757
** show what would have happened.
58
+**
59
+** --case-sensitive BOOL Overwrite the case-sensitive setting. If false,
60
+** files whose names differ only in case are taken
61
+** to be the same file.
5862
*/
5963
void merge_cmd(void){
6064
int vid; /* Current version "V" */
6165
int mid; /* Version we are merging from "M" */
6266
int pid; /* The pivot version - most recent common ancestor P */
@@ -69,10 +73,11 @@
6973
int debugFlag; /* True if --debug is present */
7074
int nChng; /* Number of file name changes */
7175
int *aChng; /* An array of file name changes */
7276
int i; /* Loop counter */
7377
int nConflict = 0; /* Number of conflicts seen */
78
+ int caseSensitive; /* True for case-sensitive filenames */
7479
Stmt q;
7580
7681
7782
/* Notation:
7883
**
@@ -87,14 +92,16 @@
8792
backoutFlag = find_option("backout",0,0)!=0;
8893
debugFlag = find_option("debug",0,0)!=0;
8994
zBinGlob = find_option("binary",0,1);
9095
nochangeFlag = find_option("nochange","n",0)!=0;
9196
zPivot = find_option("baseline",0,1);
97
+ capture_case_sensitive_option();
9298
if( g.argc!=3 ){
9399
usage("VERSION");
94100
}
95101
db_must_be_within_tree();
102
+ caseSensitive = filenames_are_case_sensitive();
96103
if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
97104
vid = db_lget_int("checkout", 0);
98105
if( vid==0 ){
99106
fossil_fatal("nothing is checked out");
100107
}
@@ -150,11 +157,11 @@
150157
** in the current checkout, the pivot, and the version being merged.
151158
*/
152159
db_multi_exec(
153160
"DROP TABLE IF EXISTS fv;"
154161
"CREATE TEMP TABLE fv("
155
- " fn TEXT PRIMARY KEY," /* The filename */
162
+ " fn TEXT PRIMARY KEY COLLATE %s," /* The filename */
156163
" idv INTEGER," /* VFILE entry for current version */
157164
" idp INTEGER," /* VFILE entry for the pivot */
158165
" idm INTEGER," /* VFILE entry for version merging in */
159166
" chnged BOOLEAN," /* True if current version has been edited */
160167
" ridv INTEGER," /* Record ID for current version */
@@ -161,11 +168,12 @@
161168
" ridp INTEGER," /* Record ID for pivot */
162169
" ridm INTEGER," /* Record ID for merge */
163170
" isexe BOOLEAN," /* Execute permission enabled */
164171
" fnp TEXT," /* The filename in the pivot */
165172
" fnm TEXT" /* the filename in the merged version */
166
- ");"
173
+ ");",
174
+ caseSensitive ? "binary" : "nocase"
167175
);
168176
169177
/* Add files found in V
170178
*/
171179
db_multi_exec(
172180
173181
ADDED src/mkversion.c
--- src/merge.c
+++ src/merge.c
@@ -53,10 +53,14 @@
53 ** and do not try to merge parallel changes. This
54 ** option overrides the "binary-glob" setting.
55 **
56 ** --nochange | -n Dryrun: do not actually make any changes; just
57 ** show what would have happened.
 
 
 
 
58 */
59 void merge_cmd(void){
60 int vid; /* Current version "V" */
61 int mid; /* Version we are merging from "M" */
62 int pid; /* The pivot version - most recent common ancestor P */
@@ -69,10 +73,11 @@
69 int debugFlag; /* True if --debug is present */
70 int nChng; /* Number of file name changes */
71 int *aChng; /* An array of file name changes */
72 int i; /* Loop counter */
73 int nConflict = 0; /* Number of conflicts seen */
 
74 Stmt q;
75
76
77 /* Notation:
78 **
@@ -87,14 +92,16 @@
87 backoutFlag = find_option("backout",0,0)!=0;
88 debugFlag = find_option("debug",0,0)!=0;
89 zBinGlob = find_option("binary",0,1);
90 nochangeFlag = find_option("nochange","n",0)!=0;
91 zPivot = find_option("baseline",0,1);
 
92 if( g.argc!=3 ){
93 usage("VERSION");
94 }
95 db_must_be_within_tree();
 
96 if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
97 vid = db_lget_int("checkout", 0);
98 if( vid==0 ){
99 fossil_fatal("nothing is checked out");
100 }
@@ -150,11 +157,11 @@
150 ** in the current checkout, the pivot, and the version being merged.
151 */
152 db_multi_exec(
153 "DROP TABLE IF EXISTS fv;"
154 "CREATE TEMP TABLE fv("
155 " fn TEXT PRIMARY KEY," /* The filename */
156 " idv INTEGER," /* VFILE entry for current version */
157 " idp INTEGER," /* VFILE entry for the pivot */
158 " idm INTEGER," /* VFILE entry for version merging in */
159 " chnged BOOLEAN," /* True if current version has been edited */
160 " ridv INTEGER," /* Record ID for current version */
@@ -161,11 +168,12 @@
161 " ridp INTEGER," /* Record ID for pivot */
162 " ridm INTEGER," /* Record ID for merge */
163 " isexe BOOLEAN," /* Execute permission enabled */
164 " fnp TEXT," /* The filename in the pivot */
165 " fnm TEXT" /* the filename in the merged version */
166 ");"
 
167 );
168
169 /* Add files found in V
170 */
171 db_multi_exec(
172
173 DDED src/mkversion.c
--- src/merge.c
+++ src/merge.c
@@ -53,10 +53,14 @@
53 ** and do not try to merge parallel changes. This
54 ** option overrides the "binary-glob" setting.
55 **
56 ** --nochange | -n Dryrun: do not actually make any changes; just
57 ** show what would have happened.
58 **
59 ** --case-sensitive BOOL Overwrite the case-sensitive setting. If false,
60 ** files whose names differ only in case are taken
61 ** to be the same file.
62 */
63 void merge_cmd(void){
64 int vid; /* Current version "V" */
65 int mid; /* Version we are merging from "M" */
66 int pid; /* The pivot version - most recent common ancestor P */
@@ -69,10 +73,11 @@
73 int debugFlag; /* True if --debug is present */
74 int nChng; /* Number of file name changes */
75 int *aChng; /* An array of file name changes */
76 int i; /* Loop counter */
77 int nConflict = 0; /* Number of conflicts seen */
78 int caseSensitive; /* True for case-sensitive filenames */
79 Stmt q;
80
81
82 /* Notation:
83 **
@@ -87,14 +92,16 @@
92 backoutFlag = find_option("backout",0,0)!=0;
93 debugFlag = find_option("debug",0,0)!=0;
94 zBinGlob = find_option("binary",0,1);
95 nochangeFlag = find_option("nochange","n",0)!=0;
96 zPivot = find_option("baseline",0,1);
97 capture_case_sensitive_option();
98 if( g.argc!=3 ){
99 usage("VERSION");
100 }
101 db_must_be_within_tree();
102 caseSensitive = filenames_are_case_sensitive();
103 if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
104 vid = db_lget_int("checkout", 0);
105 if( vid==0 ){
106 fossil_fatal("nothing is checked out");
107 }
@@ -150,11 +157,11 @@
157 ** in the current checkout, the pivot, and the version being merged.
158 */
159 db_multi_exec(
160 "DROP TABLE IF EXISTS fv;"
161 "CREATE TEMP TABLE fv("
162 " fn TEXT PRIMARY KEY COLLATE %s," /* The filename */
163 " idv INTEGER," /* VFILE entry for current version */
164 " idp INTEGER," /* VFILE entry for the pivot */
165 " idm INTEGER," /* VFILE entry for version merging in */
166 " chnged BOOLEAN," /* True if current version has been edited */
167 " ridv INTEGER," /* Record ID for current version */
@@ -161,11 +168,12 @@
168 " ridp INTEGER," /* Record ID for pivot */
169 " ridm INTEGER," /* Record ID for merge */
170 " isexe BOOLEAN," /* Execute permission enabled */
171 " fnp TEXT," /* The filename in the pivot */
172 " fnm TEXT" /* the filename in the merged version */
173 ");",
174 caseSensitive ? "binary" : "nocase"
175 );
176
177 /* Add files found in V
178 */
179 db_multi_exec(
180
181 DDED src/mkversion.c
+1 -6
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -1,10 +1,5 @@
1
-fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2
-** makefile - to extract information from the "mainfest" and "manifest.uuid"
3
-** files for this p)
1
+fopen(argv[1],"gv[1],"fMSC_VER)
42
d = _MSC_VER / 1 return 0;
53
}
64
b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
75
}
8
-;
9
- char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10
- fopen(argv[1
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -1,10 +1,5 @@
1 fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2 ** makefile - to extract information from the "mainfest" and "manifest.uuid"
3 ** files for this p)
4 d = _MSC_VER / 1 return 0;
5 }
6 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
7 }
8 ;
9 char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10 fopen(argv[1
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -1,10 +1,5 @@
1 fopen(argv[1],"gv[1],"fMSC_VER)
 
 
2 d = _MSC_VER / 1 return 0;
3 }
4 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
5 }
 
 
 
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -0,0 +1,5 @@
1
+fopen(argv[1],"gv[1],"fMSC_VER)
2
+ d = _MSC_VER / 1 return 0;
3
+}
4
+b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
5
+}
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -0,0 +1,5 @@
 
 
 
 
 
--- a/src/mkversion.c
+++ b/src/mkversion.c
@@ -0,0 +1,5 @@
1 fopen(argv[1],"gv[1],"fMSC_VER)
2 d = _MSC_VER / 1 return 0;
3 }
4 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
5 }
+6 -2
--- src/popen.c
+++ src/popen.c
@@ -172,17 +172,21 @@
172172
close(pout[1]);
173173
*pChildPid = 0;
174174
return 1;
175175
}
176176
if( *pChildPid==0 ){
177
+ int fd;
178
+ int nErr = 0;
177179
/* This is the child process */
178180
close(0);
179
- dup(pout[0]);
181
+ fd = dup(pout[0]);
182
+ if( fd!=0 ) nErr++;
180183
close(pout[0]);
181184
close(pout[1]);
182185
close(1);
183
- dup(pin[1]);
186
+ fd = dup(pin[1]);
187
+ if( fd!=1 ) nErr++;
184188
close(pin[0]);
185189
close(pin[1]);
186190
execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
187191
return 1;
188192
}else{
189193
--- src/popen.c
+++ src/popen.c
@@ -172,17 +172,21 @@
172 close(pout[1]);
173 *pChildPid = 0;
174 return 1;
175 }
176 if( *pChildPid==0 ){
 
 
177 /* This is the child process */
178 close(0);
179 dup(pout[0]);
 
180 close(pout[0]);
181 close(pout[1]);
182 close(1);
183 dup(pin[1]);
 
184 close(pin[0]);
185 close(pin[1]);
186 execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
187 return 1;
188 }else{
189
--- src/popen.c
+++ src/popen.c
@@ -172,17 +172,21 @@
172 close(pout[1]);
173 *pChildPid = 0;
174 return 1;
175 }
176 if( *pChildPid==0 ){
177 int fd;
178 int nErr = 0;
179 /* This is the child process */
180 close(0);
181 fd = dup(pout[0]);
182 if( fd!=0 ) nErr++;
183 close(pout[0]);
184 close(pout[1]);
185 close(1);
186 fd = dup(pin[1]);
187 if( fd!=1 ) nErr++;
188 close(pin[0]);
189 close(pin[1]);
190 execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
191 return 1;
192 }else{
193
+1 -1
--- src/printf.c
+++ src/printf.c
@@ -859,11 +859,11 @@
859859
int a, b;
860860
do{
861861
a = *zA++;
862862
b = *zB++;
863863
}while( a==b && a!=0 );
864
- return a - b;
864
+ return ((unsigned char)a) - (unsigned char)b;
865865
}
866866
}
867867
868868
/*
869869
** Case insensitive string comparison.
870870
--- src/printf.c
+++ src/printf.c
@@ -859,11 +859,11 @@
859 int a, b;
860 do{
861 a = *zA++;
862 b = *zB++;
863 }while( a==b && a!=0 );
864 return a - b;
865 }
866 }
867
868 /*
869 ** Case insensitive string comparison.
870
--- src/printf.c
+++ src/printf.c
@@ -859,11 +859,11 @@
859 int a, b;
860 do{
861 a = *zA++;
862 b = *zB++;
863 }while( a==b && a!=0 );
864 return ((unsigned char)a) - (unsigned char)b;
865 }
866 }
867
868 /*
869 ** Case insensitive string comparison.
870
+1 -1
--- src/rebuild.c
+++ src/rebuild.c
@@ -882,11 +882,11 @@
882882
}
883883
884884
/*
885885
** COMMAND: deconstruct
886886
**
887
-** Usage %fossil deconstruct ?OPTIONS? DESTIONATION
887
+** Usage %fossil deconstruct ?OPTIONS? DESTINATION
888888
**
889889
** Options:
890890
** -R|--repository REPOSITORY
891891
** -L|--prefixlength N
892892
**
893893
--- src/rebuild.c
+++ src/rebuild.c
@@ -882,11 +882,11 @@
882 }
883
884 /*
885 ** COMMAND: deconstruct
886 **
887 ** Usage %fossil deconstruct ?OPTIONS? DESTIONATION
888 **
889 ** Options:
890 ** -R|--repository REPOSITORY
891 ** -L|--prefixlength N
892 **
893
--- src/rebuild.c
+++ src/rebuild.c
@@ -882,11 +882,11 @@
882 }
883
884 /*
885 ** COMMAND: deconstruct
886 **
887 ** Usage %fossil deconstruct ?OPTIONS? DESTINATION
888 **
889 ** Options:
890 ** -R|--repository REPOSITORY
891 ** -L|--prefixlength N
892 **
893
+1 -1
--- src/search.c
+++ src/search.c
@@ -203,8 +203,8 @@
203203
db_prepare(&q,
204204
"SELECT rid, uuid, date, comment, 0, 0 FROM srch"
205205
" WHERE x>%d ORDER BY x DESC, date DESC",
206206
iBest/3
207207
);
208
- print_timeline(&q, 1000);
208
+ print_timeline(&q, 1000, 0);
209209
db_finalize(&q);
210210
}
211211
--- src/search.c
+++ src/search.c
@@ -203,8 +203,8 @@
203 db_prepare(&q,
204 "SELECT rid, uuid, date, comment, 0, 0 FROM srch"
205 " WHERE x>%d ORDER BY x DESC, date DESC",
206 iBest/3
207 );
208 print_timeline(&q, 1000);
209 db_finalize(&q);
210 }
211
--- src/search.c
+++ src/search.c
@@ -203,8 +203,8 @@
203 db_prepare(&q,
204 "SELECT rid, uuid, date, comment, 0, 0 FROM srch"
205 " WHERE x>%d ORDER BY x DESC, date DESC",
206 iBest/3
207 );
208 print_timeline(&q, 1000, 0);
209 db_finalize(&q);
210 }
211
+12 -2
--- src/setup.c
+++ src/setup.c
@@ -1050,10 +1050,11 @@
10501050
if( !g.okSetup ){
10511051
login_needed();
10521052
}
10531053
10541054
style_header("Settings");
1055
+ db_open_local();
10551056
db_begin_transaction();
10561057
@ <p>This page provides a simple interface to the "fossil setting" command.
10571058
@ See the "fossil help setting" output below for further information on
10581059
@ the meaning of each setting.</p><hr />
10591060
@ <form action="%s(g.zTop)/setup_settings" method="post"><div>
@@ -1062,25 +1063,34 @@
10621063
for(pSet=ctrlSettings; pSet->name!=0; pSet++){
10631064
if( pSet->width==0 ){
10641065
onoff_attribute(pSet->name, pSet->name,
10651066
pSet->var!=0 ? pSet->var : pSet->name,
10661067
is_truth(pSet->def));
1067
- @ <br />
1068
+ if( pSet->versionable ){
1069
+ @ (v)<br />
1070
+ } else {
1071
+ @ <br />
1072
+ }
10681073
}
10691074
}
10701075
@ </td><td style="width: 30;"></td><td valign="top">
10711076
for(pSet=ctrlSettings; pSet->name!=0; pSet++){
10721077
if( pSet->width!=0 ){
10731078
entry_attribute(pSet->name, /*pSet->width*/ 40, pSet->name,
10741079
pSet->var!=0 ? pSet->var : pSet->name,
10751080
(char*)pSet->def);
1076
- @ <br />
1081
+ if( pSet->versionable ){
1082
+ @ (v)<br />
1083
+ } else {
1084
+ @ <br />
1085
+ }
10771086
}
10781087
}
10791088
@ </td></tr></table>
10801089
@ <p><input type="submit" name="submit" value="Apply Changes" /></p>
10811090
@ </div></form>
1091
+ @ <p>Settings marked with (v) are 'versionable' and will be overridden by the contents of files named <tt>.fossil-settings/PROPERTY</tt>.</p>
10821092
@ <hr /><p>
10831093
@ These settings work in the same way, as the <kbd>set</kbd> commandline:<br />
10841094
@ </p><pre>%s(zHelp_setting_cmd)</pre>
10851095
db_end_transaction(0);
10861096
style_footer();
10871097
--- src/setup.c
+++ src/setup.c
@@ -1050,10 +1050,11 @@
1050 if( !g.okSetup ){
1051 login_needed();
1052 }
1053
1054 style_header("Settings");
 
1055 db_begin_transaction();
1056 @ <p>This page provides a simple interface to the "fossil setting" command.
1057 @ See the "fossil help setting" output below for further information on
1058 @ the meaning of each setting.</p><hr />
1059 @ <form action="%s(g.zTop)/setup_settings" method="post"><div>
@@ -1062,25 +1063,34 @@
1062 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1063 if( pSet->width==0 ){
1064 onoff_attribute(pSet->name, pSet->name,
1065 pSet->var!=0 ? pSet->var : pSet->name,
1066 is_truth(pSet->def));
1067 @ <br />
 
 
 
 
1068 }
1069 }
1070 @ </td><td style="width: 30;"></td><td valign="top">
1071 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1072 if( pSet->width!=0 ){
1073 entry_attribute(pSet->name, /*pSet->width*/ 40, pSet->name,
1074 pSet->var!=0 ? pSet->var : pSet->name,
1075 (char*)pSet->def);
1076 @ <br />
 
 
 
 
1077 }
1078 }
1079 @ </td></tr></table>
1080 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
1081 @ </div></form>
 
1082 @ <hr /><p>
1083 @ These settings work in the same way, as the <kbd>set</kbd> commandline:<br />
1084 @ </p><pre>%s(zHelp_setting_cmd)</pre>
1085 db_end_transaction(0);
1086 style_footer();
1087
--- src/setup.c
+++ src/setup.c
@@ -1050,10 +1050,11 @@
1050 if( !g.okSetup ){
1051 login_needed();
1052 }
1053
1054 style_header("Settings");
1055 db_open_local();
1056 db_begin_transaction();
1057 @ <p>This page provides a simple interface to the "fossil setting" command.
1058 @ See the "fossil help setting" output below for further information on
1059 @ the meaning of each setting.</p><hr />
1060 @ <form action="%s(g.zTop)/setup_settings" method="post"><div>
@@ -1062,25 +1063,34 @@
1063 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1064 if( pSet->width==0 ){
1065 onoff_attribute(pSet->name, pSet->name,
1066 pSet->var!=0 ? pSet->var : pSet->name,
1067 is_truth(pSet->def));
1068 if( pSet->versionable ){
1069 @ (v)<br />
1070 } else {
1071 @ <br />
1072 }
1073 }
1074 }
1075 @ </td><td style="width: 30;"></td><td valign="top">
1076 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1077 if( pSet->width!=0 ){
1078 entry_attribute(pSet->name, /*pSet->width*/ 40, pSet->name,
1079 pSet->var!=0 ? pSet->var : pSet->name,
1080 (char*)pSet->def);
1081 if( pSet->versionable ){
1082 @ (v)<br />
1083 } else {
1084 @ <br />
1085 }
1086 }
1087 }
1088 @ </td></tr></table>
1089 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
1090 @ </div></form>
1091 @ <p>Settings marked with (v) are 'versionable' and will be overridden by the contents of files named <tt>.fossil-settings/PROPERTY</tt>.</p>
1092 @ <hr /><p>
1093 @ These settings work in the same way, as the <kbd>set</kbd> commandline:<br />
1094 @ </p><pre>%s(zHelp_setting_cmd)</pre>
1095 db_end_transaction(0);
1096 style_footer();
1097
+3777 -1278
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.7.7. By combining all the individual C code files into this
3
+** version 3.7.8. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -385,23 +385,29 @@
385385
/*
386386
** Exactly one of the following macros must be defined in order to
387387
** specify which memory allocation subsystem to use.
388388
**
389389
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
390
+** SQLITE_WIN32_MALLOC // Use Win32 native heap API
390391
** SQLITE_MEMDEBUG // Debugging version of system malloc()
392
+**
393
+** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
394
+** assert() macro is enabled, each call into the Win32 native heap subsystem
395
+** will cause HeapValidate to be called. If heap validation should fail, an
396
+** assertion will be triggered.
391397
**
392398
** (Historical note: There used to be several other options, but we've
393399
** pared it down to just these two.)
394400
**
395401
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
396402
** the default.
397403
*/
398
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
404
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
399405
# error "At most one of the following compile-time configuration options\
400
- is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
406
+ is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"
401407
#endif
402
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
408
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
403409
# define SQLITE_SYSTEM_MALLOC 1
404410
#endif
405411
406412
/*
407413
** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
@@ -648,13 +654,13 @@
648654
**
649655
** See also: [sqlite3_libversion()],
650656
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651657
** [sqlite_version()] and [sqlite_source_id()].
652658
*/
653
-#define SQLITE_VERSION "3.7.7"
654
-#define SQLITE_VERSION_NUMBER 3007007
655
-#define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
659
+#define SQLITE_VERSION "3.7.8"
660
+#define SQLITE_VERSION_NUMBER 3007008
661
+#define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
656662
657663
/*
658664
** CAPI3REF: Run-Time Library Version Numbers
659665
** KEYWORDS: sqlite3_version, sqlite3_sourceid
660666
**
@@ -851,11 +857,11 @@
851857
** semicolon-separate SQL statements passed into its 2nd argument,
852858
** in the context of the [database connection] passed in as its 1st
853859
** argument. ^If the callback function of the 3rd argument to
854860
** sqlite3_exec() is not NULL, then it is invoked for each result row
855861
** coming out of the evaluated SQL statements. ^The 4th argument to
856
-** to sqlite3_exec() is relayed through to the 1st argument of each
862
+** sqlite3_exec() is relayed through to the 1st argument of each
857863
** callback invocation. ^If the callback pointer to sqlite3_exec()
858864
** is NULL, then no callback is ever invoked and result rows are
859865
** ignored.
860866
**
861867
** ^If an error occurs while evaluating the SQL statements passed into
@@ -1282,20 +1288,52 @@
12821288
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
12831289
** VFSes do not need this signal and should silently ignore this opcode.
12841290
** Applications should not call [sqlite3_file_control()] with this
12851291
** opcode as doing so may disrupt the operation of the specialized VFSes
12861292
** that do require it.
1293
+**
1294
+** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
1295
+** retry counts and intervals for certain disk I/O operations for the
1296
+** windows [VFS] in order to work to provide robustness against
1297
+** anti-virus programs. By default, the windows VFS will retry file read,
1298
+** file write, and file delete opertions up to 10 times, with a delay
1299
+** of 25 milliseconds before the first retry and with the delay increasing
1300
+** by an additional 25 milliseconds with each subsequent retry. This
1301
+** opcode allows those to values (10 retries and 25 milliseconds of delay)
1302
+** to be adjusted. The values are changed for all database connections
1303
+** within the same process. The argument is a pointer to an array of two
1304
+** integers where the first integer i the new retry count and the second
1305
+** integer is the delay. If either integer is negative, then the setting
1306
+** is not changed but instead the prior value of that setting is written
1307
+** into the array entry, allowing the current retry settings to be
1308
+** interrogated. The zDbName parameter is ignored.
1309
+**
1310
+** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
1311
+** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
1312
+** write ahead log and shared memory files used for transaction control
1313
+** are automatically deleted when the latest connection to the database
1314
+** closes. Setting persistent WAL mode causes those files to persist after
1315
+** close. Persisting the files is useful when other processes that do not
1316
+** have write permission on the directory containing the database file want
1317
+** to read the database file, as the WAL and shared memory files must exist
1318
+** in order for the database to be readable. The fourth parameter to
1319
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
1320
+** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
1321
+** WAL mode. If the integer is -1, then it is overwritten with the current
1322
+** WAL persistence setting.
1323
+**
12871324
*/
12881325
#define SQLITE_FCNTL_LOCKSTATE 1
12891326
#define SQLITE_GET_LOCKPROXYFILE 2
12901327
#define SQLITE_SET_LOCKPROXYFILE 3
12911328
#define SQLITE_LAST_ERRNO 4
12921329
#define SQLITE_FCNTL_SIZE_HINT 5
12931330
#define SQLITE_FCNTL_CHUNK_SIZE 6
12941331
#define SQLITE_FCNTL_FILE_POINTER 7
12951332
#define SQLITE_FCNTL_SYNC_OMITTED 8
1296
-
1333
+#define SQLITE_FCNTL_WIN32_AV_RETRY 9
1334
+#define SQLITE_FCNTL_PERSIST_WAL 10
12971335
12981336
/*
12991337
** CAPI3REF: Mutex Handle
13001338
**
13011339
** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -1443,11 +1481,11 @@
14431481
** The xSleep() method causes the calling thread to sleep for at
14441482
** least the number of microseconds given. ^The xCurrentTime()
14451483
** method returns a Julian Day Number for the current date and time as
14461484
** a floating point value.
14471485
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
1448
-** Day Number multipled by 86400000 (the number of milliseconds in
1486
+** Day Number multiplied by 86400000 (the number of milliseconds in
14491487
** a 24-hour day).
14501488
** ^SQLite will use the xCurrentTimeInt64() method to get the current
14511489
** date and time if that method is available (if iVersion is 2 or
14521490
** greater and the function pointer is not NULL) and will fall back
14531491
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
@@ -1719,20 +1757,14 @@
17191757
** also used during testing of SQLite in order to specify an alternative
17201758
** memory allocator that simulates memory out-of-memory conditions in
17211759
** order to verify that SQLite recovers gracefully from such
17221760
** conditions.
17231761
**
1724
-** The xMalloc and xFree methods must work like the
1725
-** malloc() and free() functions from the standard C library.
1726
-** The xRealloc method must work like realloc() from the standard C library
1727
-** with the exception that if the second argument to xRealloc is zero,
1728
-** xRealloc must be a no-op - it must not perform any allocation or
1729
-** deallocation. ^SQLite guarantees that the second argument to
1762
+** The xMalloc, xRealloc, and xFree methods must work like the
1763
+** malloc(), realloc() and free() functions from the standard C library.
1764
+** ^SQLite guarantees that the second argument to
17301765
** xRealloc is always a value returned by a prior call to xRoundup.
1731
-** And so in cases where xRoundup always returns a positive number,
1732
-** xRealloc can perform exactly as the standard library realloc() and
1733
-** still be in compliance with this specification.
17341766
**
17351767
** xSize should return the allocated size of a memory allocation
17361768
** previously obtained from xMalloc or xRealloc. The allocated size
17371769
** is always at least as big as the requested size but may be larger.
17381770
**
@@ -1881,11 +1913,11 @@
18811913
** scratch memory beyond what is provided by this configuration option, then
18821914
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
18831915
**
18841916
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
18851917
** <dd> ^This option specifies a static memory buffer that SQLite can use for
1886
-** the database page cache with the default page cache implemenation.
1918
+** the database page cache with the default page cache implementation.
18871919
** This configuration should not be used if an application-define page
18881920
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
18891921
** There are three arguments to this option: A pointer to 8-byte aligned
18901922
** memory, the size of each page buffer (sz), and the number of pages (N).
18911923
** The sz argument should be the size of the largest database page
@@ -2979,16 +3011,16 @@
29793011
** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
29803012
**
29813013
** ^If [URI filename] interpretation is enabled, and the filename argument
29823014
** begins with "file:", then the filename is interpreted as a URI. ^URI
29833015
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2984
-** is set in the fourth argument to sqlite3_open_v2(), or if it has
3016
+** set in the fourth argument to sqlite3_open_v2(), or if it has
29853017
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
29863018
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
29873019
** As of SQLite version 3.7.7, URI filename interpretation is turned off
29883020
** by default, but future releases of SQLite might enable URI filename
2989
-** intepretation by default. See "[URI filenames]" for additional
3021
+** interpretation by default. See "[URI filenames]" for additional
29903022
** information.
29913023
**
29923024
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
29933025
** authority, then it must be either an empty string or the string
29943026
** "localhost". ^If the authority is not an empty string or "localhost", an
@@ -3803,11 +3835,11 @@
38033835
** [extended result codes] might be returned as well.
38043836
**
38053837
** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
38063838
** database locks it needs to do its job. ^If the statement is a [COMMIT]
38073839
** or occurs outside of an explicit transaction, then you can retry the
3808
-** statement. If the statement is not a [COMMIT] and occurs within a
3840
+** statement. If the statement is not a [COMMIT] and occurs within an
38093841
** explicit transaction then you should rollback the transaction before
38103842
** continuing.
38113843
**
38123844
** ^[SQLITE_DONE] means that the statement has finished executing
38133845
** successfully. sqlite3_step() should not be called again on this virtual
@@ -4082,11 +4114,11 @@
40824114
40834115
/*
40844116
** CAPI3REF: Destroy A Prepared Statement Object
40854117
**
40864118
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
4087
-** ^If the most recent evaluation of the statement encountered no errors or
4119
+** ^If the most recent evaluation of the statement encountered no errors
40884120
** or if the statement is never been evaluated, then sqlite3_finalize() returns
40894121
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
40904122
** sqlite3_finalize(S) returns the appropriate [error code] or
40914123
** [extended error code].
40924124
**
@@ -5996,11 +6028,11 @@
59966028
** versions of these routines, it should at least provide stubs that always
59976029
** return true so that one does not get spurious assertion failures.
59986030
**
59996031
** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
60006032
** the routine should return 1. This seems counter-intuitive since
6001
-** clearly the mutex cannot be held if it does not exist. But the
6033
+** clearly the mutex cannot be held if it does not exist. But
60026034
** the reason the mutex does not exist is because the build is not
60036035
** using mutexes. And we do not want the assert() containing the
60046036
** call to sqlite3_mutex_held() to fail, so a non-zero return is
60056037
** the appropriate thing to do. ^The sqlite3_mutex_notheld()
60066038
** interface should also return 1 when given a NULL pointer.
@@ -6119,11 +6151,12 @@
61196151
#define SQLITE_TESTCTRL_RESERVE 14
61206152
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
61216153
#define SQLITE_TESTCTRL_ISKEYWORD 16
61226154
#define SQLITE_TESTCTRL_PGHDRSZ 17
61236155
#define SQLITE_TESTCTRL_SCRATCHMALLOC 18
6124
-#define SQLITE_TESTCTRL_LAST 18
6156
+#define SQLITE_TESTCTRL_LOCALTIME_FAULT 19
6157
+#define SQLITE_TESTCTRL_LAST 19
61256158
61266159
/*
61276160
** CAPI3REF: SQLite Runtime Status
61286161
**
61296162
** ^This interface is used to retrieve runtime status information
@@ -6505,11 +6538,11 @@
65056538
** [[the xFetch() page cache methods]]
65066539
** The xFetch() method locates a page in the cache and returns a pointer to
65076540
** the page, or a NULL pointer.
65086541
** A "page", in this context, means a buffer of szPage bytes aligned at an
65096542
** 8-byte boundary. The page to be fetched is determined by the key. ^The
6510
-** mimimum key value is 1. After it has been retrieved using xFetch, the page
6543
+** minimum key value is 1. After it has been retrieved using xFetch, the page
65116544
** is considered to be "pinned".
65126545
**
65136546
** If the requested page is already in the page cache, then the page cache
65146547
** implementation must return a pointer to the page buffer with its content
65156548
** intact. If the requested page is not already in the cache, then the
@@ -7599,10 +7632,18 @@
75997632
*/
76007633
#ifndef SQLITE_TEMP_STORE
76017634
# define SQLITE_TEMP_STORE 1
76027635
#endif
76037636
7637
+/*
7638
+** If all temporary storage is in-memory, then omit the external merge-sort
7639
+** logic since it is superfluous.
7640
+*/
7641
+#if SQLITE_TEMP_STORE==3 && !defined(SQLITE_OMIT_MERGE_SORT)
7642
+# define SQLITE_OMIT_MERGE_SORT
7643
+#endif
7644
+
76047645
/*
76057646
** GCC does not define the offsetof() macro so we'll have to do it
76067647
** ourselves.
76077648
*/
76087649
#ifndef offsetof
@@ -7941,10 +7982,11 @@
79417982
#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
79427983
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
79437984
#define BTREE_MEMORY 4 /* This is an in-memory DB */
79447985
#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
79457986
#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
7987
+#define BTREE_SORTER 32 /* Used as accumulator in external merge sort */
79467988
79477989
SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
79487990
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
79497991
SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
79507992
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
@@ -8143,10 +8185,11 @@
81438185
** or VDBE. The VDBE implements an abstract machine that runs a
81448186
** simple program to access and modify the underlying database.
81458187
*/
81468188
#ifndef _SQLITE_VDBE_H_
81478189
#define _SQLITE_VDBE_H_
8190
+/* #include <stdio.h> */
81488191
81498192
/*
81508193
** A single VDBE is an opaque structure named "Vdbe". Only routines
81518194
** in the source file sqliteVdbe.c are allowed to see the insides
81528195
** of this structure.
@@ -8186,10 +8229,11 @@
81868229
Mem *pMem; /* Used when p4type is P4_MEM */
81878230
VTable *pVtab; /* Used when p4type is P4_VTAB */
81888231
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
81898232
int *ai; /* Used when p4type is P4_INTARRAY */
81908233
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
8234
+ int (*xAdvance)(BtCursor *, int *);
81918235
} p4;
81928236
#ifdef SQLITE_DEBUG
81938237
char *zComment; /* Comment to improve readability */
81948238
#endif
81958239
#ifdef VDBE_PROFILE
@@ -8241,10 +8285,11 @@
82418285
#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
82428286
#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
82438287
#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
82448288
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
82458289
#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
8290
+#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
82468291
82478292
/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
82488293
** is made. That copy is freed when the Vdbe is finalized. But if the
82498294
** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still
82508295
** gets freed when the Vdbe is finalized so it still should be obtained
@@ -8354,89 +8399,89 @@
83548399
#define OP_ReadCookie 35
83558400
#define OP_SetCookie 36
83568401
#define OP_VerifyCookie 37
83578402
#define OP_OpenRead 38
83588403
#define OP_OpenWrite 39
8359
-#define OP_OpenAutoindex 40
8360
-#define OP_OpenEphemeral 41
8361
-#define OP_OpenPseudo 42
8362
-#define OP_Close 43
8363
-#define OP_SeekLt 44
8364
-#define OP_SeekLe 45
8365
-#define OP_SeekGe 46
8366
-#define OP_SeekGt 47
8367
-#define OP_Seek 48
8368
-#define OP_NotFound 49
8369
-#define OP_Found 50
8370
-#define OP_IsUnique 51
8371
-#define OP_NotExists 52
8372
-#define OP_Sequence 53
8373
-#define OP_NewRowid 54
8374
-#define OP_Insert 55
8375
-#define OP_InsertInt 56
8376
-#define OP_Delete 57
8377
-#define OP_ResetCount 58
8378
-#define OP_RowKey 59
8379
-#define OP_RowData 60
8380
-#define OP_Rowid 61
8381
-#define OP_NullRow 62
8382
-#define OP_Last 63
8383
-#define OP_Sort 64
8384
-#define OP_Rewind 65
8385
-#define OP_Prev 66
8386
-#define OP_Next 67
8387
-#define OP_IdxInsert 70
8388
-#define OP_IdxDelete 71
8389
-#define OP_IdxRowid 72
8390
-#define OP_IdxLT 81
8391
-#define OP_IdxGE 92
8392
-#define OP_Destroy 95
8393
-#define OP_Clear 96
8394
-#define OP_CreateIndex 97
8395
-#define OP_CreateTable 98
8396
-#define OP_ParseSchema 99
8397
-#define OP_LoadAnalysis 100
8398
-#define OP_DropTable 101
8399
-#define OP_DropIndex 102
8400
-#define OP_DropTrigger 103
8401
-#define OP_IntegrityCk 104
8402
-#define OP_RowSetAdd 105
8403
-#define OP_RowSetRead 106
8404
-#define OP_RowSetTest 107
8405
-#define OP_Program 108
8406
-#define OP_Param 109
8407
-#define OP_FkCounter 110
8408
-#define OP_FkIfZero 111
8409
-#define OP_MemMax 112
8410
-#define OP_IfPos 113
8411
-#define OP_IfNeg 114
8412
-#define OP_IfZero 115
8413
-#define OP_AggStep 116
8414
-#define OP_AggFinal 117
8415
-#define OP_Checkpoint 118
8416
-#define OP_JournalMode 119
8417
-#define OP_Vacuum 120
8418
-#define OP_IncrVacuum 121
8419
-#define OP_Expire 122
8420
-#define OP_TableLock 123
8421
-#define OP_VBegin 124
8422
-#define OP_VCreate 125
8423
-#define OP_VDestroy 126
8424
-#define OP_VOpen 127
8425
-#define OP_VFilter 128
8426
-#define OP_VColumn 129
8427
-#define OP_VNext 131
8428
-#define OP_VRename 132
8429
-#define OP_VUpdate 133
8430
-#define OP_Pagecount 134
8431
-#define OP_MaxPgcnt 135
8432
-#define OP_Trace 136
8433
-#define OP_Noop 137
8434
-#define OP_Explain 138
8435
-
8436
-/* The following opcode values are never used */
8437
-#define OP_NotUsed_139 139
8404
+#define OP_OpenSorter 40
8405
+#define OP_OpenAutoindex 41
8406
+#define OP_OpenEphemeral 42
8407
+#define OP_OpenPseudo 43
8408
+#define OP_Close 44
8409
+#define OP_SeekLt 45
8410
+#define OP_SeekLe 46
8411
+#define OP_SeekGe 47
8412
+#define OP_SeekGt 48
8413
+#define OP_Seek 49
8414
+#define OP_NotFound 50
8415
+#define OP_Found 51
8416
+#define OP_IsUnique 52
8417
+#define OP_NotExists 53
8418
+#define OP_Sequence 54
8419
+#define OP_NewRowid 55
8420
+#define OP_Insert 56
8421
+#define OP_InsertInt 57
8422
+#define OP_Delete 58
8423
+#define OP_ResetCount 59
8424
+#define OP_RowKey 60
8425
+#define OP_RowData 61
8426
+#define OP_Rowid 62
8427
+#define OP_NullRow 63
8428
+#define OP_Last 64
8429
+#define OP_Sort 65
8430
+#define OP_Rewind 66
8431
+#define OP_Prev 67
8432
+#define OP_Next 70
8433
+#define OP_IdxInsert 71
8434
+#define OP_IdxDelete 72
8435
+#define OP_IdxRowid 81
8436
+#define OP_IdxLT 92
8437
+#define OP_IdxGE 95
8438
+#define OP_Destroy 96
8439
+#define OP_Clear 97
8440
+#define OP_CreateIndex 98
8441
+#define OP_CreateTable 99
8442
+#define OP_ParseSchema 100
8443
+#define OP_LoadAnalysis 101
8444
+#define OP_DropTable 102
8445
+#define OP_DropIndex 103
8446
+#define OP_DropTrigger 104
8447
+#define OP_IntegrityCk 105
8448
+#define OP_RowSetAdd 106
8449
+#define OP_RowSetRead 107
8450
+#define OP_RowSetTest 108
8451
+#define OP_Program 109
8452
+#define OP_Param 110
8453
+#define OP_FkCounter 111
8454
+#define OP_FkIfZero 112
8455
+#define OP_MemMax 113
8456
+#define OP_IfPos 114
8457
+#define OP_IfNeg 115
8458
+#define OP_IfZero 116
8459
+#define OP_AggStep 117
8460
+#define OP_AggFinal 118
8461
+#define OP_Checkpoint 119
8462
+#define OP_JournalMode 120
8463
+#define OP_Vacuum 121
8464
+#define OP_IncrVacuum 122
8465
+#define OP_Expire 123
8466
+#define OP_TableLock 124
8467
+#define OP_VBegin 125
8468
+#define OP_VCreate 126
8469
+#define OP_VDestroy 127
8470
+#define OP_VOpen 128
8471
+#define OP_VFilter 129
8472
+#define OP_VColumn 131
8473
+#define OP_VNext 132
8474
+#define OP_VRename 133
8475
+#define OP_VUpdate 134
8476
+#define OP_Pagecount 135
8477
+#define OP_MaxPgcnt 136
8478
+#define OP_Trace 137
8479
+#define OP_Noop 138
8480
+#define OP_Explain 139
8481
+
8482
+/* The following opcode values are never used */
84388483
#define OP_NotUsed_140 140
84398484
84408485
84418486
/* Properties such as "out2" or "jump" that are specified in
84428487
** comments following the "case" for each opcode in the vdbe.c
@@ -8453,23 +8498,23 @@
84538498
/* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
84548499
/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
84558500
/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
84568501
/* 24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
84578502
/* 32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
8458
-/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
8459
-/* 48 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00,\
8460
-/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
8461
-/* 64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x08, 0x00,\
8462
-/* 72 */ 0x02, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8463
-/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
8464
-/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x02,\
8465
-/* 96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
8466
-/* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\
8467
-/* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
8468
-/* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
8469
-/* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x02,\
8470
-/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
8503
+/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,\
8504
+/* 48 */ 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02,\
8505
+/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,\
8506
+/* 64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x01, 0x08,\
8507
+/* 72 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8508
+/* 80 */ 0x15, 0x02, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
8509
+/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
8510
+/* 96 */ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\
8511
+/* 104 */ 0x00, 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00,\
8512
+/* 112 */ 0x01, 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
8513
+/* 120 */ 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\
8514
+/* 128 */ 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x02,\
8515
+/* 136 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
84718516
/* 144 */ 0x04, 0x04,}
84728517
84738518
/************** End of opcodes.h *********************************************/
84748519
/************** Continuing where we left off in vdbe.h ***********************/
84758520
@@ -8484,13 +8529,13 @@
84848529
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
84858530
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
84868531
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
84878532
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
84888533
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
8489
-SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
8490
-SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
8491
-SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
8534
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
8535
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
8536
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
84928537
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
84938538
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
84948539
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
84958540
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
84968541
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
@@ -8608,10 +8653,11 @@
86088653
** NOTE: These values must match the corresponding BTREE_ values in btree.h.
86098654
*/
86108655
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
86118656
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
86128657
#define PAGER_MEMORY 0x0004 /* In-memory database */
8658
+#define PAGER_SORTER 0x0020 /* Accumulator in external merge sort */
86138659
86148660
/*
86158661
** Valid values for the second argument to sqlite3PagerLockingMode().
86168662
*/
86178663
#define PAGER_LOCKINGMODE_QUERY -1
@@ -8703,10 +8749,13 @@
87038749
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
87048750
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
87058751
SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
87068752
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
87078753
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
8754
+#ifndef SQLITE_OMIT_MERGE_SORT
8755
+SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager*);
8756
+#endif
87088757
87098758
/* Functions used to truncate the database file. */
87108759
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
87118760
87128761
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
@@ -9556,10 +9605,12 @@
95569605
#define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */
95579606
#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
95589607
#define SQLITE_IndexCover 0x10 /* Disable index covering table */
95599608
#define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
95609609
#define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
9610
+#define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */
9611
+#define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */
95619612
#define SQLITE_OptMask 0xff /* Mask of all disablable opts */
95629613
95639614
/*
95649615
** Possible values for the sqlite.magic field.
95659616
** The numbers are obtained at random and have no special meaning, other
@@ -10447,10 +10498,11 @@
1044710498
Table *pTab; /* An SQL table corresponding to zName */
1044810499
Select *pSelect; /* A SELECT statement used in place of a table name */
1044910500
u8 isPopulated; /* Temporary table associated with SELECT is populated */
1045010501
u8 jointype; /* Type of join between this able and the previous */
1045110502
u8 notIndexed; /* True if there is a NOT INDEXED clause */
10503
+ u8 isCorrelated; /* True if sub-query is correlated */
1045210504
#ifndef SQLITE_OMIT_EXPLAIN
1045310505
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
1045410506
#endif
1045510507
int iCursor; /* The VDBE cursor number used to access this table */
1045610508
Expr *pOn; /* The ON clause of a join */
@@ -10566,10 +10618,11 @@
1056610618
struct WhereInfo {
1056710619
Parse *pParse; /* Parsing and code generating context */
1056810620
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
1056910621
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
1057010622
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
10623
+ u8 eDistinct;
1057110624
SrcList *pTabList; /* List of tables in the join */
1057210625
int iTop; /* The very beginning of the WHERE loop */
1057310626
int iContinue; /* Jump here to continue with next record */
1057410627
int iBreak; /* Jump here to break out of the loop */
1057510628
int nLevel; /* Number of nested loop */
@@ -10577,10 +10630,13 @@
1057710630
double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
1057810631
double nRowOut; /* Estimated number of output rows */
1057910632
WhereLevel a[1]; /* Information about each nest loop in WHERE */
1058010633
};
1058110634
10635
+#define WHERE_DISTINCT_UNIQUE 1
10636
+#define WHERE_DISTINCT_ORDERED 2
10637
+
1058210638
/*
1058310639
** A NameContext defines a context in which to resolve table and column
1058410640
** names. The context consists of a list of tables (the pSrcList) field and
1058510641
** a list of named expression (pEList). The named expression list may
1058610642
** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
@@ -11053,10 +11109,11 @@
1105311109
int isPCacheInit; /* True after malloc is initialized */
1105411110
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
1105511111
int nRefInitMutex; /* Number of users of pInitMutex */
1105611112
void (*xLog)(void*,int,const char*); /* Function for logging */
1105711113
void *pLogArg; /* First argument to xLog() */
11114
+ int bLocaltimeFault; /* True to fail localtime() calls */
1105811115
};
1105911116
1106011117
/*
1106111118
** Context pointer passed down through the tree-walk.
1106211119
*/
@@ -11337,11 +11394,11 @@
1133711394
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
1133811395
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
1133911396
#endif
1134011397
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
1134111398
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11342
-SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
11399
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
1134311400
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
1134411401
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
1134511402
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
1134611403
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
1134711404
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
@@ -12013,10 +12070,11 @@
1201312070
0, /* isPCacheInit */
1201412071
0, /* pInitMutex */
1201512072
0, /* nRefInitMutex */
1201612073
0, /* xLog */
1201712074
0, /* pLogArg */
12075
+ 0, /* bLocaltimeFault */
1201812076
};
1201912077
1202012078
1202112079
/*
1202212080
** Hash table for global functions - functions common to all
@@ -12321,10 +12379,13 @@
1232112379
#ifdef SQLITE_OMIT_LOOKASIDE
1232212380
"OMIT_LOOKASIDE",
1232312381
#endif
1232412382
#ifdef SQLITE_OMIT_MEMORYDB
1232512383
"OMIT_MEMORYDB",
12384
+#endif
12385
+#ifdef SQLITE_OMIT_MERGE_SORT
12386
+ "OMIT_MERGE_SORT",
1232612387
#endif
1232712388
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
1232812389
"OMIT_OR_OPTIMIZATION",
1232912390
#endif
1233012391
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
@@ -12387,10 +12448,13 @@
1238712448
#ifdef SQLITE_OMIT_WSD
1238812449
"OMIT_WSD",
1238912450
#endif
1239012451
#ifdef SQLITE_OMIT_XFER_OPT
1239112452
"OMIT_XFER_OPT",
12453
+#endif
12454
+#ifdef SQLITE_PAGECACHE_BLOCKALLOC
12455
+ "PAGECACHE_BLOCKALLOC",
1239212456
#endif
1239312457
#ifdef SQLITE_PERFORMANCE_TRACE
1239412458
"PERFORMANCE_TRACE",
1239512459
#endif
1239612460
#ifdef SQLITE_PROXY_DEBUG
@@ -12508,10 +12572,13 @@
1250812572
/*
1250912573
** Boolean values
1251012574
*/
1251112575
typedef unsigned char Bool;
1251212576
12577
+/* Opaque type used by code in vdbesort.c */
12578
+typedef struct VdbeSorter VdbeSorter;
12579
+
1251312580
/*
1251412581
** A cursor is a pointer into a single BTree within a database file.
1251512582
** The cursor can seek to a BTree entry with a particular key, or
1251612583
** loop over all entries of the Btree. You can also insert new BTree
1251712584
** entries or retrieve the key or data from the entry that the cursor
@@ -12539,10 +12606,11 @@
1253912606
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
1254012607
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
1254112608
i64 seqCount; /* Sequence counter */
1254212609
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
1254312610
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
12611
+ VdbeSorter *pSorter; /* Sorter object for OP_OpenSorter cursors */
1254412612
1254512613
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
1254612614
** OP_IsUnique opcode on this cursor. */
1254712615
int seekResult;
1254812616
@@ -12858,17 +12926,36 @@
1285812926
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
1285912927
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
1286012928
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
1286112929
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
1286212930
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
12931
+#define MemReleaseExt(X) \
12932
+ if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
12933
+ sqlite3VdbeMemReleaseExternal(X);
1286312934
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
1286412935
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
1286512936
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
1286612937
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
1286712938
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
1286812939
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
1286912940
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
12941
+
12942
+#ifdef SQLITE_OMIT_MERGE_SORT
12943
+# define sqlite3VdbeSorterInit(Y,Z) SQLITE_OK
12944
+# define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
12945
+# define sqlite3VdbeSorterClose(Y,Z)
12946
+# define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
12947
+# define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
12948
+# define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
12949
+#else
12950
+SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
12951
+SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, int);
12952
+SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
12953
+SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
12954
+SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
12955
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
12956
+#endif
1287012957
1287112958
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
1287212959
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
1287312960
SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
1287412961
#else
@@ -13159,30 +13246,16 @@
1315913246
** Astronomical Algorithms, 2nd Edition, 1998
1316013247
** ISBM 0-943396-61-1
1316113248
** Willmann-Bell, Inc
1316213249
** Richmond, Virginia (USA)
1316313250
*/
13251
+/* #include <stdlib.h> */
13252
+/* #include <assert.h> */
1316413253
#include <time.h>
1316513254
1316613255
#ifndef SQLITE_OMIT_DATETIME_FUNCS
1316713256
13168
-/*
13169
-** On recent Windows platforms, the localtime_s() function is available
13170
-** as part of the "Secure CRT". It is essentially equivalent to
13171
-** localtime_r() available under most POSIX platforms, except that the
13172
-** order of the parameters is reversed.
13173
-**
13174
-** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
13175
-**
13176
-** If the user has not indicated to use localtime_r() or localtime_s()
13177
-** already, check for an MSVC build environment that provides
13178
-** localtime_s().
13179
-*/
13180
-#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
13181
- defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
13182
-#define HAVE_LOCALTIME_S 1
13183
-#endif
1318413257
1318513258
/*
1318613259
** A structure for holding a single date and time.
1318713260
*/
1318813261
typedef struct DateTime DateTime;
@@ -13523,20 +13596,90 @@
1352313596
static void clearYMD_HMS_TZ(DateTime *p){
1352413597
p->validYMD = 0;
1352513598
p->validHMS = 0;
1352613599
p->validTZ = 0;
1352713600
}
13601
+
13602
+/*
13603
+** On recent Windows platforms, the localtime_s() function is available
13604
+** as part of the "Secure CRT". It is essentially equivalent to
13605
+** localtime_r() available under most POSIX platforms, except that the
13606
+** order of the parameters is reversed.
13607
+**
13608
+** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
13609
+**
13610
+** If the user has not indicated to use localtime_r() or localtime_s()
13611
+** already, check for an MSVC build environment that provides
13612
+** localtime_s().
13613
+*/
13614
+#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
13615
+ defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
13616
+#define HAVE_LOCALTIME_S 1
13617
+#endif
13618
+
13619
+#ifndef SQLITE_OMIT_LOCALTIME
13620
+/*
13621
+** The following routine implements the rough equivalent of localtime_r()
13622
+** using whatever operating-system specific localtime facility that
13623
+** is available. This routine returns 0 on success and
13624
+** non-zero on any kind of error.
13625
+**
13626
+** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
13627
+** routine will always fail.
13628
+*/
13629
+static int osLocaltime(time_t *t, struct tm *pTm){
13630
+ int rc;
13631
+#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
13632
+ && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
13633
+ struct tm *pX;
13634
+#if SQLITE_THREADSAFE>0
13635
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
13636
+#endif
13637
+ sqlite3_mutex_enter(mutex);
13638
+ pX = localtime(t);
13639
+#ifndef SQLITE_OMIT_BUILTIN_TEST
13640
+ if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
13641
+#endif
13642
+ if( pX ) *pTm = *pX;
13643
+ sqlite3_mutex_leave(mutex);
13644
+ rc = pX==0;
13645
+#else
13646
+#ifndef SQLITE_OMIT_BUILTIN_TEST
13647
+ if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
13648
+#endif
13649
+#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
13650
+ rc = localtime_r(t, pTm)==0;
13651
+#else
13652
+ rc = localtime_s(pTm, t);
13653
+#endif /* HAVE_LOCALTIME_R */
13654
+#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
13655
+ return rc;
13656
+}
13657
+#endif /* SQLITE_OMIT_LOCALTIME */
13658
+
1352813659
1352913660
#ifndef SQLITE_OMIT_LOCALTIME
1353013661
/*
13531
-** Compute the difference (in milliseconds)
13532
-** between localtime and UTC (a.k.a. GMT)
13533
-** for the time value p where p is in UTC.
13662
+** Compute the difference (in milliseconds) between localtime and UTC
13663
+** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
13664
+** return this value and set *pRc to SQLITE_OK.
13665
+**
13666
+** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
13667
+** is undefined in this case.
1353413668
*/
13535
-static sqlite3_int64 localtimeOffset(DateTime *p){
13669
+static sqlite3_int64 localtimeOffset(
13670
+ DateTime *p, /* Date at which to calculate offset */
13671
+ sqlite3_context *pCtx, /* Write error here if one occurs */
13672
+ int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
13673
+){
1353613674
DateTime x, y;
1353713675
time_t t;
13676
+ struct tm sLocal;
13677
+
13678
+ /* Initialize the contents of sLocal to avoid a compiler warning. */
13679
+ memset(&sLocal, 0, sizeof(sLocal));
13680
+
1353813681
x = *p;
1353913682
computeYMD_HMS(&x);
1354013683
if( x.Y<1971 || x.Y>=2038 ){
1354113684
x.Y = 2000;
1354213685
x.M = 1;
@@ -13550,51 +13693,27 @@
1355013693
}
1355113694
x.tz = 0;
1355213695
x.validJD = 0;
1355313696
computeJD(&x);
1355413697
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
13555
-#ifdef HAVE_LOCALTIME_R
13556
- {
13557
- struct tm sLocal;
13558
- localtime_r(&t, &sLocal);
13559
- y.Y = sLocal.tm_year + 1900;
13560
- y.M = sLocal.tm_mon + 1;
13561
- y.D = sLocal.tm_mday;
13562
- y.h = sLocal.tm_hour;
13563
- y.m = sLocal.tm_min;
13564
- y.s = sLocal.tm_sec;
13565
- }
13566
-#elif defined(HAVE_LOCALTIME_S) && HAVE_LOCALTIME_S
13567
- {
13568
- struct tm sLocal;
13569
- localtime_s(&sLocal, &t);
13570
- y.Y = sLocal.tm_year + 1900;
13571
- y.M = sLocal.tm_mon + 1;
13572
- y.D = sLocal.tm_mday;
13573
- y.h = sLocal.tm_hour;
13574
- y.m = sLocal.tm_min;
13575
- y.s = sLocal.tm_sec;
13576
- }
13577
-#else
13578
- {
13579
- struct tm *pTm;
13580
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
13581
- pTm = localtime(&t);
13582
- y.Y = pTm->tm_year + 1900;
13583
- y.M = pTm->tm_mon + 1;
13584
- y.D = pTm->tm_mday;
13585
- y.h = pTm->tm_hour;
13586
- y.m = pTm->tm_min;
13587
- y.s = pTm->tm_sec;
13588
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
13589
- }
13590
-#endif
13698
+ if( osLocaltime(&t, &sLocal) ){
13699
+ sqlite3_result_error(pCtx, "local time unavailable", -1);
13700
+ *pRc = SQLITE_ERROR;
13701
+ return 0;
13702
+ }
13703
+ y.Y = sLocal.tm_year + 1900;
13704
+ y.M = sLocal.tm_mon + 1;
13705
+ y.D = sLocal.tm_mday;
13706
+ y.h = sLocal.tm_hour;
13707
+ y.m = sLocal.tm_min;
13708
+ y.s = sLocal.tm_sec;
1359113709
y.validYMD = 1;
1359213710
y.validHMS = 1;
1359313711
y.validJD = 0;
1359413712
y.validTZ = 0;
1359513713
computeJD(&y);
13714
+ *pRc = SQLITE_OK;
1359613715
return y.iJD - x.iJD;
1359713716
}
1359813717
#endif /* SQLITE_OMIT_LOCALTIME */
1359913718
1360013719
/*
@@ -13614,13 +13733,16 @@
1361413733
** weekday N
1361513734
** unixepoch
1361613735
** localtime
1361713736
** utc
1361813737
**
13619
-** Return 0 on success and 1 if there is any kind of error.
13738
+** Return 0 on success and 1 if there is any kind of error. If the error
13739
+** is in a system call (i.e. localtime()), then an error message is written
13740
+** to context pCtx. If the error is an unrecognized modifier, no error is
13741
+** written to pCtx.
1362013742
*/
13621
-static int parseModifier(const char *zMod, DateTime *p){
13743
+static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
1362213744
int rc = 1;
1362313745
int n;
1362413746
double r;
1362513747
char *z, zBuf[30];
1362613748
z = zBuf;
@@ -13636,13 +13758,12 @@
1363613758
** Assuming the current time value is UTC (a.k.a. GMT), shift it to
1363713759
** show local time.
1363813760
*/
1363913761
if( strcmp(z, "localtime")==0 ){
1364013762
computeJD(p);
13641
- p->iJD += localtimeOffset(p);
13763
+ p->iJD += localtimeOffset(p, pCtx, &rc);
1364213764
clearYMD_HMS_TZ(p);
13643
- rc = 0;
1364413765
}
1364513766
break;
1364613767
}
1364713768
#endif
1364813769
case 'u': {
@@ -13659,15 +13780,16 @@
1365913780
}
1366013781
#ifndef SQLITE_OMIT_LOCALTIME
1366113782
else if( strcmp(z, "utc")==0 ){
1366213783
sqlite3_int64 c1;
1366313784
computeJD(p);
13664
- c1 = localtimeOffset(p);
13665
- p->iJD -= c1;
13666
- clearYMD_HMS_TZ(p);
13667
- p->iJD += c1 - localtimeOffset(p);
13668
- rc = 0;
13785
+ c1 = localtimeOffset(p, pCtx, &rc);
13786
+ if( rc==SQLITE_OK ){
13787
+ p->iJD -= c1;
13788
+ clearYMD_HMS_TZ(p);
13789
+ p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
13790
+ }
1366913791
}
1367013792
#endif
1367113793
break;
1367213794
}
1367313795
case 'w': {
@@ -13844,13 +13966,12 @@
1384413966
if( !z || parseDateOrTime(context, (char*)z, p) ){
1384513967
return 1;
1384613968
}
1384713969
}
1384813970
for(i=1; i<argc; i++){
13849
- if( (z = sqlite3_value_text(argv[i]))==0 || parseModifier((char*)z, p) ){
13850
- return 1;
13851
- }
13971
+ z = sqlite3_value_text(argv[i]);
13972
+ if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
1385213973
}
1385313974
return 0;
1385413975
}
1385513976
1385613977
@@ -14344,11 +14465,11 @@
1434414465
DO_OS_MALLOC_TEST(0);
1434514466
/* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
1434614467
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
1434714468
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
1434814469
** reaching the VFS. */
14349
- rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f3f, pFlagsOut);
14470
+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
1435014471
assert( rc==SQLITE_OK || pFile->pMethods==0 );
1435114472
return rc;
1435214473
}
1435314474
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
1435414475
return pVfs->xDelete(pVfs, zPath, dirSync);
@@ -14880,10 +15001,11 @@
1488015001
extern void backtrace_symbols_fd(void*const*,int,int);
1488115002
#else
1488215003
# define backtrace(A,B) 1
1488315004
# define backtrace_symbols_fd(A,B,C)
1488415005
#endif
15006
+/* #include <stdio.h> */
1488515007
1488615008
/*
1488715009
** Each memory allocation looks like this:
1488815010
**
1488915011
** ------------------------------------------------------------------------
@@ -15805,11 +15927,11 @@
1580515927
** Free an outstanding memory allocation.
1580615928
**
1580715929
** This function assumes that the necessary mutexes, if any, are
1580815930
** already held by the caller. Hence "Unsafe".
1580915931
*/
15810
-void memsys3FreeUnsafe(void *pOld){
15932
+static void memsys3FreeUnsafe(void *pOld){
1581115933
Mem3Block *p = (Mem3Block*)pOld;
1581215934
int i;
1581315935
u32 size, x;
1581415936
assert( sqlite3_mutex_held(mem3.mutex) );
1581515937
assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
@@ -15880,21 +16002,21 @@
1588016002
}
1588116003
1588216004
/*
1588316005
** Free memory.
1588416006
*/
15885
-void memsys3Free(void *pPrior){
16007
+static void memsys3Free(void *pPrior){
1588616008
assert( pPrior );
1588716009
memsys3Enter();
1588816010
memsys3FreeUnsafe(pPrior);
1588916011
memsys3Leave();
1589016012
}
1589116013
1589216014
/*
1589316015
** Change the size of an existing memory allocation
1589416016
*/
15895
-void *memsys3Realloc(void *pPrior, int nBytes){
16017
+static void *memsys3Realloc(void *pPrior, int nBytes){
1589616018
int nOld;
1589716019
void *p;
1589816020
if( pPrior==0 ){
1589916021
return sqlite3_malloc(nBytes);
1590016022
}
@@ -17983,10 +18105,11 @@
1798318105
**
1798418106
*************************************************************************
1798518107
**
1798618108
** Memory allocation functions used throughout sqlite.
1798718109
*/
18110
+/* #include <stdarg.h> */
1798818111
1798918112
/*
1799018113
** Attempt to release up to n bytes of non-essential memory currently
1799118114
** held by SQLite. An example of non-essential memory is memory used to
1799218115
** cache database pages that are not currently in use.
@@ -19960,10 +20083,11 @@
1996020083
** BOM or Byte Order Mark:
1996120084
** 0xff 0xfe little-endian utf-16 follows
1996220085
** 0xfe 0xff big-endian utf-16 follows
1996320086
**
1996420087
*/
20088
+/* #include <assert.h> */
1996520089
1996620090
#ifndef SQLITE_AMALGAMATION
1996720091
/*
1996820092
** The following constant value is used by the SQLITE_BIGENDIAN and
1996920093
** SQLITE_LITTLEENDIAN macros.
@@ -20502,10 +20626,11 @@
2050220626
**
2050320627
** This file contains functions for allocating memory, comparing
2050420628
** strings, and stuff like that.
2050520629
**
2050620630
*/
20631
+/* #include <stdarg.h> */
2050720632
#ifdef SQLITE_HAVE_ISNAN
2050820633
# include <math.h>
2050920634
#endif
2051020635
2051120636
/*
@@ -21634,26 +21759,32 @@
2163421759
return -x;
2163521760
}
2163621761
2163721762
#ifdef SQLITE_ENABLE_8_3_NAMES
2163821763
/*
21639
-** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
21764
+** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
2164021765
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
2164121766
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
2164221767
** three characters, then shorten the suffix on z[] to be the last three
2164321768
** characters of the original suffix.
21769
+**
21770
+** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
21771
+** do the suffix shortening regardless of URI parameter.
2164421772
**
2164521773
** Examples:
2164621774
**
2164721775
** test.db-journal => test.nal
2164821776
** test.db-wal => test.wal
2164921777
** test.db-shm => test.shm
2165021778
*/
2165121779
SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
21780
+#if SQLITE_ENABLE_8_3_NAMES<2
2165221781
const char *zOk;
2165321782
zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
21654
- if( zOk && sqlite3GetBoolean(zOk) ){
21783
+ if( zOk && sqlite3GetBoolean(zOk) )
21784
+#endif
21785
+ {
2165521786
int i, sz;
2165621787
sz = sqlite3Strlen30(z);
2165721788
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
2165821789
if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
2165921790
}
@@ -21674,10 +21805,11 @@
2167421805
**
2167521806
*************************************************************************
2167621807
** This is the implementation of generic hash-tables
2167721808
** used in SQLite.
2167821809
*/
21810
+/* #include <assert.h> */
2167921811
2168021812
/* Turn bulk memory into a hash table object by initializing the
2168121813
** fields of the Hash structure.
2168221814
**
2168321815
** "pNew" is a pointer to the hash table that is to be initialized.
@@ -21982,52 +22114,52 @@
2198222114
/* 35 */ "ReadCookie",
2198322115
/* 36 */ "SetCookie",
2198422116
/* 37 */ "VerifyCookie",
2198522117
/* 38 */ "OpenRead",
2198622118
/* 39 */ "OpenWrite",
21987
- /* 40 */ "OpenAutoindex",
21988
- /* 41 */ "OpenEphemeral",
21989
- /* 42 */ "OpenPseudo",
21990
- /* 43 */ "Close",
21991
- /* 44 */ "SeekLt",
21992
- /* 45 */ "SeekLe",
21993
- /* 46 */ "SeekGe",
21994
- /* 47 */ "SeekGt",
21995
- /* 48 */ "Seek",
21996
- /* 49 */ "NotFound",
21997
- /* 50 */ "Found",
21998
- /* 51 */ "IsUnique",
21999
- /* 52 */ "NotExists",
22000
- /* 53 */ "Sequence",
22001
- /* 54 */ "NewRowid",
22002
- /* 55 */ "Insert",
22003
- /* 56 */ "InsertInt",
22004
- /* 57 */ "Delete",
22005
- /* 58 */ "ResetCount",
22006
- /* 59 */ "RowKey",
22007
- /* 60 */ "RowData",
22008
- /* 61 */ "Rowid",
22009
- /* 62 */ "NullRow",
22010
- /* 63 */ "Last",
22011
- /* 64 */ "Sort",
22012
- /* 65 */ "Rewind",
22013
- /* 66 */ "Prev",
22014
- /* 67 */ "Next",
22119
+ /* 40 */ "OpenSorter",
22120
+ /* 41 */ "OpenAutoindex",
22121
+ /* 42 */ "OpenEphemeral",
22122
+ /* 43 */ "OpenPseudo",
22123
+ /* 44 */ "Close",
22124
+ /* 45 */ "SeekLt",
22125
+ /* 46 */ "SeekLe",
22126
+ /* 47 */ "SeekGe",
22127
+ /* 48 */ "SeekGt",
22128
+ /* 49 */ "Seek",
22129
+ /* 50 */ "NotFound",
22130
+ /* 51 */ "Found",
22131
+ /* 52 */ "IsUnique",
22132
+ /* 53 */ "NotExists",
22133
+ /* 54 */ "Sequence",
22134
+ /* 55 */ "NewRowid",
22135
+ /* 56 */ "Insert",
22136
+ /* 57 */ "InsertInt",
22137
+ /* 58 */ "Delete",
22138
+ /* 59 */ "ResetCount",
22139
+ /* 60 */ "RowKey",
22140
+ /* 61 */ "RowData",
22141
+ /* 62 */ "Rowid",
22142
+ /* 63 */ "NullRow",
22143
+ /* 64 */ "Last",
22144
+ /* 65 */ "Sort",
22145
+ /* 66 */ "Rewind",
22146
+ /* 67 */ "Prev",
2201522147
/* 68 */ "Or",
2201622148
/* 69 */ "And",
22017
- /* 70 */ "IdxInsert",
22018
- /* 71 */ "IdxDelete",
22019
- /* 72 */ "IdxRowid",
22149
+ /* 70 */ "Next",
22150
+ /* 71 */ "IdxInsert",
22151
+ /* 72 */ "IdxDelete",
2202022152
/* 73 */ "IsNull",
2202122153
/* 74 */ "NotNull",
2202222154
/* 75 */ "Ne",
2202322155
/* 76 */ "Eq",
2202422156
/* 77 */ "Gt",
2202522157
/* 78 */ "Le",
2202622158
/* 79 */ "Lt",
2202722159
/* 80 */ "Ge",
22028
- /* 81 */ "IdxLT",
22160
+ /* 81 */ "IdxRowid",
2202922161
/* 82 */ "BitAnd",
2203022162
/* 83 */ "BitOr",
2203122163
/* 84 */ "ShiftLeft",
2203222164
/* 85 */ "ShiftRight",
2203322165
/* 86 */ "Add",
@@ -22034,58 +22166,58 @@
2203422166
/* 87 */ "Subtract",
2203522167
/* 88 */ "Multiply",
2203622168
/* 89 */ "Divide",
2203722169
/* 90 */ "Remainder",
2203822170
/* 91 */ "Concat",
22039
- /* 92 */ "IdxGE",
22171
+ /* 92 */ "IdxLT",
2204022172
/* 93 */ "BitNot",
2204122173
/* 94 */ "String8",
22042
- /* 95 */ "Destroy",
22043
- /* 96 */ "Clear",
22044
- /* 97 */ "CreateIndex",
22045
- /* 98 */ "CreateTable",
22046
- /* 99 */ "ParseSchema",
22047
- /* 100 */ "LoadAnalysis",
22048
- /* 101 */ "DropTable",
22049
- /* 102 */ "DropIndex",
22050
- /* 103 */ "DropTrigger",
22051
- /* 104 */ "IntegrityCk",
22052
- /* 105 */ "RowSetAdd",
22053
- /* 106 */ "RowSetRead",
22054
- /* 107 */ "RowSetTest",
22055
- /* 108 */ "Program",
22056
- /* 109 */ "Param",
22057
- /* 110 */ "FkCounter",
22058
- /* 111 */ "FkIfZero",
22059
- /* 112 */ "MemMax",
22060
- /* 113 */ "IfPos",
22061
- /* 114 */ "IfNeg",
22062
- /* 115 */ "IfZero",
22063
- /* 116 */ "AggStep",
22064
- /* 117 */ "AggFinal",
22065
- /* 118 */ "Checkpoint",
22066
- /* 119 */ "JournalMode",
22067
- /* 120 */ "Vacuum",
22068
- /* 121 */ "IncrVacuum",
22069
- /* 122 */ "Expire",
22070
- /* 123 */ "TableLock",
22071
- /* 124 */ "VBegin",
22072
- /* 125 */ "VCreate",
22073
- /* 126 */ "VDestroy",
22074
- /* 127 */ "VOpen",
22075
- /* 128 */ "VFilter",
22076
- /* 129 */ "VColumn",
22174
+ /* 95 */ "IdxGE",
22175
+ /* 96 */ "Destroy",
22176
+ /* 97 */ "Clear",
22177
+ /* 98 */ "CreateIndex",
22178
+ /* 99 */ "CreateTable",
22179
+ /* 100 */ "ParseSchema",
22180
+ /* 101 */ "LoadAnalysis",
22181
+ /* 102 */ "DropTable",
22182
+ /* 103 */ "DropIndex",
22183
+ /* 104 */ "DropTrigger",
22184
+ /* 105 */ "IntegrityCk",
22185
+ /* 106 */ "RowSetAdd",
22186
+ /* 107 */ "RowSetRead",
22187
+ /* 108 */ "RowSetTest",
22188
+ /* 109 */ "Program",
22189
+ /* 110 */ "Param",
22190
+ /* 111 */ "FkCounter",
22191
+ /* 112 */ "FkIfZero",
22192
+ /* 113 */ "MemMax",
22193
+ /* 114 */ "IfPos",
22194
+ /* 115 */ "IfNeg",
22195
+ /* 116 */ "IfZero",
22196
+ /* 117 */ "AggStep",
22197
+ /* 118 */ "AggFinal",
22198
+ /* 119 */ "Checkpoint",
22199
+ /* 120 */ "JournalMode",
22200
+ /* 121 */ "Vacuum",
22201
+ /* 122 */ "IncrVacuum",
22202
+ /* 123 */ "Expire",
22203
+ /* 124 */ "TableLock",
22204
+ /* 125 */ "VBegin",
22205
+ /* 126 */ "VCreate",
22206
+ /* 127 */ "VDestroy",
22207
+ /* 128 */ "VOpen",
22208
+ /* 129 */ "VFilter",
2207722209
/* 130 */ "Real",
22078
- /* 131 */ "VNext",
22079
- /* 132 */ "VRename",
22080
- /* 133 */ "VUpdate",
22081
- /* 134 */ "Pagecount",
22082
- /* 135 */ "MaxPgcnt",
22083
- /* 136 */ "Trace",
22084
- /* 137 */ "Noop",
22085
- /* 138 */ "Explain",
22086
- /* 139 */ "NotUsed_139",
22210
+ /* 131 */ "VColumn",
22211
+ /* 132 */ "VNext",
22212
+ /* 133 */ "VRename",
22213
+ /* 134 */ "VUpdate",
22214
+ /* 135 */ "Pagecount",
22215
+ /* 136 */ "MaxPgcnt",
22216
+ /* 137 */ "Trace",
22217
+ /* 138 */ "Noop",
22218
+ /* 139 */ "Explain",
2208722219
/* 140 */ "NotUsed_140",
2208822220
/* 141 */ "ToText",
2208922221
/* 142 */ "ToBlob",
2209022222
/* 143 */ "ToNumeric",
2209122223
/* 144 */ "ToInt",
@@ -22183,14 +22315,17 @@
2218322315
#ifdef MEMORY_DEBUG
2218422316
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
2218522317
#endif
2218622318
2218722319
#ifdef SQLITE_DEBUG
22188
-SQLITE_PRIVATE int sqlite3OSTrace = 0;
22189
-#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
22320
+# ifndef SQLITE_DEBUG_OS_TRACE
22321
+# define SQLITE_DEBUG_OS_TRACE 0
22322
+# endif
22323
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
22324
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
2219022325
#else
22191
-#define OSTRACE(X)
22326
+# define OSTRACE(X)
2219222327
#endif
2219322328
2219422329
/*
2219522330
** Macros for performance tracing. Normally turned off. Only works
2219622331
** on i486 hardware.
@@ -24343,10 +24478,11 @@
2434324478
*/
2434424479
#include <sys/types.h>
2434524480
#include <sys/stat.h>
2434624481
#include <fcntl.h>
2434724482
#include <unistd.h>
24483
+/* #include <time.h> */
2434824484
#include <sys/time.h>
2434924485
#include <errno.h>
2435024486
#ifndef SQLITE_OMIT_WAL
2435124487
#include <sys/mman.h>
2435224488
#endif
@@ -24364,10 +24500,14 @@
2436424500
2436524501
#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
2436624502
# include <sys/mount.h>
2436724503
#endif
2436824504
24505
+#ifdef HAVE_UTIME
24506
+# include <utime.h>
24507
+#endif
24508
+
2436924509
/*
2437024510
** Allowed values of unixFile.fsFlags
2437124511
*/
2437224512
#define SQLITE_FSFLAGS_IS_MSDOS 0x1
2437324513
@@ -24374,10 +24514,11 @@
2437424514
/*
2437524515
** If we are to be thread-safe, include the pthreads header and define
2437624516
** the SQLITE_UNIX_THREADS macro.
2437724517
*/
2437824518
#if SQLITE_THREADSAFE
24519
+/* # include <pthread.h> */
2437924520
# define SQLITE_UNIX_THREADS 1
2438024521
#endif
2438124522
2438224523
/*
2438324524
** Default permissions when creating a new file
@@ -24429,11 +24570,10 @@
2442924570
typedef struct unixFile unixFile;
2443024571
struct unixFile {
2443124572
sqlite3_io_methods const *pMethod; /* Always the first entry */
2443224573
unixInodeInfo *pInode; /* Info about locks on this inode */
2443324574
int h; /* The file descriptor */
24434
- int dirfd; /* File descriptor for the directory */
2443524575
unsigned char eFileLock; /* The type of lock held on this fd */
2443624576
unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
2443724577
int lastErrno; /* The unix errno from last I/O error */
2443824578
void *lockingContext; /* Locking style specific state */
2443924579
UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
@@ -24471,12 +24611,18 @@
2447124611
};
2447224612
2447324613
/*
2447424614
** Allowed values for the unixFile.ctrlFlags bitmask:
2447524615
*/
24476
-#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
24477
-#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
24616
+#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
24617
+#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
24618
+#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
24619
+#ifndef SQLITE_DISABLE_DIRSYNC
24620
+# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
24621
+#else
24622
+# define UNIXFILE_DIRSYNC 0x00
24623
+#endif
2447824624
2447924625
/*
2448024626
** Include code that is common to all os_*.c files
2448124627
*/
2448224628
/************** Include os_common.h in the middle of os_unix.c ***************/
@@ -24511,14 +24657,17 @@
2451124657
#ifdef MEMORY_DEBUG
2451224658
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
2451324659
#endif
2451424660
2451524661
#ifdef SQLITE_DEBUG
24516
-SQLITE_PRIVATE int sqlite3OSTrace = 0;
24517
-#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
24662
+# ifndef SQLITE_DEBUG_OS_TRACE
24663
+# define SQLITE_DEBUG_OS_TRACE 0
24664
+# endif
24665
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
24666
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
2451824667
#else
24519
-#define OSTRACE(X)
24668
+# define OSTRACE(X)
2452024669
#endif
2452124670
2452224671
/*
2452324672
** Macros for performance tracing. Normally turned off. Only works
2452424673
** on i486 hardware.
@@ -24723,10 +24872,13 @@
2472324872
*/
2472424873
static int posixOpen(const char *zFile, int flags, int mode){
2472524874
return open(zFile, flags, mode);
2472624875
}
2472724876
24877
+/* Forward reference */
24878
+static int openDirectory(const char*, int*);
24879
+
2472824880
/*
2472924881
** Many system calls are accessed through pointer-to-functions so that
2473024882
** they may be overridden at runtime to facilitate fault injection during
2473124883
** testing and sandboxing. The following array holds the names and pointers
2473224884
** to all overrideable system calls.
@@ -24819,10 +24971,16 @@
2481924971
#else
2482024972
{ "fallocate", (sqlite3_syscall_ptr)0, 0 },
2482124973
#endif
2482224974
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
2482324975
24976
+ { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
24977
+#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
24978
+
24979
+ { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
24980
+#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
24981
+
2482424982
}; /* End of the overrideable system calls */
2482524983
2482624984
/*
2482724985
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
2482824986
** "unix" VFSes. Return SQLITE_OK opon successfully updating the
@@ -25103,11 +25261,13 @@
2510325261
case EINVAL:
2510425262
case ENOTCONN:
2510525263
case ENODEV:
2510625264
case ENXIO:
2510725265
case ENOENT:
25266
+#ifdef ESTALE /* ESTALE is not defined on Interix systems */
2510825267
case ESTALE:
25268
+#endif
2510925269
case ENOSYS:
2511025270
/* these should force the client to close the file and reconnect */
2511125271
2511225272
default:
2511325273
return sqliteIOErr;
@@ -26173,22 +26333,18 @@
2617326333
** even on VxWorks. A mutex will be acquired on VxWorks by the
2617426334
** vxworksReleaseFileId() routine.
2617526335
*/
2617626336
static int closeUnixFile(sqlite3_file *id){
2617726337
unixFile *pFile = (unixFile*)id;
26178
- if( pFile->dirfd>=0 ){
26179
- robust_close(pFile, pFile->dirfd, __LINE__);
26180
- pFile->dirfd=-1;
26181
- }
2618226338
if( pFile->h>=0 ){
2618326339
robust_close(pFile, pFile->h, __LINE__);
2618426340
pFile->h = -1;
2618526341
}
2618626342
#if OS_VXWORKS
2618726343
if( pFile->pId ){
2618826344
if( pFile->isDelete ){
26189
- unlink(pFile->pId->zCanonicalName);
26345
+ osUnlink(pFile->pId->zCanonicalName);
2619026346
}
2619126347
vxworksReleaseFileId(pFile->pId);
2619226348
pFile->pId = 0;
2619326349
}
2619426350
#endif
@@ -26369,12 +26525,14 @@
2636926525
/* If we have any lock, then the lock file already exists. All we have
2637026526
** to do is adjust our internal record of the lock level.
2637126527
*/
2637226528
if( pFile->eFileLock > NO_LOCK ){
2637326529
pFile->eFileLock = eFileLock;
26374
-#if !OS_VXWORKS
2637526530
/* Always update the timestamp on the old file */
26531
+#ifdef HAVE_UTIME
26532
+ utime(zLockFile, NULL);
26533
+#else
2637626534
utimes(zLockFile, NULL);
2637726535
#endif
2637826536
return SQLITE_OK;
2637926537
}
2638026538
@@ -26431,11 +26589,11 @@
2643126589
return SQLITE_OK;
2643226590
}
2643326591
2643426592
/* To fully unlock the database, delete the lock file */
2643526593
assert( eFileLock==NO_LOCK );
26436
- if( unlink(zLockFile) ){
26594
+ if( osUnlink(zLockFile) ){
2643726595
int rc = 0;
2643826596
int tErrno = errno;
2643926597
if( ENOENT != tErrno ){
2644026598
rc = SQLITE_IOERR_UNLOCK;
2644126599
}
@@ -26937,15 +27095,16 @@
2693727095
*/
2693827096
static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
2693927097
int rc = SQLITE_OK;
2694027098
int reserved = 0;
2694127099
unixFile *pFile = (unixFile*)id;
27100
+ afpLockingContext *context;
2694227101
2694327102
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
2694427103
2694527104
assert( pFile );
26946
- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
27105
+ context = (afpLockingContext *) pFile->lockingContext;
2694727106
if( context->reserved ){
2694827107
*pResOut = 1;
2694927108
return SQLITE_OK;
2695027109
}
2695127110
unixEnterMutex(); /* Because pFile->pInode is shared across threads */
@@ -27081,11 +27240,11 @@
2708127240
2708227241
/* If control gets to this point, then actually go ahead and make
2708327242
** operating system calls for the specified lock.
2708427243
*/
2708527244
if( eFileLock==SHARED_LOCK ){
27086
- int lrc1, lrc2, lrc1Errno;
27245
+ int lrc1, lrc2, lrc1Errno = 0;
2708727246
long lk, mask;
2708827247
2708927248
assert( pInode->nShared==0 );
2709027249
assert( pInode->eFileLock==0 );
2709127250
@@ -27455,21 +27614,23 @@
2745527614
#if defined(USE_PREAD)
2745627615
do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
2745727616
#elif defined(USE_PREAD64)
2745827617
do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
2745927618
#else
27460
- newOffset = lseek(id->h, offset, SEEK_SET);
27461
- SimulateIOError( newOffset-- );
27462
- if( newOffset!=offset ){
27463
- if( newOffset == -1 ){
27464
- ((unixFile*)id)->lastErrno = errno;
27465
- }else{
27466
- ((unixFile*)id)->lastErrno = 0;
27467
- }
27468
- return -1;
27469
- }
27470
- do{ got = osWrite(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
27619
+ do{
27620
+ newOffset = lseek(id->h, offset, SEEK_SET);
27621
+ SimulateIOError( newOffset-- );
27622
+ if( newOffset!=offset ){
27623
+ if( newOffset == -1 ){
27624
+ ((unixFile*)id)->lastErrno = errno;
27625
+ }else{
27626
+ ((unixFile*)id)->lastErrno = 0;
27627
+ }
27628
+ return -1;
27629
+ }
27630
+ got = osWrite(id->h, pBuf, cnt);
27631
+ }while( got<0 && errno==EINTR );
2747127632
#endif
2747227633
TIMER_END;
2747327634
if( got<0 ){
2747427635
((unixFile*)id)->lastErrno = errno;
2747527636
}
@@ -27666,10 +27827,54 @@
2766627827
if( OS_VXWORKS && rc!= -1 ){
2766727828
rc = 0;
2766827829
}
2766927830
return rc;
2767027831
}
27832
+
27833
+/*
27834
+** Open a file descriptor to the directory containing file zFilename.
27835
+** If successful, *pFd is set to the opened file descriptor and
27836
+** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
27837
+** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
27838
+** value.
27839
+**
27840
+** The directory file descriptor is used for only one thing - to
27841
+** fsync() a directory to make sure file creation and deletion events
27842
+** are flushed to disk. Such fsyncs are not needed on newer
27843
+** journaling filesystems, but are required on older filesystems.
27844
+**
27845
+** This routine can be overridden using the xSetSysCall interface.
27846
+** The ability to override this routine was added in support of the
27847
+** chromium sandbox. Opening a directory is a security risk (we are
27848
+** told) so making it overrideable allows the chromium sandbox to
27849
+** replace this routine with a harmless no-op. To make this routine
27850
+** a no-op, replace it with a stub that returns SQLITE_OK but leaves
27851
+** *pFd set to a negative number.
27852
+**
27853
+** If SQLITE_OK is returned, the caller is responsible for closing
27854
+** the file descriptor *pFd using close().
27855
+*/
27856
+static int openDirectory(const char *zFilename, int *pFd){
27857
+ int ii;
27858
+ int fd = -1;
27859
+ char zDirname[MAX_PATHNAME+1];
27860
+
27861
+ sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
27862
+ for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
27863
+ if( ii>0 ){
27864
+ zDirname[ii] = '\0';
27865
+ fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
27866
+ if( fd>=0 ){
27867
+#ifdef FD_CLOEXEC
27868
+ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
27869
+#endif
27870
+ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
27871
+ }
27872
+ }
27873
+ *pFd = fd;
27874
+ return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
27875
+}
2767127876
2767227877
/*
2767327878
** Make sure all writes to a particular file are committed to disk.
2767427879
**
2767527880
** If dataOnly==0 then both the file itself and its metadata (file
@@ -27707,32 +27912,27 @@
2770727912
SimulateIOError( rc=1 );
2770827913
if( rc ){
2770927914
pFile->lastErrno = errno;
2771027915
return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
2771127916
}
27712
- if( pFile->dirfd>=0 ){
27713
- OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
27917
+
27918
+ /* Also fsync the directory containing the file if the DIRSYNC flag
27919
+ ** is set. This is a one-time occurrance. Many systems (examples: AIX)
27920
+ ** are unable to fsync a directory, so ignore errors on the fsync.
27921
+ */
27922
+ if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
27923
+ int dirfd;
27924
+ OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
2771427925
HAVE_FULLFSYNC, isFullsync));
27715
-#ifndef SQLITE_DISABLE_DIRSYNC
27716
- /* The directory sync is only attempted if full_fsync is
27717
- ** turned off or unavailable. If a full_fsync occurred above,
27718
- ** then the directory sync is superfluous.
27719
- */
27720
- if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
27721
- /*
27722
- ** We have received multiple reports of fsync() returning
27723
- ** errors when applied to directories on certain file systems.
27724
- ** A failed directory sync is not a big deal. So it seems
27725
- ** better to ignore the error. Ticket #1657
27726
- */
27727
- /* pFile->lastErrno = errno; */
27728
- /* return SQLITE_IOERR; */
27729
- }
27730
-#endif
27731
- /* Only need to sync once, so close the directory when we are done */
27732
- robust_close(pFile, pFile->dirfd, __LINE__);
27733
- pFile->dirfd = -1;
27926
+ rc = osOpenDirectory(pFile->zPath, &dirfd);
27927
+ if( rc==SQLITE_OK && dirfd>=0 ){
27928
+ full_fsync(dirfd, 0, 0);
27929
+ robust_close(pFile, dirfd, __LINE__);
27930
+ }else if( rc==SQLITE_CANTOPEN ){
27931
+ rc = SQLITE_OK;
27932
+ }
27933
+ pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
2773427934
}
2773527935
return rc;
2773627936
}
2773727937
2773827938
/*
@@ -27810,15 +28010,13 @@
2781028010
static int proxyFileControl(sqlite3_file*,int,void*);
2781128011
#endif
2781228012
2781328013
/*
2781428014
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
27815
-** file-control operation.
27816
-**
27817
-** If the user has configured a chunk-size for this file, it could be
27818
-** that the file needs to be extended at this point. Otherwise, the
27819
-** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
28015
+** file-control operation. Enlarge the database to nBytes in size
28016
+** (rounded up to the next chunk-size). If the database is already
28017
+** nBytes or larger, this routine is a no-op.
2782028018
*/
2782128019
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
2782228020
if( pFile->szChunk ){
2782328021
i64 nSize; /* Required file size */
2782428022
struct stat buf; /* Used to hold return values of fstat() */
@@ -27866,25 +28064,41 @@
2786628064
2786728065
/*
2786828066
** Information and control of an open file handle.
2786928067
*/
2787028068
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
28069
+ unixFile *pFile = (unixFile*)id;
2787128070
switch( op ){
2787228071
case SQLITE_FCNTL_LOCKSTATE: {
27873
- *(int*)pArg = ((unixFile*)id)->eFileLock;
28072
+ *(int*)pArg = pFile->eFileLock;
2787428073
return SQLITE_OK;
2787528074
}
2787628075
case SQLITE_LAST_ERRNO: {
27877
- *(int*)pArg = ((unixFile*)id)->lastErrno;
28076
+ *(int*)pArg = pFile->lastErrno;
2787828077
return SQLITE_OK;
2787928078
}
2788028079
case SQLITE_FCNTL_CHUNK_SIZE: {
27881
- ((unixFile*)id)->szChunk = *(int *)pArg;
28080
+ pFile->szChunk = *(int *)pArg;
2788228081
return SQLITE_OK;
2788328082
}
2788428083
case SQLITE_FCNTL_SIZE_HINT: {
27885
- return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
28084
+ int rc;
28085
+ SimulateIOErrorBenign(1);
28086
+ rc = fcntlSizeHint(pFile, *(i64 *)pArg);
28087
+ SimulateIOErrorBenign(0);
28088
+ return rc;
28089
+ }
28090
+ case SQLITE_FCNTL_PERSIST_WAL: {
28091
+ int bPersist = *(int*)pArg;
28092
+ if( bPersist<0 ){
28093
+ *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
28094
+ }else if( bPersist==0 ){
28095
+ pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
28096
+ }else{
28097
+ pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
28098
+ }
28099
+ return SQLITE_OK;
2788628100
}
2788728101
#ifndef NDEBUG
2788828102
/* The pager calls this method to signal that it has done
2788928103
** a rollback and that the database is therefore unchanged and
2789028104
** it hence it is OK for the transaction change counter to be
@@ -28096,11 +28310,11 @@
2809628310
unixShmNode *p = pFd->pInode->pShmNode;
2809728311
assert( unixMutexHeld() );
2809828312
if( p && p->nRef==0 ){
2809928313
int i;
2810028314
assert( p->pInode==pFd->pInode );
28101
- if( p->mutex ) sqlite3_mutex_free(p->mutex);
28315
+ sqlite3_mutex_free(p->mutex);
2810228316
for(i=0; i<p->nRegion; i++){
2810328317
if( p->h>=0 ){
2810428318
munmap(p->apRegion[i], p->szRegion);
2810528319
}else{
2810628320
sqlite3_free(p->apRegion[i]);
@@ -28565,11 +28779,11 @@
2856528779
** shared-memory file, too */
2856628780
unixEnterMutex();
2856728781
assert( pShmNode->nRef>0 );
2856828782
pShmNode->nRef--;
2856928783
if( pShmNode->nRef==0 ){
28570
- if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename);
28784
+ if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
2857128785
unixShmPurge(pDbFd);
2857228786
}
2857328787
unixLeaveMutex();
2857428788
2857528789
return SQLITE_OK;
@@ -28878,11 +29092,11 @@
2887829092
** Initialize the contents of the unixFile structure pointed to by pId.
2887929093
*/
2888029094
static int fillInUnixFile(
2888129095
sqlite3_vfs *pVfs, /* Pointer to vfs object */
2888229096
int h, /* Open file descriptor of file being opened */
28883
- int dirfd, /* Directory file descriptor */
29097
+ int syncDir, /* True to sync directory on first sync */
2888429098
sqlite3_file *pId, /* Write to the unixFile structure here */
2888529099
const char *zFilename, /* Name of the file being opened */
2888629100
int noLock, /* Omit locking if true */
2888729101
int isDelete, /* Delete on close if true */
2888829102
int isReadOnly /* True if the file is opened read-only */
@@ -28909,20 +29123,22 @@
2890929123
assert( zFilename==0 || zFilename[0]=='/' );
2891029124
#endif
2891129125
2891229126
OSTRACE(("OPEN %-3d %s\n", h, zFilename));
2891329127
pNew->h = h;
28914
- pNew->dirfd = dirfd;
2891529128
pNew->zPath = zFilename;
2891629129
if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
2891729130
pNew->ctrlFlags = UNIXFILE_EXCL;
2891829131
}else{
2891929132
pNew->ctrlFlags = 0;
2892029133
}
2892129134
if( isReadOnly ){
2892229135
pNew->ctrlFlags |= UNIXFILE_RDONLY;
2892329136
}
29137
+ if( syncDir ){
29138
+ pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
29139
+ }
2892429140
2892529141
#if OS_VXWORKS
2892629142
pNew->pId = vxworksFindFileId(zFilename);
2892729143
if( pNew->pId==0 ){
2892829144
noLock = 1;
@@ -29045,56 +29261,24 @@
2904529261
pNew->lastErrno = 0;
2904629262
#if OS_VXWORKS
2904729263
if( rc!=SQLITE_OK ){
2904829264
if( h>=0 ) robust_close(pNew, h, __LINE__);
2904929265
h = -1;
29050
- unlink(zFilename);
29266
+ osUnlink(zFilename);
2905129267
isDelete = 0;
2905229268
}
2905329269
pNew->isDelete = isDelete;
2905429270
#endif
2905529271
if( rc!=SQLITE_OK ){
29056
- if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__);
2905729272
if( h>=0 ) robust_close(pNew, h, __LINE__);
2905829273
}else{
2905929274
pNew->pMethod = pLockingStyle;
2906029275
OpenCounter(+1);
2906129276
}
2906229277
return rc;
2906329278
}
2906429279
29065
-/*
29066
-** Open a file descriptor to the directory containing file zFilename.
29067
-** If successful, *pFd is set to the opened file descriptor and
29068
-** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
29069
-** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
29070
-** value.
29071
-**
29072
-** If SQLITE_OK is returned, the caller is responsible for closing
29073
-** the file descriptor *pFd using close().
29074
-*/
29075
-static int openDirectory(const char *zFilename, int *pFd){
29076
- int ii;
29077
- int fd = -1;
29078
- char zDirname[MAX_PATHNAME+1];
29079
-
29080
- sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
29081
- for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
29082
- if( ii>0 ){
29083
- zDirname[ii] = '\0';
29084
- fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
29085
- if( fd>=0 ){
29086
-#ifdef FD_CLOEXEC
29087
- osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
29088
-#endif
29089
- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
29090
- }
29091
- }
29092
- *pFd = fd;
29093
- return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
29094
-}
29095
-
2909629280
/*
2909729281
** Return the name of a directory in which to put temporary files.
2909829282
** If no suitable temporary file directory can be found, return NULL.
2909929283
*/
2910029284
static const char *unixTempFileDir(void){
@@ -29205,11 +29389,11 @@
2920529389
** ignored and -1 is returned. The caller will try to open a new file
2920629390
** descriptor on the same path, fail, and return an error to SQLite.
2920729391
**
2920829392
** Even if a subsequent open() call does succeed, the consequences of
2920929393
** not searching for a resusable file descriptor are not dire. */
29210
- if( 0==stat(zPath, &sStat) ){
29394
+ if( 0==osStat(zPath, &sStat) ){
2921129395
unixInodeInfo *pInode;
2921229396
2921329397
unixEnterMutex();
2921429398
pInode = inodeList;
2921529399
while( pInode && (pInode->fileId.dev!=sStat.st_dev
@@ -29281,11 +29465,11 @@
2928129465
while( nDb>0 && zPath[nDb]!='-' ) nDb--;
2928229466
if( nDb==0 ) return SQLITE_OK;
2928329467
memcpy(zDb, zPath, nDb);
2928429468
zDb[nDb] = '\0';
2928529469
29286
- if( 0==stat(zDb, &sStat) ){
29470
+ if( 0==osStat(zDb, &sStat) ){
2928729471
*pMode = sStat.st_mode & 0777;
2928829472
}else{
2928929473
rc = SQLITE_IOERR_FSTAT;
2929029474
}
2929129475
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
@@ -29323,11 +29507,10 @@
2932329507
int flags, /* Input flags to control the opening */
2932429508
int *pOutFlags /* Output flags returned to SQLite core */
2932529509
){
2932629510
unixFile *p = (unixFile *)pFile;
2932729511
int fd = -1; /* File descriptor returned by open() */
29328
- int dirfd = -1; /* Directory file descriptor */
2932929512
int openFlags = 0; /* Flags to pass to open() */
2933029513
int eType = flags&0xFFFFFF00; /* Type of file to open */
2933129514
int noLock; /* True to omit locking primitives */
2933229515
int rc = SQLITE_OK; /* Function Return Code */
2933329516
@@ -29337,16 +29520,19 @@
2933729520
int isReadonly = (flags & SQLITE_OPEN_READONLY);
2933829521
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
2933929522
#if SQLITE_ENABLE_LOCKING_STYLE
2934029523
int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
2934129524
#endif
29525
+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
29526
+ struct statfs fsInfo;
29527
+#endif
2934229528
2934329529
/* If creating a master or main-file journal, this function will open
2934429530
** a file-descriptor on the directory too. The first time unixSync()
2934529531
** is called the directory file descriptor will be fsync()ed and close()d.
2934629532
*/
29347
- int isOpenDirectory = (isCreate && (
29533
+ int syncDir = (isCreate && (
2934829534
eType==SQLITE_OPEN_MASTER_JOURNAL
2934929535
|| eType==SQLITE_OPEN_MAIN_JOURNAL
2935029536
|| eType==SQLITE_OPEN_WAL
2935129537
));
2935229538
@@ -29396,11 +29582,11 @@
2939629582
}
2939729583
}
2939829584
p->pUnused = pUnused;
2939929585
}else if( !zName ){
2940029586
/* If zName is NULL, the upper layer is requesting a temp file. */
29401
- assert(isDelete && !isOpenDirectory);
29587
+ assert(isDelete && !syncDir);
2940229588
rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
2940329589
if( rc!=SQLITE_OK ){
2940429590
return rc;
2940529591
}
2940629592
zName = zTmpname;
@@ -29452,44 +29638,29 @@
2945229638
2945329639
if( isDelete ){
2945429640
#if OS_VXWORKS
2945529641
zPath = zName;
2945629642
#else
29457
- unlink(zName);
29643
+ osUnlink(zName);
2945829644
#endif
2945929645
}
2946029646
#if SQLITE_ENABLE_LOCKING_STYLE
2946129647
else{
2946229648
p->openFlags = openFlags;
2946329649
}
2946429650
#endif
2946529651
29466
- if( isOpenDirectory ){
29467
- rc = openDirectory(zPath, &dirfd);
29468
- if( rc!=SQLITE_OK ){
29469
- /* It is safe to close fd at this point, because it is guaranteed not
29470
- ** to be open on a database file. If it were open on a database file,
29471
- ** it would not be safe to close as this would release any locks held
29472
- ** on the file by this process. */
29473
- assert( eType!=SQLITE_OPEN_MAIN_DB );
29474
- robust_close(p, fd, __LINE__);
29475
- goto open_finished;
29476
- }
29477
- }
29478
-
2947929652
#ifdef FD_CLOEXEC
2948029653
osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
2948129654
#endif
2948229655
2948329656
noLock = eType!=SQLITE_OPEN_MAIN_DB;
2948429657
2948529658
2948629659
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
29487
- struct statfs fsInfo;
2948829660
if( fstatfs(fd, &fsInfo) == -1 ){
2948929661
((unixFile*)pFile)->lastErrno = errno;
29490
- if( dirfd>=0 ) robust_close(p, dirfd, __LINE__);
2949129662
robust_close(p, fd, __LINE__);
2949229663
return SQLITE_IOERR_ACCESS;
2949329664
}
2949429665
if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
2949529666
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
@@ -29507,31 +29678,27 @@
2950729678
/* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
2950829679
** never use proxy, NULL means use proxy for non-local files only. */
2950929680
if( envforce!=NULL ){
2951029681
useProxy = atoi(envforce)>0;
2951129682
}else{
29512
- struct statfs fsInfo;
2951329683
if( statfs(zPath, &fsInfo) == -1 ){
2951429684
/* In theory, the close(fd) call is sub-optimal. If the file opened
2951529685
** with fd is a database file, and there are other connections open
2951629686
** on that file that are currently holding advisory locks on it,
2951729687
** then the call to close() will cancel those locks. In practice,
2951829688
** we're assuming that statfs() doesn't fail very often. At least
2951929689
** not while other file descriptors opened by the same process on
2952029690
** the same file are working. */
2952129691
p->lastErrno = errno;
29522
- if( dirfd>=0 ){
29523
- robust_close(p, dirfd, __LINE__);
29524
- }
2952529692
robust_close(p, fd, __LINE__);
2952629693
rc = SQLITE_IOERR_ACCESS;
2952729694
goto open_finished;
2952829695
}
2952929696
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
2953029697
}
2953129698
if( useProxy ){
29532
- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
29699
+ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
2953329700
isDelete, isReadonly);
2953429701
if( rc==SQLITE_OK ){
2953529702
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
2953629703
if( rc!=SQLITE_OK ){
2953729704
/* Use unixClose to clean up the resources added in fillInUnixFile
@@ -29545,11 +29712,11 @@
2954529712
goto open_finished;
2954629713
}
2954729714
}
2954829715
#endif
2954929716
29550
- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
29717
+ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
2955129718
isDelete, isReadonly);
2955229719
open_finished:
2955329720
if( rc!=SQLITE_OK ){
2955429721
sqlite3_free(p->pUnused);
2955529722
}
@@ -29567,17 +29734,17 @@
2956729734
int dirSync /* If true, fsync() directory after deleting file */
2956829735
){
2956929736
int rc = SQLITE_OK;
2957029737
UNUSED_PARAMETER(NotUsed);
2957129738
SimulateIOError(return SQLITE_IOERR_DELETE);
29572
- if( unlink(zPath)==(-1) && errno!=ENOENT ){
29739
+ if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
2957329740
return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
2957429741
}
2957529742
#ifndef SQLITE_DISABLE_DIRSYNC
2957629743
if( dirSync ){
2957729744
int fd;
29578
- rc = openDirectory(zPath, &fd);
29745
+ rc = osOpenDirectory(zPath, &fd);
2957929746
if( rc==SQLITE_OK ){
2958029747
#if OS_VXWORKS
2958129748
if( fsync(fd)==-1 )
2958229749
#else
2958329750
if( fsync(fd) )
@@ -29584,10 +29751,12 @@
2958429751
#endif
2958529752
{
2958629753
rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
2958729754
}
2958829755
robust_close(0, fd, __LINE__);
29756
+ }else if( rc==SQLITE_CANTOPEN ){
29757
+ rc = SQLITE_OK;
2958929758
}
2959029759
}
2959129760
#endif
2959229761
return rc;
2959329762
}
@@ -29626,11 +29795,11 @@
2962629795
assert(!"Invalid flags argument");
2962729796
}
2962829797
*pResOut = (osAccess(zPath, amode)==0);
2962929798
if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
2963029799
struct stat buf;
29631
- if( 0==stat(zPath, &buf) && buf.st_size==0 ){
29800
+ if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
2963229801
*pResOut = 0;
2963329802
}
2963429803
}
2963529804
return SQLITE_OK;
2963629805
}
@@ -30145,11 +30314,10 @@
3014530314
const char *path, /* path for the new unixFile */
3014630315
unixFile **ppFile, /* unixFile created and returned by ref */
3014730316
int islockfile /* if non zero missing dirs will be created */
3014830317
) {
3014930318
int fd = -1;
30150
- int dirfd = -1;
3015130319
unixFile *pNew;
3015230320
int rc = SQLITE_OK;
3015330321
int openFlags = O_RDWR | O_CREAT;
3015430322
sqlite3_vfs dummyVfs;
3015530323
int terrno = 0;
@@ -30210,11 +30378,11 @@
3021030378
dummyVfs.zName = "dummy";
3021130379
pUnused->fd = fd;
3021230380
pUnused->flags = openFlags;
3021330381
pNew->pUnused = pUnused;
3021430382
30215
- rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0);
30383
+ rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
3021630384
if( rc==SQLITE_OK ){
3021730385
*ppFile = pNew;
3021830386
return SQLITE_OK;
3021930387
}
3022030388
end_create_proxy:
@@ -30250,10 +30418,12 @@
3025030418
*pError = err;
3025130419
}
3025230420
return SQLITE_IOERR;
3025330421
}
3025430422
}
30423
+#else
30424
+ UNUSED_PARAMETER(pError);
3025530425
#endif
3025630426
#ifdef SQLITE_TEST
3025730427
/* simulate multiple hosts by creating unique hostid file paths */
3025830428
if( sqlite3_hostid_num != 0){
3025930429
pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
@@ -30324,11 +30494,11 @@
3032430494
conchFile->openFlags = O_RDWR | O_CREAT;
3032530495
3032630496
end_breaklock:
3032730497
if( rc ){
3032830498
if( fd>=0 ){
30329
- unlink(tPath);
30499
+ osUnlink(tPath);
3033030500
robust_close(pFile, fd, __LINE__);
3033130501
}
3033230502
fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
3033330503
}
3033430504
return rc;
@@ -30342,10 +30512,11 @@
3034230512
unixFile *conchFile = pCtx->conchFile;
3034330513
int rc = SQLITE_OK;
3034430514
int nTries = 0;
3034530515
struct timespec conchModTime;
3034630516
30517
+ memset(&conchModTime, 0, sizeof(conchModTime));
3034730518
do {
3034830519
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
3034930520
nTries ++;
3035030521
if( rc==SQLITE_BUSY ){
3035130522
/* If the lock failed (busy):
@@ -30573,15 +30744,16 @@
3057330744
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
3057430745
3057530746
end_takeconch:
3057630747
OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
3057730748
if( rc==SQLITE_OK && pFile->openFlags ){
30749
+ int fd;
3057830750
if( pFile->h>=0 ){
3057930751
robust_close(pFile, pFile->h, __LINE__);
3058030752
}
3058130753
pFile->h = -1;
30582
- int fd = robust_open(pCtx->dbPath, pFile->openFlags,
30754
+ fd = robust_open(pCtx->dbPath, pFile->openFlags,
3058330755
SQLITE_DEFAULT_FILE_PERMISSIONS);
3058430756
OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
3058530757
if( fd>=0 ){
3058630758
pFile->h = fd;
3058730759
}else{
@@ -31147,11 +31319,11 @@
3114731319
};
3114831320
unsigned int i; /* Loop counter */
3114931321
3115031322
/* Double-check that the aSyscall[] array has been constructed
3115131323
** correctly. See ticket [bb3a86e890c8e96ab] */
31152
- assert( ArraySize(aSyscall)==16 );
31324
+ assert( ArraySize(aSyscall)==18 );
3115331325
3115431326
/* Register all VFSes defined in the aVfs[] array */
3115531327
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
3115631328
sqlite3_vfs_register(&aVfs[i], i==0);
3115731329
}
@@ -31264,14 +31436,17 @@
3126431436
#ifdef MEMORY_DEBUG
3126531437
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
3126631438
#endif
3126731439
3126831440
#ifdef SQLITE_DEBUG
31269
-SQLITE_PRIVATE int sqlite3OSTrace = 0;
31270
-#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
31441
+# ifndef SQLITE_DEBUG_OS_TRACE
31442
+# define SQLITE_DEBUG_OS_TRACE 0
31443
+# endif
31444
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
31445
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
3127131446
#else
31272
-#define OSTRACE(X)
31447
+# define OSTRACE(X)
3127331448
#endif
3127431449
3127531450
/*
3127631451
** Macros for performance tracing. Normally turned off. Only works
3127731452
** on i486 hardware.
@@ -31479,12 +31654,13 @@
3147931654
typedef struct winFile winFile;
3148031655
struct winFile {
3148131656
const sqlite3_io_methods *pMethod; /*** Must be first ***/
3148231657
sqlite3_vfs *pVfs; /* The VFS used to open this file */
3148331658
HANDLE h; /* Handle for accessing the file */
31484
- unsigned char locktype; /* Type of lock currently held on this file */
31659
+ u8 locktype; /* Type of lock currently held on this file */
3148531660
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
31661
+ u8 bPersistWal; /* True to persist WAL files */
3148631662
DWORD lastErrno; /* The Windows errno from the last I/O error */
3148731663
DWORD sectorSize; /* Sector size of the device file is on */
3148831664
winShm *pShm; /* Instance of shared memory on this file */
3148931665
const char *zPath; /* Full pathname of this file */
3149031666
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
@@ -31495,10 +31671,80 @@
3149531671
winceLock local; /* Locks obtained by this instance of winFile */
3149631672
winceLock *shared; /* Global shared lock memory for the file */
3149731673
#endif
3149831674
};
3149931675
31676
+/*
31677
+ * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
31678
+ * various Win32 API heap functions instead of our own.
31679
+ */
31680
+#ifdef SQLITE_WIN32_MALLOC
31681
+/*
31682
+ * The initial size of the Win32-specific heap. This value may be zero.
31683
+ */
31684
+#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
31685
+# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
31686
+ (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
31687
+#endif
31688
+
31689
+/*
31690
+ * The maximum size of the Win32-specific heap. This value may be zero.
31691
+ */
31692
+#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
31693
+# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
31694
+#endif
31695
+
31696
+/*
31697
+ * The extra flags to use in calls to the Win32 heap APIs. This value may be
31698
+ * zero for the default behavior.
31699
+ */
31700
+#ifndef SQLITE_WIN32_HEAP_FLAGS
31701
+# define SQLITE_WIN32_HEAP_FLAGS (0)
31702
+#endif
31703
+
31704
+/*
31705
+** The winMemData structure stores information required by the Win32-specific
31706
+** sqlite3_mem_methods implementation.
31707
+*/
31708
+typedef struct winMemData winMemData;
31709
+struct winMemData {
31710
+#ifndef NDEBUG
31711
+ u32 magic; /* Magic number to detect structure corruption. */
31712
+#endif
31713
+ HANDLE hHeap; /* The handle to our heap. */
31714
+ BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
31715
+};
31716
+
31717
+#ifndef NDEBUG
31718
+#define WINMEM_MAGIC 0x42b2830b
31719
+#endif
31720
+
31721
+static struct winMemData win_mem_data = {
31722
+#ifndef NDEBUG
31723
+ WINMEM_MAGIC,
31724
+#endif
31725
+ NULL, FALSE
31726
+};
31727
+
31728
+#ifndef NDEBUG
31729
+#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
31730
+#else
31731
+#define winMemAssertMagic()
31732
+#endif
31733
+
31734
+#define winMemGetHeap() win_mem_data.hHeap
31735
+
31736
+static void *winMemMalloc(int nBytes);
31737
+static void winMemFree(void *pPrior);
31738
+static void *winMemRealloc(void *pPrior, int nBytes);
31739
+static int winMemSize(void *p);
31740
+static int winMemRoundup(int n);
31741
+static int winMemInit(void *pAppData);
31742
+static void winMemShutdown(void *pAppData);
31743
+
31744
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
31745
+#endif /* SQLITE_WIN32_MALLOC */
3150031746
3150131747
/*
3150231748
** Forward prototypes.
3150331749
*/
3150431750
static int getSectorSize(
@@ -31547,10 +31793,192 @@
3154731793
}
3154831794
return sqlite3_os_type==2;
3154931795
}
3155031796
#endif /* SQLITE_OS_WINCE */
3155131797
31798
+#ifdef SQLITE_WIN32_MALLOC
31799
+/*
31800
+** Allocate nBytes of memory.
31801
+*/
31802
+static void *winMemMalloc(int nBytes){
31803
+ HANDLE hHeap;
31804
+ void *p;
31805
+
31806
+ winMemAssertMagic();
31807
+ hHeap = winMemGetHeap();
31808
+ assert( hHeap!=0 );
31809
+ assert( hHeap!=INVALID_HANDLE_VALUE );
31810
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
31811
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31812
+#endif
31813
+ assert( nBytes>=0 );
31814
+ p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
31815
+ if( !p ){
31816
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
31817
+ nBytes, GetLastError(), (void*)hHeap);
31818
+ }
31819
+ return p;
31820
+}
31821
+
31822
+/*
31823
+** Free memory.
31824
+*/
31825
+static void winMemFree(void *pPrior){
31826
+ HANDLE hHeap;
31827
+
31828
+ winMemAssertMagic();
31829
+ hHeap = winMemGetHeap();
31830
+ assert( hHeap!=0 );
31831
+ assert( hHeap!=INVALID_HANDLE_VALUE );
31832
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
31833
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
31834
+#endif
31835
+ if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
31836
+ if( !HeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
31837
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
31838
+ pPrior, GetLastError(), (void*)hHeap);
31839
+ }
31840
+}
31841
+
31842
+/*
31843
+** Change the size of an existing memory allocation
31844
+*/
31845
+static void *winMemRealloc(void *pPrior, int nBytes){
31846
+ HANDLE hHeap;
31847
+ void *p;
31848
+
31849
+ winMemAssertMagic();
31850
+ hHeap = winMemGetHeap();
31851
+ assert( hHeap!=0 );
31852
+ assert( hHeap!=INVALID_HANDLE_VALUE );
31853
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
31854
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
31855
+#endif
31856
+ assert( nBytes>=0 );
31857
+ if( !pPrior ){
31858
+ p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
31859
+ }else{
31860
+ p = HeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
31861
+ }
31862
+ if( !p ){
31863
+ sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
31864
+ pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(),
31865
+ (void*)hHeap);
31866
+ }
31867
+ return p;
31868
+}
31869
+
31870
+/*
31871
+** Return the size of an outstanding allocation, in bytes.
31872
+*/
31873
+static int winMemSize(void *p){
31874
+ HANDLE hHeap;
31875
+ SIZE_T n;
31876
+
31877
+ winMemAssertMagic();
31878
+ hHeap = winMemGetHeap();
31879
+ assert( hHeap!=0 );
31880
+ assert( hHeap!=INVALID_HANDLE_VALUE );
31881
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
31882
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31883
+#endif
31884
+ if( !p ) return 0;
31885
+ n = HeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
31886
+ if( n==(SIZE_T)-1 ){
31887
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
31888
+ p, GetLastError(), (void*)hHeap);
31889
+ return 0;
31890
+ }
31891
+ return (int)n;
31892
+}
31893
+
31894
+/*
31895
+** Round up a request size to the next valid allocation size.
31896
+*/
31897
+static int winMemRoundup(int n){
31898
+ return n;
31899
+}
31900
+
31901
+/*
31902
+** Initialize this module.
31903
+*/
31904
+static int winMemInit(void *pAppData){
31905
+ winMemData *pWinMemData = (winMemData *)pAppData;
31906
+
31907
+ if( !pWinMemData ) return SQLITE_ERROR;
31908
+ assert( pWinMemData->magic==WINMEM_MAGIC );
31909
+ if( !pWinMemData->hHeap ){
31910
+ pWinMemData->hHeap = HeapCreate(SQLITE_WIN32_HEAP_FLAGS,
31911
+ SQLITE_WIN32_HEAP_INIT_SIZE,
31912
+ SQLITE_WIN32_HEAP_MAX_SIZE);
31913
+ if( !pWinMemData->hHeap ){
31914
+ sqlite3_log(SQLITE_NOMEM,
31915
+ "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
31916
+ GetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE,
31917
+ SQLITE_WIN32_HEAP_MAX_SIZE);
31918
+ return SQLITE_NOMEM;
31919
+ }
31920
+ pWinMemData->bOwned = TRUE;
31921
+ }
31922
+ assert( pWinMemData->hHeap!=0 );
31923
+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
31924
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
31925
+ assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31926
+#endif
31927
+ return SQLITE_OK;
31928
+}
31929
+
31930
+/*
31931
+** Deinitialize this module.
31932
+*/
31933
+static void winMemShutdown(void *pAppData){
31934
+ winMemData *pWinMemData = (winMemData *)pAppData;
31935
+
31936
+ if( !pWinMemData ) return;
31937
+ if( pWinMemData->hHeap ){
31938
+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
31939
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
31940
+ assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31941
+#endif
31942
+ if( pWinMemData->bOwned ){
31943
+ if( !HeapDestroy(pWinMemData->hHeap) ){
31944
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
31945
+ GetLastError(), (void*)pWinMemData->hHeap);
31946
+ }
31947
+ pWinMemData->bOwned = FALSE;
31948
+ }
31949
+ pWinMemData->hHeap = NULL;
31950
+ }
31951
+}
31952
+
31953
+/*
31954
+** Populate the low-level memory allocation function pointers in
31955
+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
31956
+** arguments specify the block of memory to manage.
31957
+**
31958
+** This routine is only called by sqlite3_config(), and therefore
31959
+** is not required to be threadsafe (it is not).
31960
+*/
31961
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
31962
+ static const sqlite3_mem_methods winMemMethods = {
31963
+ winMemMalloc,
31964
+ winMemFree,
31965
+ winMemRealloc,
31966
+ winMemSize,
31967
+ winMemRoundup,
31968
+ winMemInit,
31969
+ winMemShutdown,
31970
+ &win_mem_data
31971
+ };
31972
+ return &winMemMethods;
31973
+}
31974
+
31975
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
31976
+ sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
31977
+}
31978
+#endif /* SQLITE_WIN32_MALLOC */
31979
+
3155231980
/*
3155331981
** Convert a UTF-8 string to microsoft unicode (UTF-16?).
3155431982
**
3155531983
** Space to hold the returned string is obtained from malloc.
3155631984
*/
@@ -31778,19 +32206,68 @@
3177832206
iLine, iErrno, zFunc, zPath, zMsg
3177932207
);
3178032208
3178132209
return errcode;
3178232210
}
32211
+
32212
+/*
32213
+** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
32214
+** will be retried following a locking error - probably caused by
32215
+** antivirus software. Also the initial delay before the first retry.
32216
+** The delay increases linearly with each retry.
32217
+*/
32218
+#ifndef SQLITE_WIN32_IOERR_RETRY
32219
+# define SQLITE_WIN32_IOERR_RETRY 10
32220
+#endif
32221
+#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
32222
+# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
32223
+#endif
32224
+static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
32225
+static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
32226
+
32227
+/*
32228
+** If a ReadFile() or WriteFile() error occurs, invoke this routine
32229
+** to see if it should be retried. Return TRUE to retry. Return FALSE
32230
+** to give up with an error.
32231
+*/
32232
+static int retryIoerr(int *pnRetry){
32233
+ DWORD e;
32234
+ if( *pnRetry>=win32IoerrRetry ){
32235
+ return 0;
32236
+ }
32237
+ e = GetLastError();
32238
+ if( e==ERROR_ACCESS_DENIED ||
32239
+ e==ERROR_LOCK_VIOLATION ||
32240
+ e==ERROR_SHARING_VIOLATION ){
32241
+ Sleep(win32IoerrRetryDelay*(1+*pnRetry));
32242
+ ++*pnRetry;
32243
+ return 1;
32244
+ }
32245
+ return 0;
32246
+}
32247
+
32248
+/*
32249
+** Log a I/O error retry episode.
32250
+*/
32251
+static void logIoerr(int nRetry){
32252
+ if( nRetry ){
32253
+ sqlite3_log(SQLITE_IOERR,
32254
+ "delayed %dms for lock/sharing conflict",
32255
+ win32IoerrRetryDelay*nRetry*(nRetry+1)/2
32256
+ );
32257
+ }
32258
+}
3178332259
3178432260
#if SQLITE_OS_WINCE
3178532261
/*************************************************************************
3178632262
** This section contains code for WinCE only.
3178732263
*/
3178832264
/*
3178932265
** WindowsCE does not have a localtime() function. So create a
3179032266
** substitute.
3179132267
*/
32268
+/* #include <time.h> */
3179232269
struct tm *__cdecl localtime(const time_t *t)
3179332270
{
3179432271
static struct tm y;
3179532272
FILETIME uTm, lTm;
3179632273
SYSTEMTIME pTm;
@@ -32196,22 +32673,25 @@
3219632673
int amt, /* Number of bytes to read */
3219732674
sqlite3_int64 offset /* Begin reading at this offset */
3219832675
){
3219932676
winFile *pFile = (winFile*)id; /* file handle */
3220032677
DWORD nRead; /* Number of bytes actually read from file */
32678
+ int nRetry = 0; /* Number of retrys */
3220132679
3220232680
assert( id!=0 );
3220332681
SimulateIOError(return SQLITE_IOERR_READ);
3220432682
OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
3220532683
3220632684
if( seekWinFile(pFile, offset) ){
3220732685
return SQLITE_FULL;
3220832686
}
32209
- if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
32687
+ while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
32688
+ if( retryIoerr(&nRetry) ) continue;
3221032689
pFile->lastErrno = GetLastError();
3221132690
return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
3221232691
}
32692
+ logIoerr(nRetry);
3221332693
if( nRead<(DWORD)amt ){
3221432694
/* Unread parts of the buffer must be zero-filled */
3221532695
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
3221632696
return SQLITE_IOERR_SHORT_READ;
3221732697
}
@@ -32229,10 +32709,11 @@
3222932709
int amt, /* Number of bytes to write */
3223032710
sqlite3_int64 offset /* Offset into the file to begin writing at */
3223132711
){
3223232712
int rc; /* True if error has occured, else false */
3223332713
winFile *pFile = (winFile*)id; /* File handle */
32714
+ int nRetry = 0; /* Number of retries */
3223432715
3223532716
assert( amt>0 );
3223632717
assert( pFile );
3223732718
SimulateIOError(return SQLITE_IOERR_WRITE);
3223832719
SimulateDiskfullError(return SQLITE_FULL);
@@ -32243,11 +32724,16 @@
3224332724
if( rc==0 ){
3224432725
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
3224532726
int nRem = amt; /* Number of bytes yet to be written */
3224632727
DWORD nWrite; /* Bytes written by each WriteFile() call */
3224732728
32248
- while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
32729
+ while( nRem>0 ){
32730
+ if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
32731
+ if( retryIoerr(&nRetry) ) continue;
32732
+ break;
32733
+ }
32734
+ if( nWrite<=0 ) break;
3224932735
aRem += nWrite;
3225032736
nRem -= nWrite;
3225132737
}
3225232738
if( nRem>0 ){
3225332739
pFile->lastErrno = GetLastError();
@@ -32254,14 +32740,17 @@
3225432740
rc = 1;
3225532741
}
3225632742
}
3225732743
3225832744
if( rc ){
32259
- if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
32745
+ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
32746
+ || ( pFile->lastErrno==ERROR_DISK_FULL )){
3226032747
return SQLITE_FULL;
3226132748
}
3226232749
return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
32750
+ }else{
32751
+ logIoerr(nRetry);
3226332752
}
3226432753
return SQLITE_OK;
3226532754
}
3226632755
3226732756
/*
@@ -32651,32 +33140,63 @@
3265133140
3265233141
/*
3265333142
** Control and query of the open file handle.
3265433143
*/
3265533144
static int winFileControl(sqlite3_file *id, int op, void *pArg){
33145
+ winFile *pFile = (winFile*)id;
3265633146
switch( op ){
3265733147
case SQLITE_FCNTL_LOCKSTATE: {
32658
- *(int*)pArg = ((winFile*)id)->locktype;
33148
+ *(int*)pArg = pFile->locktype;
3265933149
return SQLITE_OK;
3266033150
}
3266133151
case SQLITE_LAST_ERRNO: {
32662
- *(int*)pArg = (int)((winFile*)id)->lastErrno;
33152
+ *(int*)pArg = (int)pFile->lastErrno;
3266333153
return SQLITE_OK;
3266433154
}
3266533155
case SQLITE_FCNTL_CHUNK_SIZE: {
32666
- ((winFile*)id)->szChunk = *(int *)pArg;
33156
+ pFile->szChunk = *(int *)pArg;
3266733157
return SQLITE_OK;
3266833158
}
3266933159
case SQLITE_FCNTL_SIZE_HINT: {
32670
- sqlite3_int64 sz = *(sqlite3_int64*)pArg;
32671
- SimulateIOErrorBenign(1);
32672
- winTruncate(id, sz);
32673
- SimulateIOErrorBenign(0);
33160
+ winFile *pFile = (winFile*)id;
33161
+ sqlite3_int64 oldSz;
33162
+ int rc = winFileSize(id, &oldSz);
33163
+ if( rc==SQLITE_OK ){
33164
+ sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
33165
+ if( newSz>oldSz ){
33166
+ SimulateIOErrorBenign(1);
33167
+ rc = winTruncate(id, newSz);
33168
+ SimulateIOErrorBenign(0);
33169
+ }
33170
+ }
33171
+ return rc;
33172
+ }
33173
+ case SQLITE_FCNTL_PERSIST_WAL: {
33174
+ int bPersist = *(int*)pArg;
33175
+ if( bPersist<0 ){
33176
+ *(int*)pArg = pFile->bPersistWal;
33177
+ }else{
33178
+ pFile->bPersistWal = bPersist!=0;
33179
+ }
3267433180
return SQLITE_OK;
3267533181
}
3267633182
case SQLITE_FCNTL_SYNC_OMITTED: {
3267733183
return SQLITE_OK;
33184
+ }
33185
+ case SQLITE_FCNTL_WIN32_AV_RETRY: {
33186
+ int *a = (int*)pArg;
33187
+ if( a[0]>0 ){
33188
+ win32IoerrRetry = a[0];
33189
+ }else{
33190
+ a[0] = win32IoerrRetry;
33191
+ }
33192
+ if( a[1]>0 ){
33193
+ win32IoerrRetryDelay = a[1];
33194
+ }else{
33195
+ a[1] = win32IoerrRetryDelay;
33196
+ }
33197
+ return SQLITE_OK;
3267833198
}
3267933199
}
3268033200
return SQLITE_NOTFOUND;
3268133201
}
3268233202
@@ -33482,10 +34002,11 @@
3348234002
int isTemp = 0;
3348334003
#endif
3348434004
winFile *pFile = (winFile*)id;
3348534005
void *zConverted; /* Filename in OS encoding */
3348634006
const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
34007
+ int cnt = 0;
3348734008
3348834009
/* If argument zPath is a NULL pointer, this function is required to open
3348934010
** a temporary file. Use this buffer to store the file name in.
3349034011
*/
3349134012
char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */
@@ -33601,34 +34122,34 @@
3360134122
#if SQLITE_OS_WINCE
3360234123
dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
3360334124
#endif
3360434125
3360534126
if( isNT() ){
33606
- h = CreateFileW((WCHAR*)zConverted,
33607
- dwDesiredAccess,
33608
- dwShareMode,
33609
- NULL,
33610
- dwCreationDisposition,
33611
- dwFlagsAndAttributes,
33612
- NULL
33613
- );
34127
+ while( (h = CreateFileW((WCHAR*)zConverted,
34128
+ dwDesiredAccess,
34129
+ dwShareMode, NULL,
34130
+ dwCreationDisposition,
34131
+ dwFlagsAndAttributes,
34132
+ NULL))==INVALID_HANDLE_VALUE &&
34133
+ retryIoerr(&cnt) ){}
3361434134
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3361534135
** Since the ASCII version of these Windows API do not exist for WINCE,
3361634136
** it's important to not reference them for WINCE builds.
3361734137
*/
3361834138
#if SQLITE_OS_WINCE==0
3361934139
}else{
33620
- h = CreateFileA((char*)zConverted,
33621
- dwDesiredAccess,
33622
- dwShareMode,
33623
- NULL,
33624
- dwCreationDisposition,
33625
- dwFlagsAndAttributes,
33626
- NULL
33627
- );
34140
+ while( (h = CreateFileA((char*)zConverted,
34141
+ dwDesiredAccess,
34142
+ dwShareMode, NULL,
34143
+ dwCreationDisposition,
34144
+ dwFlagsAndAttributes,
34145
+ NULL))==INVALID_HANDLE_VALUE &&
34146
+ retryIoerr(&cnt) ){}
3362834147
#endif
3362934148
}
34149
+
34150
+ logIoerr(cnt);
3363034151
3363134152
OSTRACE(("OPEN %d %s 0x%lx %s\n",
3363234153
h, zName, dwDesiredAccess,
3363334154
h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
3363434155
@@ -33691,19 +34212,17 @@
3369134212
** file open, we will be unable to delete it. To work around this
3369234213
** problem, we delay 100 milliseconds and try to delete again. Up
3369334214
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
3369434215
** up and returning an error.
3369534216
*/
33696
-#define MX_DELETION_ATTEMPTS 5
3369734217
static int winDelete(
3369834218
sqlite3_vfs *pVfs, /* Not used on win32 */
3369934219
const char *zFilename, /* Name of file to delete */
3370034220
int syncDir /* Not used on win32 */
3370134221
){
3370234222
int cnt = 0;
33703
- DWORD rc;
33704
- DWORD error = 0;
34223
+ int rc;
3370534224
void *zConverted;
3370634225
UNUSED_PARAMETER(pVfs);
3370734226
UNUSED_PARAMETER(syncDir);
3370834227
3370934228
SimulateIOError(return SQLITE_IOERR_DELETE);
@@ -33710,38 +34229,34 @@
3371034229
zConverted = convertUtf8Filename(zFilename);
3371134230
if( zConverted==0 ){
3371234231
return SQLITE_NOMEM;
3371334232
}
3371434233
if( isNT() ){
33715
- do{
33716
- DeleteFileW(zConverted);
33717
- }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
33718
- || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33719
- && (++cnt < MX_DELETION_ATTEMPTS)
33720
- && (Sleep(100), 1) );
34234
+ rc = 1;
34235
+ while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
34236
+ (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}
34237
+ rc = rc ? SQLITE_OK : SQLITE_ERROR;
3372134238
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3372234239
** Since the ASCII version of these Windows API do not exist for WINCE,
3372334240
** it's important to not reference them for WINCE builds.
3372434241
*/
3372534242
#if SQLITE_OS_WINCE==0
3372634243
}else{
33727
- do{
33728
- DeleteFileA(zConverted);
33729
- }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
33730
- || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33731
- && (++cnt < MX_DELETION_ATTEMPTS)
33732
- && (Sleep(100), 1) );
34244
+ rc = 1;
34245
+ while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
34246
+ (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}
34247
+ rc = rc ? SQLITE_OK : SQLITE_ERROR;
3373334248
#endif
3373434249
}
34250
+ if( rc ){
34251
+ rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
34252
+ }else{
34253
+ logIoerr(cnt);
34254
+ }
3373534255
free(zConverted);
33736
- OSTRACE(("DELETE \"%s\" %s\n", zFilename,
33737
- ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
33738
- "ok" : "failed" ));
33739
-
33740
- return ( (rc == INVALID_FILE_ATTRIBUTES)
33741
- && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
33742
- winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
34256
+ OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
34257
+ return rc;
3374334258
}
3374434259
3374534260
/*
3374634261
** Check the existance and status of a file.
3374734262
*/
@@ -33760,15 +34275,17 @@
3376034275
zConverted = convertUtf8Filename(zFilename);
3376134276
if( zConverted==0 ){
3376234277
return SQLITE_NOMEM;
3376334278
}
3376434279
if( isNT() ){
34280
+ int cnt = 0;
3376534281
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
3376634282
memset(&sAttrData, 0, sizeof(sAttrData));
33767
- if( GetFileAttributesExW((WCHAR*)zConverted,
34283
+ while( !(rc = GetFileAttributesExW((WCHAR*)zConverted,
3376834284
GetFileExInfoStandard,
33769
- &sAttrData) ){
34285
+ &sAttrData)) && retryIoerr(&cnt) ){}
34286
+ if( rc ){
3377034287
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
3377134288
** as if it does not exist.
3377234289
*/
3377334290
if( flags==SQLITE_ACCESS_EXISTS
3377434291
&& sAttrData.nFileSizeHigh==0
@@ -33776,10 +34293,11 @@
3377634293
attr = INVALID_FILE_ATTRIBUTES;
3377734294
}else{
3377834295
attr = sAttrData.dwFileAttributes;
3377934296
}
3378034297
}else{
34298
+ logIoerr(cnt);
3378134299
if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
3378234300
winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
3378334301
free(zConverted);
3378434302
return SQLITE_IOERR_ACCESS;
3378534303
}else{
@@ -33800,11 +34318,12 @@
3380034318
case SQLITE_ACCESS_READ:
3380134319
case SQLITE_ACCESS_EXISTS:
3380234320
rc = attr!=INVALID_FILE_ATTRIBUTES;
3380334321
break;
3380434322
case SQLITE_ACCESS_READWRITE:
33805
- rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
34323
+ rc = attr!=INVALID_FILE_ATTRIBUTES &&
34324
+ (attr & FILE_ATTRIBUTE_READONLY)==0;
3380634325
break;
3380734326
default:
3380834327
assert(!"Invalid flags argument");
3380934328
}
3381034329
*pResOut = rc;
@@ -35256,10 +35775,13 @@
3525635775
typedef struct PCache1 PCache1;
3525735776
typedef struct PgHdr1 PgHdr1;
3525835777
typedef struct PgFreeslot PgFreeslot;
3525935778
typedef struct PGroup PGroup;
3526035779
35780
+typedef struct PGroupBlock PGroupBlock;
35781
+typedef struct PGroupBlockList PGroupBlockList;
35782
+
3526135783
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
3526235784
** of one or more PCaches that are able to recycle each others unpinned
3526335785
** pages when they are under memory pressure. A PGroup is an instance of
3526435786
** the following object.
3526535787
**
@@ -35285,12 +35807,70 @@
3528535807
int nMaxPage; /* Sum of nMax for purgeable caches */
3528635808
int nMinPage; /* Sum of nMin for purgeable caches */
3528735809
int mxPinned; /* nMaxpage + 10 - nMinPage */
3528835810
int nCurrentPage; /* Number of purgeable pages allocated */
3528935811
PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
35812
+#ifdef SQLITE_PAGECACHE_BLOCKALLOC
35813
+ int isBusy; /* Do not run ReleaseMemory() if true */
35814
+ PGroupBlockList *pBlockList; /* List of block-lists for this group */
35815
+#endif
3529035816
};
3529135817
35818
+/*
35819
+** If SQLITE_PAGECACHE_BLOCKALLOC is defined when the library is built,
35820
+** each PGroup structure has a linked list of the the following starting
35821
+** at PGroup.pBlockList. There is one entry for each distinct page-size
35822
+** currently used by members of the PGroup (i.e. 1024 bytes, 4096 bytes
35823
+** etc.). Variable PGroupBlockList.nByte is set to the actual allocation
35824
+** size requested by each pcache, which is the database page-size plus
35825
+** the various header structures used by the pcache, pager and btree layers.
35826
+** Usually around (pgsz+200) bytes.
35827
+**
35828
+** This size (pgsz+200) bytes is not allocated efficiently by some
35829
+** implementations of malloc. In particular, some implementations are only
35830
+** able to allocate blocks of memory chunks of 2^N bytes, where N is some
35831
+** integer value. Since the page-size is a power of 2, this means we
35832
+** end up wasting (pgsz-200) bytes in each allocation.
35833
+**
35834
+** If SQLITE_PAGECACHE_BLOCKALLOC is defined, the (pgsz+200) byte blocks
35835
+** are not allocated directly. Instead, blocks of roughly M*(pgsz+200) bytes
35836
+** are requested from malloc allocator. After a block is returned,
35837
+** sqlite3MallocSize() is used to determine how many (pgsz+200) byte
35838
+** allocations can fit in the space returned by malloc(). This value may
35839
+** be more than M.
35840
+**
35841
+** The blocks are stored in a doubly-linked list. Variable PGroupBlock.nEntry
35842
+** contains the number of allocations that will fit in the aData[] space.
35843
+** nEntry is limited to the number of bits in bitmask mUsed. If a slot
35844
+** within aData is in use, the corresponding bit in mUsed is set. Thus
35845
+** when (mUsed+1==(1 << nEntry)) the block is completely full.
35846
+**
35847
+** Each time a slot within a block is freed, the block is moved to the start
35848
+** of the linked-list. And if a block becomes completely full, then it is
35849
+** moved to the end of the list. As a result, when searching for a free
35850
+** slot, only the first block in the list need be examined. If it is full,
35851
+** then it is guaranteed that all blocks are full.
35852
+*/
35853
+struct PGroupBlockList {
35854
+ int nByte; /* Size of each allocation in bytes */
35855
+ PGroupBlock *pFirst; /* First PGroupBlock in list */
35856
+ PGroupBlock *pLast; /* Last PGroupBlock in list */
35857
+ PGroupBlockList *pNext; /* Next block-list attached to group */
35858
+};
35859
+
35860
+struct PGroupBlock {
35861
+ Bitmask mUsed; /* Mask of used slots */
35862
+ int nEntry; /* Maximum number of allocations in aData[] */
35863
+ u8 *aData; /* Pointer to data block */
35864
+ PGroupBlock *pNext; /* Next PGroupBlock in list */
35865
+ PGroupBlock *pPrev; /* Previous PGroupBlock in list */
35866
+ PGroupBlockList *pList; /* Owner list */
35867
+};
35868
+
35869
+/* Minimum value for PGroupBlock.nEntry */
35870
+#define PAGECACHE_BLOCKALLOC_MINENTRY 15
35871
+
3529235872
/* Each page cache is an instance of the following object. Every
3529335873
** open database file (including each in-memory database and each
3529435874
** temporary or transient database) has a single page cache which
3529535875
** is an instance of this object.
3529635876
**
@@ -35389,10 +35969,21 @@
3538935969
**
3539035970
** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
3539135971
*/
3539235972
#define PGHDR1_TO_PAGE(p) (void*)(((char*)p) - p->pCache->szPage)
3539335973
#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)
35974
+
35975
+/*
35976
+** Blocks used by the SQLITE_PAGECACHE_BLOCKALLOC blocks to store/retrieve
35977
+** a PGroupBlock pointer based on a pointer to a page buffer.
35978
+*/
35979
+#define PAGE_SET_BLOCKPTR(pCache, pPg, pBlock) \
35980
+ ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) = pBlock )
35981
+
35982
+#define PAGE_GET_BLOCKPTR(pCache, pPg) \
35983
+ ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) )
35984
+
3539435985
3539535986
/*
3539635987
** Macros to enter and leave the PCache LRU mutex.
3539735988
*/
3539835989
#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
@@ -35515,25 +36106,159 @@
3551536106
return iSize;
3551636107
}
3551736108
}
3551836109
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
3551936110
36111
+#ifdef SQLITE_PAGECACHE_BLOCKALLOC
36112
+/*
36113
+** The block pBlock belongs to list pList but is not currently linked in.
36114
+** Insert it into the start of the list.
36115
+*/
36116
+static void addBlockToList(PGroupBlockList *pList, PGroupBlock *pBlock){
36117
+ pBlock->pPrev = 0;
36118
+ pBlock->pNext = pList->pFirst;
36119
+ pList->pFirst = pBlock;
36120
+ if( pBlock->pNext ){
36121
+ pBlock->pNext->pPrev = pBlock;
36122
+ }else{
36123
+ assert( pList->pLast==0 );
36124
+ pList->pLast = pBlock;
36125
+ }
36126
+}
36127
+
36128
+/*
36129
+** If there are no blocks in the list headed by pList, remove pList
36130
+** from the pGroup->pBlockList list and free it with sqlite3_free().
36131
+*/
36132
+static void freeListIfEmpty(PGroup *pGroup, PGroupBlockList *pList){
36133
+ assert( sqlite3_mutex_held(pGroup->mutex) );
36134
+ if( pList->pFirst==0 ){
36135
+ PGroupBlockList **pp;
36136
+ for(pp=&pGroup->pBlockList; *pp!=pList; pp=&(*pp)->pNext);
36137
+ *pp = (*pp)->pNext;
36138
+ sqlite3_free(pList);
36139
+ }
36140
+}
36141
+#endif /* SQLITE_PAGECACHE_BLOCKALLOC */
36142
+
3552036143
/*
3552136144
** Allocate a new page object initially associated with cache pCache.
3552236145
*/
3552336146
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
3552436147
int nByte = sizeof(PgHdr1) + pCache->szPage;
35525
- void *pPg = pcache1Alloc(nByte);
36148
+ void *pPg = 0;
3552636149
PgHdr1 *p;
36150
+
36151
+#ifdef SQLITE_PAGECACHE_BLOCKALLOC
36152
+ PGroup *pGroup = pCache->pGroup;
36153
+ PGroupBlockList *pList;
36154
+ PGroupBlock *pBlock;
36155
+ int i;
36156
+
36157
+ nByte += sizeof(PGroupBlockList *);
36158
+ nByte = ROUND8(nByte);
36159
+
36160
+ for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
36161
+ if( pList->nByte==nByte ) break;
36162
+ }
36163
+ if( pList==0 ){
36164
+ PGroupBlockList *pNew;
36165
+ assert( pGroup->isBusy==0 );
36166
+ assert( sqlite3_mutex_held(pGroup->mutex) );
36167
+ pGroup->isBusy = 1; /* Disable sqlite3PcacheReleaseMemory() */
36168
+ pNew = (PGroupBlockList *)sqlite3MallocZero(sizeof(PGroupBlockList));
36169
+ pGroup->isBusy = 0; /* Reenable sqlite3PcacheReleaseMemory() */
36170
+ if( pNew==0 ){
36171
+ /* malloc() failure. Return early. */
36172
+ return 0;
36173
+ }
36174
+#ifdef SQLITE_DEBUG
36175
+ for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
36176
+ assert( pList->nByte!=nByte );
36177
+ }
36178
+#endif
36179
+ pNew->nByte = nByte;
36180
+ pNew->pNext = pGroup->pBlockList;
36181
+ pGroup->pBlockList = pNew;
36182
+ pList = pNew;
36183
+ }
36184
+
36185
+ pBlock = pList->pFirst;
36186
+ if( pBlock==0 || pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) ){
36187
+ int sz;
36188
+
36189
+ /* Allocate a new block. Try to allocate enough space for the PGroupBlock
36190
+ ** structure and MINENTRY allocations of nByte bytes each. If the
36191
+ ** allocator returns more memory than requested, then more than MINENTRY
36192
+ ** allocations may fit in it. */
36193
+ assert( sqlite3_mutex_held(pGroup->mutex) );
36194
+ pcache1LeaveMutex(pCache->pGroup);
36195
+ sz = sizeof(PGroupBlock) + PAGECACHE_BLOCKALLOC_MINENTRY * nByte;
36196
+ pBlock = (PGroupBlock *)sqlite3Malloc(sz);
36197
+ pcache1EnterMutex(pCache->pGroup);
36198
+
36199
+ if( !pBlock ){
36200
+ freeListIfEmpty(pGroup, pList);
36201
+ return 0;
36202
+ }
36203
+ pBlock->nEntry = (sqlite3MallocSize(pBlock) - sizeof(PGroupBlock)) / nByte;
36204
+ if( pBlock->nEntry>=BMS ){
36205
+ pBlock->nEntry = BMS-1;
36206
+ }
36207
+ pBlock->pList = pList;
36208
+ pBlock->mUsed = 0;
36209
+ pBlock->aData = (u8 *)&pBlock[1];
36210
+ addBlockToList(pList, pBlock);
36211
+
36212
+ sz = sqlite3MallocSize(pBlock);
36213
+ sqlite3_mutex_enter(pcache1.mutex);
36214
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
36215
+ sqlite3_mutex_leave(pcache1.mutex);
36216
+ }
36217
+
36218
+ for(i=0; pPg==0 && ALWAYS(i<pBlock->nEntry); i++){
36219
+ if( 0==(pBlock->mUsed & ((Bitmask)1<<i)) ){
36220
+ pBlock->mUsed |= ((Bitmask)1<<i);
36221
+ pPg = (void *)&pBlock->aData[pList->nByte * i];
36222
+ }
36223
+ }
36224
+ assert( pPg );
36225
+ PAGE_SET_BLOCKPTR(pCache, pPg, pBlock);
36226
+
36227
+ /* If the block is now full, shift it to the end of the list */
36228
+ if( pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) && pList->pLast!=pBlock ){
36229
+ assert( pList->pFirst==pBlock );
36230
+ assert( pBlock->pPrev==0 );
36231
+ assert( pList->pLast->pNext==0 );
36232
+ pList->pFirst = pBlock->pNext;
36233
+ pList->pFirst->pPrev = 0;
36234
+ pBlock->pPrev = pList->pLast;
36235
+ pBlock->pNext = 0;
36236
+ pList->pLast->pNext = pBlock;
36237
+ pList->pLast = pBlock;
36238
+ }
36239
+ p = PAGE_TO_PGHDR1(pCache, pPg);
36240
+ if( pCache->bPurgeable ){
36241
+ pCache->pGroup->nCurrentPage++;
36242
+ }
36243
+#else
36244
+ /* The group mutex must be released before pcache1Alloc() is called. This
36245
+ ** is because it may call sqlite3_release_memory(), which assumes that
36246
+ ** this mutex is not held. */
36247
+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
36248
+ pcache1LeaveMutex(pCache->pGroup);
36249
+ pPg = pcache1Alloc(nByte);
36250
+ pcache1EnterMutex(pCache->pGroup);
3552736251
if( pPg ){
3552836252
p = PAGE_TO_PGHDR1(pCache, pPg);
3552936253
if( pCache->bPurgeable ){
3553036254
pCache->pGroup->nCurrentPage++;
3553136255
}
3553236256
}else{
3553336257
p = 0;
3553436258
}
36259
+#endif
3553536260
return p;
3553636261
}
3553736262
3553836263
/*
3553936264
** Free a page object allocated by pcache1AllocPage().
@@ -35543,14 +36268,56 @@
3554336268
** with a NULL pointer, so we mark the NULL test with ALWAYS().
3554436269
*/
3554536270
static void pcache1FreePage(PgHdr1 *p){
3554636271
if( ALWAYS(p) ){
3554736272
PCache1 *pCache = p->pCache;
36273
+ void *pPg = PGHDR1_TO_PAGE(p);
36274
+
36275
+#ifdef SQLITE_PAGECACHE_BLOCKALLOC
36276
+ PGroupBlock *pBlock = PAGE_GET_BLOCKPTR(pCache, pPg);
36277
+ PGroupBlockList *pList = pBlock->pList;
36278
+ int i = ((u8 *)pPg - pBlock->aData) / pList->nByte;
36279
+
36280
+ assert( pPg==(void *)&pBlock->aData[i*pList->nByte] );
36281
+ assert( pBlock->mUsed & ((Bitmask)1<<i) );
36282
+ pBlock->mUsed &= ~((Bitmask)1<<i);
36283
+
36284
+ /* Remove the block from the list. If it is completely empty, free it.
36285
+ ** Or if it is not completely empty, re-insert it at the start of the
36286
+ ** list. */
36287
+ if( pList->pFirst==pBlock ){
36288
+ pList->pFirst = pBlock->pNext;
36289
+ if( pList->pFirst ) pList->pFirst->pPrev = 0;
36290
+ }else{
36291
+ pBlock->pPrev->pNext = pBlock->pNext;
36292
+ }
36293
+ if( pList->pLast==pBlock ){
36294
+ pList->pLast = pBlock->pPrev;
36295
+ if( pList->pLast ) pList->pLast->pNext = 0;
36296
+ }else{
36297
+ pBlock->pNext->pPrev = pBlock->pPrev;
36298
+ }
36299
+
36300
+ if( pBlock->mUsed==0 ){
36301
+ PGroup *pGroup = p->pCache->pGroup;
36302
+
36303
+ int sz = sqlite3MallocSize(pBlock);
36304
+ sqlite3_mutex_enter(pcache1.mutex);
36305
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -sz);
36306
+ sqlite3_mutex_leave(pcache1.mutex);
36307
+ freeListIfEmpty(pGroup, pList);
36308
+ sqlite3_free(pBlock);
36309
+ }else{
36310
+ addBlockToList(pList, pBlock);
36311
+ }
36312
+#else
36313
+ assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
36314
+ pcache1Free(pPg);
36315
+#endif
3554836316
if( pCache->bPurgeable ){
3554936317
pCache->pGroup->nCurrentPage--;
3555036318
}
35551
- pcache1Free(PGHDR1_TO_PAGE(p));
3555236319
}
3555336320
}
3555436321
3555536322
/*
3555636323
** Malloc function used by SQLite to obtain space from the buffer configured
@@ -35984,13 +36751,11 @@
3598436751
/* Step 5. If a usable page buffer has still not been found,
3598536752
** attempt to allocate a new one.
3598636753
*/
3598736754
if( !pPage ){
3598836755
if( createFlag==1 ) sqlite3BeginBenignMalloc();
35989
- pcache1LeaveMutex(pGroup);
3599036756
pPage = pcache1AllocPage(pCache);
35991
- pcache1EnterMutex(pGroup);
3599236757
if( createFlag==1 ) sqlite3EndBenignMalloc();
3599336758
}
3599436759
3599536760
if( pPage ){
3599636761
unsigned int h = iKey % pCache->nHash;
@@ -36156,10 +36921,13 @@
3615636921
** been released, the function returns. The return value is the total number
3615736922
** of bytes of memory released.
3615836923
*/
3615936924
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
3616036925
int nFree = 0;
36926
+#ifdef SQLITE_PAGECACHE_BLOCKALLOC
36927
+ if( pcache1.grp.isBusy ) return 0;
36928
+#endif
3616136929
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
3616236930
assert( sqlite3_mutex_notheld(pcache1.mutex) );
3616336931
if( pcache1.pStart==0 ){
3616436932
PgHdr1 *p;
3616536933
pcache1EnterMutex(&pcache1.grp);
@@ -37368,10 +38136,12 @@
3736838136
u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
3736938137
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
3737038138
u8 tempFile; /* zFilename is a temporary file */
3737138139
u8 readOnly; /* True for a read-only database */
3737238140
u8 memDb; /* True to inhibit all file I/O */
38141
+ u8 hasSeenStress; /* pagerStress() called one or more times */
38142
+ u8 isSorter; /* True for a PAGER_SORTER */
3737338143
3737438144
/**************************************************************************
3737538145
** The following block contains those class members that change during
3737638146
** routine opertion. Class members not in this block are either fixed
3737738147
** when the pager is first created or else only change when there is a
@@ -37590,10 +38360,19 @@
3759038360
|| p->journalMode==PAGER_JOURNALMODE_MEMORY
3759138361
);
3759238362
assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
3759338363
assert( pagerUseWal(p)==0 );
3759438364
}
38365
+
38366
+ /* A sorter is a temp file that never spills to disk and always has
38367
+ ** the doNotSpill flag set
38368
+ */
38369
+ if( p->isSorter ){
38370
+ assert( p->tempFile );
38371
+ assert( p->doNotSpill );
38372
+ assert( p->fd->pMethods==0 );
38373
+ }
3759538374
3759638375
/* If changeCountDone is set, a RESERVED lock or greater must be held
3759738376
** on the file.
3759838377
*/
3759938378
assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
@@ -40487,10 +41266,11 @@
4048741266
** to the caller.
4048841267
*/
4048941268
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
4049041269
u8 *pTmp = (u8 *)pPager->pTmpSpace;
4049141270
41271
+ assert( assert_pager_state(pPager) );
4049241272
disable_simulated_io_errors();
4049341273
sqlite3BeginBenignMalloc();
4049441274
/* pPager->errCode = 0; */
4049541275
pPager->exclusiveMode = 0;
4049641276
#ifndef SQLITE_OMIT_WAL
@@ -40921,10 +41701,11 @@
4092141701
** is impossible for sqlite3PCacheFetch() to be called with createFlag==1
4092241702
** while in the error state, hence it is impossible for this routine to
4092341703
** be called in the error state. Nevertheless, we include a NEVER()
4092441704
** test for the error state as a safeguard against future changes.
4092541705
*/
41706
+ pPager->hasSeenStress = 1;
4092641707
if( NEVER(pPager->errCode) ) return SQLITE_OK;
4092741708
if( pPager->doNotSpill ) return SQLITE_OK;
4092841709
if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
4092941710
return SQLITE_OK;
4093041711
}
@@ -41292,10 +42073,16 @@
4129242073
}
4129342074
/* pPager->xBusyHandler = 0; */
4129442075
/* pPager->pBusyHandlerArg = 0; */
4129542076
pPager->xReiniter = xReinit;
4129642077
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
42078
+#ifndef SQLITE_OMIT_MERGE_SORT
42079
+ if( flags & PAGER_SORTER ){
42080
+ pPager->doNotSpill = 1;
42081
+ pPager->isSorter = 1;
42082
+ }
42083
+#endif
4129742084
4129842085
*ppPager = pPager;
4129942086
return SQLITE_OK;
4130042087
}
4130142088
@@ -42835,10 +43622,21 @@
4283543622
** Return true if this is an in-memory pager.
4283643623
*/
4283743624
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
4283843625
return MEMDB;
4283943626
}
43627
+
43628
+#ifndef SQLITE_OMIT_MERGE_SORT
43629
+/*
43630
+** Return true if the pager has seen a pagerStress callback.
43631
+*/
43632
+SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager *pPager){
43633
+ assert( pPager->isSorter );
43634
+ assert( pPager->doNotSpill );
43635
+ return pPager->hasSeenStress;
43636
+}
43637
+#endif
4284043638
4284143639
/*
4284243640
** Check that there are at least nSavepoint savepoints open. If there are
4284343641
** currently less than nSavepoints open, then open one or more savepoints
4284443642
** to make up the difference. If the number of savepoints is already
@@ -45384,17 +46182,19 @@
4538446182
**
4538546183
** The EXCLUSIVE lock is not released before returning.
4538646184
*/
4538746185
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
4538846186
if( rc==SQLITE_OK ){
46187
+ int bPersistWal = -1;
4538946188
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
4539046189
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
4539146190
}
4539246191
rc = sqlite3WalCheckpoint(
4539346192
pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
4539446193
);
45395
- if( rc==SQLITE_OK ){
46194
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
46195
+ if( rc==SQLITE_OK && bPersistWal!=1 ){
4539646196
isDelete = 1;
4539746197
}
4539846198
}
4539946199
4540046200
walIndexClose(pWal, isDelete);
@@ -49202,15 +50002,26 @@
4920250002
assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
4920350003
4920450004
/* A BTREE_SINGLE database is always a temporary and/or ephemeral */
4920550005
assert( (flags & BTREE_SINGLE)==0 || isTempDb );
4920650006
50007
+ /* The BTREE_SORTER flag is only used if SQLITE_OMIT_MERGE_SORT is undef */
50008
+#ifdef SQLITE_OMIT_MERGE_SORT
50009
+ assert( (flags & BTREE_SORTER)==0 );
50010
+#endif
50011
+
50012
+ /* BTREE_SORTER is always on a BTREE_SINGLE, BTREE_OMIT_JOURNAL */
50013
+ assert( (flags & BTREE_SORTER)==0 ||
50014
+ (flags & (BTREE_SINGLE|BTREE_OMIT_JOURNAL))
50015
+ ==(BTREE_SINGLE|BTREE_OMIT_JOURNAL) );
50016
+
4920750017
if( db->flags & SQLITE_NoReadlock ){
4920850018
flags |= BTREE_NO_READLOCK;
4920950019
}
4921050020
if( isMemdb ){
4921150021
flags |= BTREE_MEMORY;
50022
+ flags &= ~BTREE_SORTER;
4921250023
}
4921350024
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
4921450025
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
4921550026
}
4921650027
p = sqlite3MallocZero(sizeof(Btree));
@@ -50936,11 +51747,12 @@
5093651747
5093751748
if( NEVER(wrFlag && pBt->readOnly) ){
5093851749
return SQLITE_READONLY;
5093951750
}
5094051751
if( iTable==1 && btreePagecount(pBt)==0 ){
50941
- return SQLITE_EMPTY;
51752
+ assert( wrFlag==0 );
51753
+ iTable = 0;
5094251754
}
5094351755
5094451756
/* Now that no other errors can occur, finish filling in the BtCursor
5094551757
** variables and link the cursor into the BtShared list. */
5094651758
pCur->pgnoRoot = (Pgno)iTable;
@@ -51690,10 +52502,13 @@
5169052502
int i;
5169152503
for(i=1; i<=pCur->iPage; i++){
5169252504
releasePage(pCur->apPage[i]);
5169352505
}
5169452506
pCur->iPage = 0;
52507
+ }else if( pCur->pgnoRoot==0 ){
52508
+ pCur->eState = CURSOR_INVALID;
52509
+ return SQLITE_OK;
5169552510
}else{
5169652511
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
5169752512
if( rc!=SQLITE_OK ){
5169852513
pCur->eState = CURSOR_INVALID;
5169952514
return rc;
@@ -51799,11 +52614,11 @@
5179952614
assert( cursorHoldsMutex(pCur) );
5180052615
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
5180152616
rc = moveToRoot(pCur);
5180252617
if( rc==SQLITE_OK ){
5180352618
if( pCur->eState==CURSOR_INVALID ){
51804
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
52619
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
5180552620
*pRes = 1;
5180652621
}else{
5180752622
assert( pCur->apPage[pCur->iPage]->nCell>0 );
5180852623
*pRes = 0;
5180952624
rc = moveToLeftmost(pCur);
@@ -51838,11 +52653,11 @@
5183852653
}
5183952654
5184052655
rc = moveToRoot(pCur);
5184152656
if( rc==SQLITE_OK ){
5184252657
if( CURSOR_INVALID==pCur->eState ){
51843
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
52658
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
5184452659
*pRes = 1;
5184552660
}else{
5184652661
assert( pCur->eState==CURSOR_VALID );
5184752662
*pRes = 0;
5184852663
rc = moveToRightmost(pCur);
@@ -51911,16 +52726,16 @@
5191152726
5191252727
rc = moveToRoot(pCur);
5191352728
if( rc ){
5191452729
return rc;
5191552730
}
51916
- assert( pCur->apPage[pCur->iPage] );
51917
- assert( pCur->apPage[pCur->iPage]->isInit );
51918
- assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
52731
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
52732
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
52733
+ assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
5191952734
if( pCur->eState==CURSOR_INVALID ){
5192052735
*pRes = -1;
51921
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
52736
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
5192252737
return SQLITE_OK;
5192352738
}
5192452739
assert( pCur->apPage[0]->intKey || pIdxKey );
5192552740
for(;;){
5192652741
int lwr, upr, idx;
@@ -54745,13 +55560,20 @@
5474555560
releasePage(pPage);
5474655561
}
5474755562
return rc;
5474855563
}
5474955564
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
55565
+ BtShared *pBt = p->pBt;
5475055566
int rc;
5475155567
sqlite3BtreeEnter(p);
54752
- rc = btreeDropTable(p, iTable, piMoved);
55568
+ if( (pBt->openFlags&BTREE_SINGLE) ){
55569
+ pBt->nPage = 0;
55570
+ sqlite3PagerTruncateImage(pBt->pPager, 1);
55571
+ rc = newDatabase(pBt);
55572
+ }else{
55573
+ rc = btreeDropTable(p, iTable, piMoved);
55574
+ }
5475355575
sqlite3BtreeLeave(p);
5475455576
return rc;
5475555577
}
5475655578
5475755579
@@ -54826,10 +55648,15 @@
5482655648
** corruption) an SQLite error code is returned.
5482755649
*/
5482855650
SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
5482955651
i64 nEntry = 0; /* Value to return in *pnEntry */
5483055652
int rc; /* Return code */
55653
+
55654
+ if( pCur->pgnoRoot==0 ){
55655
+ *pnEntry = 0;
55656
+ return SQLITE_OK;
55657
+ }
5483155658
rc = moveToRoot(pCur);
5483255659
5483355660
/* Unless an error occurs, the following loop runs one iteration for each
5483455661
** page in the B-Tree structure (not including overflow pages).
5483555662
*/
@@ -55610,11 +56437,10 @@
5561056437
*/
5561156438
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
5561256439
BtShared *pBt = pBtree->pBt;
5561356440
int rc; /* Return code */
5561456441
55615
- assert( pBtree->inTrans==TRANS_NONE );
5561656442
assert( iVersion==1 || iVersion==2 );
5561756443
5561856444
/* If setting the version fields to 1, do not automatically open the
5561956445
** WAL connection, even if the version fields are currently set to 2.
5562056446
*/
@@ -56049,106 +56875,110 @@
5604956875
/* Update the schema version field in the destination database. This
5605056876
** is to make sure that the schema-version really does change in
5605156877
** the case where the source and destination databases have the
5605256878
** same schema version.
5605356879
*/
56054
- if( rc==SQLITE_DONE
56055
- && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
56056
- ){
56057
- int nDestTruncate;
56058
-
56059
- if( p->pDestDb ){
56060
- sqlite3ResetInternalSchema(p->pDestDb, -1);
56061
- }
56062
-
56063
- /* Set nDestTruncate to the final number of pages in the destination
56064
- ** database. The complication here is that the destination page
56065
- ** size may be different to the source page size.
56066
- **
56067
- ** If the source page size is smaller than the destination page size,
56068
- ** round up. In this case the call to sqlite3OsTruncate() below will
56069
- ** fix the size of the file. However it is important to call
56070
- ** sqlite3PagerTruncateImage() here so that any pages in the
56071
- ** destination file that lie beyond the nDestTruncate page mark are
56072
- ** journalled by PagerCommitPhaseOne() before they are destroyed
56073
- ** by the file truncation.
56074
- */
56075
- assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
56076
- assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
56077
- if( pgszSrc<pgszDest ){
56078
- int ratio = pgszDest/pgszSrc;
56079
- nDestTruncate = (nSrcPage+ratio-1)/ratio;
56080
- if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
56081
- nDestTruncate--;
56082
- }
56083
- }else{
56084
- nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
56085
- }
56086
- sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
56087
-
56088
- if( pgszSrc<pgszDest ){
56089
- /* If the source page-size is smaller than the destination page-size,
56090
- ** two extra things may need to happen:
56091
- **
56092
- ** * The destination may need to be truncated, and
56093
- **
56094
- ** * Data stored on the pages immediately following the
56095
- ** pending-byte page in the source database may need to be
56096
- ** copied into the destination database.
56097
- */
56098
- const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
56099
- sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
56100
- i64 iOff;
56101
- i64 iEnd;
56102
-
56103
- assert( pFile );
56104
- assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
56105
- nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
56106
- && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
56107
- ));
56108
-
56109
- /* This call ensures that all data required to recreate the original
56110
- ** database has been stored in the journal for pDestPager and the
56111
- ** journal synced to disk. So at this point we may safely modify
56112
- ** the database file in any way, knowing that if a power failure
56113
- ** occurs, the original database will be reconstructed from the
56114
- ** journal file. */
56115
- rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
56116
-
56117
- /* Write the extra pages and truncate the database file as required. */
56118
- iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
56119
- for(
56120
- iOff=PENDING_BYTE+pgszSrc;
56121
- rc==SQLITE_OK && iOff<iEnd;
56122
- iOff+=pgszSrc
56123
- ){
56124
- PgHdr *pSrcPg = 0;
56125
- const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
56126
- rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
56127
- if( rc==SQLITE_OK ){
56128
- u8 *zData = sqlite3PagerGetData(pSrcPg);
56129
- rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
56130
- }
56131
- sqlite3PagerUnref(pSrcPg);
56132
- }
56133
- if( rc==SQLITE_OK ){
56134
- rc = backupTruncateFile(pFile, iSize);
56135
- }
56136
-
56137
- /* Sync the database file to disk. */
56138
- if( rc==SQLITE_OK ){
56139
- rc = sqlite3PagerSync(pDestPager);
56140
- }
56141
- }else{
56142
- rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
56143
- }
56144
-
56145
- /* Finish committing the transaction to the destination database. */
56146
- if( SQLITE_OK==rc
56147
- && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
56148
- ){
56149
- rc = SQLITE_DONE;
56880
+ if( rc==SQLITE_DONE ){
56881
+ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
56882
+ if( rc==SQLITE_OK ){
56883
+ if( p->pDestDb ){
56884
+ sqlite3ResetInternalSchema(p->pDestDb, -1);
56885
+ }
56886
+ if( destMode==PAGER_JOURNALMODE_WAL ){
56887
+ rc = sqlite3BtreeSetVersion(p->pDest, 2);
56888
+ }
56889
+ }
56890
+ if( rc==SQLITE_OK ){
56891
+ int nDestTruncate;
56892
+ /* Set nDestTruncate to the final number of pages in the destination
56893
+ ** database. The complication here is that the destination page
56894
+ ** size may be different to the source page size.
56895
+ **
56896
+ ** If the source page size is smaller than the destination page size,
56897
+ ** round up. In this case the call to sqlite3OsTruncate() below will
56898
+ ** fix the size of the file. However it is important to call
56899
+ ** sqlite3PagerTruncateImage() here so that any pages in the
56900
+ ** destination file that lie beyond the nDestTruncate page mark are
56901
+ ** journalled by PagerCommitPhaseOne() before they are destroyed
56902
+ ** by the file truncation.
56903
+ */
56904
+ assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
56905
+ assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
56906
+ if( pgszSrc<pgszDest ){
56907
+ int ratio = pgszDest/pgszSrc;
56908
+ nDestTruncate = (nSrcPage+ratio-1)/ratio;
56909
+ if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
56910
+ nDestTruncate--;
56911
+ }
56912
+ }else{
56913
+ nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
56914
+ }
56915
+ sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
56916
+
56917
+ if( pgszSrc<pgszDest ){
56918
+ /* If the source page-size is smaller than the destination page-size,
56919
+ ** two extra things may need to happen:
56920
+ **
56921
+ ** * The destination may need to be truncated, and
56922
+ **
56923
+ ** * Data stored on the pages immediately following the
56924
+ ** pending-byte page in the source database may need to be
56925
+ ** copied into the destination database.
56926
+ */
56927
+ const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
56928
+ sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
56929
+ i64 iOff;
56930
+ i64 iEnd;
56931
+
56932
+ assert( pFile );
56933
+ assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
56934
+ nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
56935
+ && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
56936
+ ));
56937
+
56938
+ /* This call ensures that all data required to recreate the original
56939
+ ** database has been stored in the journal for pDestPager and the
56940
+ ** journal synced to disk. So at this point we may safely modify
56941
+ ** the database file in any way, knowing that if a power failure
56942
+ ** occurs, the original database will be reconstructed from the
56943
+ ** journal file. */
56944
+ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
56945
+
56946
+ /* Write the extra pages and truncate the database file as required */
56947
+ iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
56948
+ for(
56949
+ iOff=PENDING_BYTE+pgszSrc;
56950
+ rc==SQLITE_OK && iOff<iEnd;
56951
+ iOff+=pgszSrc
56952
+ ){
56953
+ PgHdr *pSrcPg = 0;
56954
+ const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
56955
+ rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
56956
+ if( rc==SQLITE_OK ){
56957
+ u8 *zData = sqlite3PagerGetData(pSrcPg);
56958
+ rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
56959
+ }
56960
+ sqlite3PagerUnref(pSrcPg);
56961
+ }
56962
+ if( rc==SQLITE_OK ){
56963
+ rc = backupTruncateFile(pFile, iSize);
56964
+ }
56965
+
56966
+ /* Sync the database file to disk. */
56967
+ if( rc==SQLITE_OK ){
56968
+ rc = sqlite3PagerSync(pDestPager);
56969
+ }
56970
+ }else{
56971
+ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
56972
+ }
56973
+
56974
+ /* Finish committing the transaction to the destination database. */
56975
+ if( SQLITE_OK==rc
56976
+ && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
56977
+ ){
56978
+ rc = SQLITE_DONE;
56979
+ }
5615056980
}
5615156981
}
5615256982
5615356983
/* If bCloseTrans is true, then this function opened a read transaction
5615456984
** on the source database. Close the read transaction here. There is
@@ -56612,38 +57442,32 @@
5661257442
** invoking an external callback, free it now. Calling this function
5661357443
** does not free any Mem.zMalloc buffer.
5661457444
*/
5661557445
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
5661657446
assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
56617
- testcase( p->flags & MEM_Agg );
56618
- testcase( p->flags & MEM_Dyn );
56619
- testcase( p->flags & MEM_RowSet );
56620
- testcase( p->flags & MEM_Frame );
56621
- if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){
56622
- if( p->flags&MEM_Agg ){
56623
- sqlite3VdbeMemFinalize(p, p->u.pDef);
56624
- assert( (p->flags & MEM_Agg)==0 );
56625
- sqlite3VdbeMemRelease(p);
56626
- }else if( p->flags&MEM_Dyn && p->xDel ){
56627
- assert( (p->flags&MEM_RowSet)==0 );
56628
- p->xDel((void *)p->z);
56629
- p->xDel = 0;
56630
- }else if( p->flags&MEM_RowSet ){
56631
- sqlite3RowSetClear(p->u.pRowSet);
56632
- }else if( p->flags&MEM_Frame ){
56633
- sqlite3VdbeMemSetNull(p);
56634
- }
57447
+ if( p->flags&MEM_Agg ){
57448
+ sqlite3VdbeMemFinalize(p, p->u.pDef);
57449
+ assert( (p->flags & MEM_Agg)==0 );
57450
+ sqlite3VdbeMemRelease(p);
57451
+ }else if( p->flags&MEM_Dyn && p->xDel ){
57452
+ assert( (p->flags&MEM_RowSet)==0 );
57453
+ p->xDel((void *)p->z);
57454
+ p->xDel = 0;
57455
+ }else if( p->flags&MEM_RowSet ){
57456
+ sqlite3RowSetClear(p->u.pRowSet);
57457
+ }else if( p->flags&MEM_Frame ){
57458
+ sqlite3VdbeMemSetNull(p);
5663557459
}
5663657460
}
5663757461
5663857462
/*
5663957463
** Release any memory held by the Mem. This may leave the Mem in an
5664057464
** inconsistent state, for example with (Mem.z==0) and
5664157465
** (Mem.type==SQLITE_TEXT).
5664257466
*/
5664357467
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
56644
- sqlite3VdbeMemReleaseExternal(p);
57468
+ MemReleaseExt(p);
5664557469
sqlite3DbFree(p->db, p->zMalloc);
5664657470
p->z = 0;
5664757471
p->zMalloc = 0;
5664857472
p->xDel = 0;
5664957473
}
@@ -56961,11 +57785,11 @@
5696157785
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
5696257786
** and flags gets srcType (either MEM_Ephem or MEM_Static).
5696357787
*/
5696457788
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
5696557789
assert( (pFrom->flags & MEM_RowSet)==0 );
56966
- sqlite3VdbeMemReleaseExternal(pTo);
57790
+ MemReleaseExt(pTo);
5696757791
memcpy(pTo, pFrom, MEMCELLSIZE);
5696857792
pTo->xDel = 0;
5696957793
if( (pFrom->flags&MEM_Static)==0 ){
5697057794
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
5697157795
assert( srcType==MEM_Ephem || srcType==MEM_Static );
@@ -56979,11 +57803,11 @@
5697957803
*/
5698057804
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
5698157805
int rc = SQLITE_OK;
5698257806
5698357807
assert( (pFrom->flags & MEM_RowSet)==0 );
56984
- sqlite3VdbeMemReleaseExternal(pTo);
57808
+ MemReleaseExt(pTo);
5698557809
memcpy(pTo, pFrom, MEMCELLSIZE);
5698657810
pTo->flags &= ~MEM_Dyn;
5698757811
5698857812
if( pTo->flags&(MEM_Str|MEM_Blob) ){
5698957813
if( 0==(pFrom->flags&MEM_Static) ){
@@ -57934,10 +58758,16 @@
5793458758
assert( p->nOp - i >= 3 );
5793558759
assert( pOp[-1].opcode==OP_Integer );
5793658760
n = pOp[-1].p1;
5793758761
if( n>nMaxArgs ) nMaxArgs = n;
5793858762
#endif
58763
+ }else if( opcode==OP_Next ){
58764
+ pOp->p4.xAdvance = sqlite3BtreeNext;
58765
+ pOp->p4type = P4_ADVANCE;
58766
+ }else if( opcode==OP_Prev ){
58767
+ pOp->p4.xAdvance = sqlite3BtreePrevious;
58768
+ pOp->p4type = P4_ADVANCE;
5793958769
}
5794058770
5794158771
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
5794258772
assert( -1-pOp->p2<p->nLabel );
5794358773
pOp->p2 = aLabel[-1-pOp->p2];
@@ -58025,37 +58855,34 @@
5802558855
** Change the value of the P1 operand for a specific instruction.
5802658856
** This routine is useful when a large program is loaded from a
5802758857
** static array using sqlite3VdbeAddOpList but we want to make a
5802858858
** few minor changes to the program.
5802958859
*/
58030
-SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
58860
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
5803158861
assert( p!=0 );
58032
- assert( addr>=0 );
58033
- if( p->nOp>addr ){
58862
+ if( ((u32)p->nOp)>addr ){
5803458863
p->aOp[addr].p1 = val;
5803558864
}
5803658865
}
5803758866
5803858867
/*
5803958868
** Change the value of the P2 operand for a specific instruction.
5804058869
** This routine is useful for setting a jump destination.
5804158870
*/
58042
-SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
58871
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
5804358872
assert( p!=0 );
58044
- assert( addr>=0 );
58045
- if( p->nOp>addr ){
58873
+ if( ((u32)p->nOp)>addr ){
5804658874
p->aOp[addr].p2 = val;
5804758875
}
5804858876
}
5804958877
5805058878
/*
5805158879
** Change the value of the P3 operand for a specific instruction.
5805258880
*/
58053
-SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
58881
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
5805458882
assert( p!=0 );
58055
- assert( addr>=0 );
58056
- if( p->nOp>addr ){
58883
+ if( ((u32)p->nOp)>addr ){
5805758884
p->aOp[addr].p3 = val;
5805858885
}
5805958886
}
5806058887
5806158888
/*
@@ -58442,10 +59269,14 @@
5844259269
break;
5844359270
}
5844459271
case P4_SUBPROGRAM: {
5844559272
sqlite3_snprintf(nTemp, zTemp, "program");
5844659273
break;
59274
+ }
59275
+ case P4_ADVANCE: {
59276
+ zTemp[0] = 0;
59277
+ break;
5844759278
}
5844859279
default: {
5844959280
zP4 = pOp->p4.z;
5845059281
if( zP4==0 ){
5845159282
zP4 = zTemp;
@@ -59006,10 +59837,11 @@
5900659837
nMem = 10;
5900759838
}
5900859839
memset(zCsr, 0, zEnd-zCsr);
5900959840
zCsr += (zCsr - (u8*)0)&7;
5901059841
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
59842
+ p->expired = 0;
5901159843
5901259844
/* Memory for registers, parameters, cursor, etc, is allocated in two
5901359845
** passes. On the first pass, we try to reuse unused space at the
5901459846
** end of the opcode array. If we are unable to satisfy all memory
5901559847
** requirements by reusing the opcode array tail, then the second
@@ -59065,10 +59897,11 @@
5906559897
*/
5906659898
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
5906759899
if( pCx==0 ){
5906859900
return;
5906959901
}
59902
+ sqlite3VdbeSorterClose(p->db, pCx);
5907059903
if( pCx->pBt ){
5907159904
sqlite3BtreeClose(pCx->pBt);
5907259905
/* The pCx->pCursor will be close automatically, if it exists, by
5907359906
** the call above. */
5907459907
}else if( pCx->pCursor ){
@@ -61205,10 +62038,18 @@
6120562038
rc = db->errCode = p->rc;
6120662039
}
6120762040
return (rc&db->errMask);
6120862041
}
6120962042
62043
+/*
62044
+** The maximum number of times that a statement will try to reparse
62045
+** itself before giving up and returning SQLITE_SCHEMA.
62046
+*/
62047
+#ifndef SQLITE_MAX_SCHEMA_RETRY
62048
+# define SQLITE_MAX_SCHEMA_RETRY 5
62049
+#endif
62050
+
6121062051
/*
6121162052
** This is the top-level implementation of sqlite3_step(). Call
6121262053
** sqlite3Step() to do most of the work. If a schema error occurs,
6121362054
** call sqlite3Reprepare() and try again.
6121462055
*/
@@ -61223,14 +62064,14 @@
6122362064
return SQLITE_MISUSE_BKPT;
6122462065
}
6122562066
db = v->db;
6122662067
sqlite3_mutex_enter(db->mutex);
6122762068
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
61228
- && cnt++ < 5
62069
+ && cnt++ < SQLITE_MAX_SCHEMA_RETRY
6122962070
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
6123062071
sqlite3_reset(pStmt);
61231
- v->expired = 0;
62072
+ assert( v->expired==0 );
6123262073
}
6123362074
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
6123462075
/* This case occurs after failing to recompile an sql statement.
6123562076
** The error message from the SQL compiler has already been loaded
6123662077
** into the database handle. This block copies the error message
@@ -62357,10 +63198,17 @@
6235763198
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
6235863199
** P if required.
6235963200
*/
6236063201
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
6236163202
63203
+/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
63204
+#ifdef SQLITE_OMIT_MERGE_SORT
63205
+# define isSorter(x) 0
63206
+#else
63207
+# define isSorter(x) ((x)->pSorter!=0)
63208
+#endif
63209
+
6236263210
/*
6236363211
** Argument pMem points at a register that will be passed to a
6236463212
** user-defined function or returned to the user as the result of a query.
6236563213
** This routine sets the pMem->type variable used by the sqlite3_value_*()
6236663214
** routines.
@@ -62951,10 +63799,11 @@
6295163799
u8 *zEndHdr; /* Pointer to first byte after the header */
6295263800
u32 offset; /* Offset into the data */
6295363801
u32 szField; /* Number of bytes in the content of a field */
6295463802
int szHdr; /* Size of the header size field at start of record */
6295563803
int avail; /* Number of bytes of available data */
63804
+ u32 t; /* A type code from the record header */
6295663805
Mem *pReg; /* PseudoTable input register */
6295763806
} am;
6295863807
struct OP_Affinity_stack_vars {
6295963808
const char *zAffinity; /* The affinity to be applied */
6296063809
char cAff; /* A single character of affinity */
@@ -63109,11 +63958,10 @@
6310963958
BtCursor *pCrsr;
6311063959
int res;
6311163960
} bl;
6311263961
struct OP_Next_stack_vars {
6311363962
VdbeCursor *pC;
63114
- BtCursor *pCrsr;
6311563963
int res;
6311663964
} bm;
6311763965
struct OP_IdxInsert_stack_vars {
6311863966
VdbeCursor *pC;
6311963967
BtCursor *pCrsr;
@@ -63363,11 +64211,11 @@
6336364211
if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
6336464212
assert( pOp->p2>0 );
6336564213
assert( pOp->p2<=p->nMem );
6336664214
pOut = &aMem[pOp->p2];
6336764215
memAboutToChange(p, pOut);
63368
- sqlite3VdbeMemReleaseExternal(pOut);
64216
+ MemReleaseExt(pOut);
6336964217
pOut->flags = MEM_Int;
6337064218
}
6337164219
6337264220
/* Sanity checking on other operands */
6337364221
#ifdef SQLITE_DEBUG
@@ -63496,11 +64344,11 @@
6349664344
break;
6349764345
}
6349864346
6349964347
/* Opcode: HaltIfNull P1 P2 P3 P4 *
6350064348
**
63501
-** Check the value in register P3. If is is NULL then Halt using
64349
+** Check the value in register P3. If it is NULL then Halt using
6350264350
** parameter P1, P2, and P4 as if this were a Halt instruction. If the
6350364351
** value in register P3 is not NULL, then this routine is a no-op.
6350464352
*/
6350564353
case OP_HaltIfNull: { /* in3 */
6350664354
pIn3 = &aMem[pOp->p3];
@@ -63730,10 +64578,15 @@
6373064578
assert( memIsValid(pIn1) );
6373164579
memAboutToChange(p, pOut);
6373264580
u.ac.zMalloc = pOut->zMalloc;
6373364581
pOut->zMalloc = 0;
6373464582
sqlite3VdbeMemMove(pOut, pIn1);
64583
+#ifdef SQLITE_DEBUG
64584
+ if( pOut->pScopyFrom>=&aMem[u.ac.p1] && pOut->pScopyFrom<&aMem[u.ac.p1+pOp->p3] ){
64585
+ pOut->pScopyFrom += u.ac.p1 - pOp->p2;
64586
+ }
64587
+#endif
6373564588
pIn1->zMalloc = u.ac.zMalloc;
6373664589
REGISTER_TRACE(u.ac.p2++, pOut);
6373764590
pIn1++;
6373864591
pOut++;
6373964592
}
@@ -64433,11 +65286,11 @@
6443365286
** additional information.
6443465287
**
6443565288
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
6443665289
** true or false and is never NULL. If both operands are NULL then the result
6443765290
** of comparison is false. If either operand is NULL then the result is true.
64438
-** If neither operand is NULL the the result is the same as it would be if
65291
+** If neither operand is NULL the result is the same as it would be if
6443965292
** the SQLITE_NULLEQ flag were omitted from P5.
6444065293
*/
6444165294
/* Opcode: Eq P1 P2 P3 P4 P5
6444265295
**
6444365296
** This works just like the Lt opcode except that the jump is taken if
@@ -64445,11 +65298,11 @@
6444565298
** See the Lt opcode for additional information.
6444665299
**
6444765300
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
6444865301
** true or false and is never NULL. If both operands are NULL then the result
6444965302
** of comparison is true. If either operand is NULL then the result is false.
64450
-** If neither operand is NULL the the result is the same as it would be if
65303
+** If neither operand is NULL the result is the same as it would be if
6445165304
** the SQLITE_NULLEQ flag were omitted from P5.
6445265305
*/
6445365306
/* Opcode: Le P1 P2 P3 P4 P5
6445465307
**
6445565308
** This works just like the Lt opcode except that the jump is taken if
@@ -64730,17 +65583,17 @@
6473065583
break;
6473165584
}
6473265585
6473365586
/* Opcode: If P1 P2 P3 * *
6473465587
**
64735
-** Jump to P2 if the value in register P1 is true. The value is
65588
+** Jump to P2 if the value in register P1 is true. The value
6473665589
** is considered true if it is numeric and non-zero. If the value
6473765590
** in P1 is NULL then take the jump if P3 is true.
6473865591
*/
6473965592
/* Opcode: IfNot P1 P2 P3 * *
6474065593
**
64741
-** Jump to P2 if the value in register P1 is False. The value is
65594
+** Jump to P2 if the value in register P1 is False. The value
6474265595
** is considered true if it has a numeric value of zero. If the value
6474365596
** in P1 is NULL then take the jump if P3 is true.
6474465597
*/
6474565598
case OP_If: /* jump, in1 */
6474665599
case OP_IfNot: { /* jump, in1 */
@@ -64828,10 +65681,11 @@
6482865681
u8 *zEndHdr; /* Pointer to first byte after the header */
6482965682
u32 offset; /* Offset into the data */
6483065683
u32 szField; /* Number of bytes in the content of a field */
6483165684
int szHdr; /* Size of the header size field at start of record */
6483265685
int avail; /* Number of bytes of available data */
65686
+ u32 t; /* A type code from the record header */
6483365687
Mem *pReg; /* PseudoTable input register */
6483465688
#endif /* local variables moved into u.am */
6483565689
6483665690
6483765691
u.am.p1 = pOp->p1;
@@ -64840,11 +65694,10 @@
6484065694
memset(&u.am.sMem, 0, sizeof(u.am.sMem));
6484165695
assert( u.am.p1<p->nCursor );
6484265696
assert( pOp->p3>0 && pOp->p3<=p->nMem );
6484365697
u.am.pDest = &aMem[pOp->p3];
6484465698
memAboutToChange(p, u.am.pDest);
64845
- MemSetTypeFlag(u.am.pDest, MEM_Null);
6484665699
u.am.zRec = 0;
6484765700
6484865701
/* This block sets the variable u.am.payloadSize to be the total number of
6484965702
** bytes in the record.
6485065703
**
@@ -64884,11 +65737,11 @@
6488465737
}else{
6488565738
assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) );
6488665739
rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize);
6488765740
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
6488865741
}
64889
- }else if( u.am.pC->pseudoTableReg>0 ){
65742
+ }else if( ALWAYS(u.am.pC->pseudoTableReg>0) ){
6489065743
u.am.pReg = &aMem[u.am.pC->pseudoTableReg];
6489165744
assert( u.am.pReg->flags & MEM_Blob );
6489265745
assert( memIsValid(u.am.pReg) );
6489365746
u.am.payloadSize = u.am.pReg->n;
6489465747
u.am.zRec = u.am.pReg->z;
@@ -64897,13 +65750,14 @@
6489765750
}else{
6489865751
/* Consider the row to be NULL */
6489965752
u.am.payloadSize = 0;
6490065753
}
6490165754
64902
- /* If u.am.payloadSize is 0, then just store a NULL */
65755
+ /* If u.am.payloadSize is 0, then just store a NULL. This can happen because of
65756
+ ** nullRow or because of a corrupt database. */
6490365757
if( u.am.payloadSize==0 ){
64904
- assert( u.am.pDest->flags&MEM_Null );
65758
+ MemSetTypeFlag(u.am.pDest, MEM_Null);
6490565759
goto op_column_out;
6490665760
}
6490765761
assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
6490865762
if( u.am.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
6490965763
goto too_big;
@@ -65006,12 +65860,18 @@
6500665860
** of the record to the start of the data for the u.am.i-th column
6500765861
*/
6500865862
for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
6500965863
if( u.am.zIdx<u.am.zEndHdr ){
6501065864
u.am.aOffset[u.am.i] = u.am.offset;
65011
- u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]);
65012
- u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]);
65865
+ if( u.am.zIdx[0]<0x80 ){
65866
+ u.am.t = u.am.zIdx[0];
65867
+ u.am.zIdx++;
65868
+ }else{
65869
+ u.am.zIdx += sqlite3GetVarint32(u.am.zIdx, &u.am.t);
65870
+ }
65871
+ u.am.aType[u.am.i] = u.am.t;
65872
+ u.am.szField = sqlite3VdbeSerialTypeLen(u.am.t);
6501365873
u.am.offset += u.am.szField;
6501465874
if( u.am.offset<u.am.szField ){ /* True if u.am.offset overflows */
6501565875
u.am.zIdx = &u.am.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
6501665876
break;
6501765877
}
@@ -65048,11 +65908,11 @@
6504865908
** a pointer to a Mem object.
6504965909
*/
6505065910
if( u.am.aOffset[u.am.p2] ){
6505165911
assert( rc==SQLITE_OK );
6505265912
if( u.am.zRec ){
65053
- sqlite3VdbeMemReleaseExternal(u.am.pDest);
65913
+ MemReleaseExt(u.am.pDest);
6505465914
sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest);
6505565915
}else{
6505665916
u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]);
6505765917
sqlite3VdbeMemMove(&u.am.sMem, u.am.pDest);
6505865918
rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, u.am.aOffset[u.am.p2], u.am.len, u.am.pC->isIndex, &u.am.sMem);
@@ -65065,11 +65925,11 @@
6506565925
u.am.pDest->enc = encoding;
6506665926
}else{
6506765927
if( pOp->p4type==P4_MEM ){
6506865928
sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static);
6506965929
}else{
65070
- assert( u.am.pDest->flags&MEM_Null );
65930
+ MemSetTypeFlag(u.am.pDest, MEM_Null);
6507165931
}
6507265932
}
6507365933
6507465934
/* If we dynamically allocated space to hold the data (in the
6507565935
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
@@ -65267,11 +66127,11 @@
6526766127
i64 nEntry;
6526866128
BtCursor *pCrsr;
6526966129
#endif /* local variables moved into u.ap */
6527066130
6527166131
u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor;
65272
- if( u.ap.pCrsr ){
66132
+ if( ALWAYS(u.ap.pCrsr) ){
6527366133
rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry);
6527466134
}else{
6527566135
u.ap.nEntry = 0;
6527666136
}
6527766137
pOut->u.i = u.ap.nEntry;
@@ -65843,19 +66703,13 @@
6584366703
u.aw.pCur->nullRow = 1;
6584466704
u.aw.pCur->isOrdered = 1;
6584566705
rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor);
6584666706
u.aw.pCur->pKeyInfo = u.aw.pKeyInfo;
6584766707
65848
- /* Since it performs no memory allocation or IO, the only values that
65849
- ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK.
65850
- ** SQLITE_EMPTY is only returned when attempting to open the table
65851
- ** rooted at page 1 of a zero-byte database. */
65852
- assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
65853
- if( rc==SQLITE_EMPTY ){
65854
- u.aw.pCur->pCursor = 0;
65855
- rc = SQLITE_OK;
65856
- }
66708
+ /* Since it performs no memory allocation or IO, the only value that
66709
+ ** sqlite3BtreeCursor() may return is SQLITE_OK. */
66710
+ assert( rc==SQLITE_OK );
6585766711
6585866712
/* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
6585966713
** SQLite used to check if the root-page flags were sane at this point
6586066714
** and report database corruption if they were not, but this check has
6586166715
** since moved into the btree layer. */
@@ -65862,11 +66716,11 @@
6586266716
u.aw.pCur->isTable = pOp->p4type!=P4_KEYINFO;
6586366717
u.aw.pCur->isIndex = !u.aw.pCur->isTable;
6586466718
break;
6586566719
}
6586666720
65867
-/* Opcode: OpenEphemeral P1 P2 * P4 *
66721
+/* Opcode: OpenEphemeral P1 P2 * P4 P5
6586866722
**
6586966723
** Open a new cursor P1 to a transient table.
6587066724
** The cursor is always opened read/write even if
6587166725
** the main database is read-only. The ephemeral
6587266726
** table is deleted automatically when the cursor is closed.
@@ -65879,18 +66733,30 @@
6587966733
** This opcode was once called OpenTemp. But that created
6588066734
** confusion because the term "temp table", might refer either
6588166735
** to a TEMP table at the SQL level, or to a table opened by
6588266736
** this opcode. Then this opcode was call OpenVirtual. But
6588366737
** that created confusion with the whole virtual-table idea.
66738
+**
66739
+** The P5 parameter can be a mask of the BTREE_* flags defined
66740
+** in btree.h. These flags control aspects of the operation of
66741
+** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
66742
+** added automatically.
6588466743
*/
6588566744
/* Opcode: OpenAutoindex P1 P2 * P4 *
6588666745
**
6588766746
** This opcode works the same as OP_OpenEphemeral. It has a
6588866747
** different name to distinguish its use. Tables created using
6588966748
** by this opcode will be used for automatically created transient
6589066749
** indices in joins.
6589166750
*/
66751
+/* Opcode: OpenSorter P1 P2 * P4 *
66752
+**
66753
+** This opcode works like OP_OpenEphemeral except that it opens
66754
+** a transient index that is specifically designed to sort large
66755
+** tables using an external merge-sort algorithm.
66756
+*/
66757
+case OP_OpenSorter:
6589266758
case OP_OpenAutoindex:
6589366759
case OP_OpenEphemeral: {
6589466760
#if 0 /* local variables moved into u.ax */
6589566761
VdbeCursor *pCx;
6589666762
#endif /* local variables moved into u.ax */
@@ -65900,10 +66766,11 @@
6590066766
SQLITE_OPEN_EXCLUSIVE |
6590166767
SQLITE_OPEN_DELETEONCLOSE |
6590266768
SQLITE_OPEN_TRANSIENT_DB;
6590366769
6590466770
assert( pOp->p1>=0 );
66771
+ assert( (pOp->opcode==OP_OpenSorter)==((pOp->p5 & BTREE_SORTER)!=0) );
6590566772
u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
6590666773
if( u.ax.pCx==0 ) goto no_mem;
6590766774
u.ax.pCx->nullRow = 1;
6590866775
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
6590966776
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
@@ -65917,11 +66784,11 @@
6591766784
** automatically created table with root-page 1 (an BLOB_INTKEY table).
6591866785
*/
6591966786
if( pOp->p4.pKeyInfo ){
6592066787
int pgno;
6592166788
assert( pOp->p4type==P4_KEYINFO );
65922
- rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY);
66789
+ rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
6592366790
if( rc==SQLITE_OK ){
6592466791
assert( pgno==MASTER_ROOT+1 );
6592566792
rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
6592666793
(KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
6592766794
u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
@@ -65933,10 +66800,15 @@
6593366800
u.ax.pCx->isTable = 1;
6593466801
}
6593566802
}
6593666803
u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
6593766804
u.ax.pCx->isIndex = !u.ax.pCx->isTable;
66805
+#ifndef SQLITE_OMIT_MERGE_SORT
66806
+ if( rc==SQLITE_OK && pOp->opcode==OP_OpenSorter ){
66807
+ rc = sqlite3VdbeSorterInit(db, u.ax.pCx);
66808
+ }
66809
+#endif
6593866810
break;
6593966811
}
6594066812
6594166813
/* Opcode: OpenPseudo P1 P2 P3 * *
6594266814
**
@@ -66052,11 +66924,11 @@
6605266924
assert( u.az.pC->pseudoTableReg==0 );
6605366925
assert( OP_SeekLe == OP_SeekLt+1 );
6605466926
assert( OP_SeekGe == OP_SeekLt+2 );
6605566927
assert( OP_SeekGt == OP_SeekLt+3 );
6605666928
assert( u.az.pC->isOrdered );
66057
- if( u.az.pC->pCursor!=0 ){
66929
+ if( ALWAYS(u.az.pC->pCursor!=0) ){
6605866930
u.az.oc = pOp->opcode;
6605966931
u.az.pC->nullRow = 0;
6606066932
if( u.az.pC->isTable ){
6606166933
/* The input value in P3 might be of any type: integer, real, string,
6606266934
** blob, or NULL. But it needs to be an integer before we can do
@@ -66390,11 +67262,11 @@
6639067262
break;
6639167263
}
6639267264
6639367265
/* Opcode: NotExists P1 P2 P3 * *
6639467266
**
66395
-** Use the content of register P3 as a integer key. If a record
67267
+** Use the content of register P3 as an integer key. If a record
6639667268
** with that key does not exist in table of P1, then jump to P2.
6639767269
** If the record does exist, then fall through. The cursor is left
6639867270
** pointing to the record if it exists.
6639967271
**
6640067272
** The difference between this operation and NotFound is that this
@@ -66418,11 +67290,11 @@
6641867290
u.bd.pC = p->apCsr[pOp->p1];
6641967291
assert( u.bd.pC!=0 );
6642067292
assert( u.bd.pC->isTable );
6642167293
assert( u.bd.pC->pseudoTableReg==0 );
6642267294
u.bd.pCrsr = u.bd.pC->pCursor;
66423
- if( u.bd.pCrsr!=0 ){
67295
+ if( ALWAYS(u.bd.pCrsr!=0) ){
6642467296
u.bd.res = 0;
6642567297
u.bd.iKey = pIn3->u.i;
6642667298
rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res);
6642767299
u.bd.pC->lastRowid = pIn3->u.i;
6642867300
u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0;
@@ -66468,11 +67340,11 @@
6646867340
** written to register P2.
6646967341
**
6647067342
** If P3>0 then P3 is a register in the root frame of this VDBE that holds
6647167343
** the largest previously generated record number. No new record numbers are
6647267344
** allowed to be less than this value. When this value reaches its maximum,
66473
-** a SQLITE_FULL error is generated. The P3 register is updated with the '
67345
+** an SQLITE_FULL error is generated. The P3 register is updated with the '
6647467346
** generated record number. This P3 mechanism is used to help implement the
6647567347
** AUTOINCREMENT feature.
6647667348
*/
6647767349
case OP_NewRowid: { /* out2-prerelease */
6647867350
#if 0 /* local variables moved into u.be */
@@ -66842,10 +67714,17 @@
6684267714
assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey );
6684367715
assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData );
6684467716
assert( u.bh.pC!=0 );
6684567717
assert( u.bh.pC->nullRow==0 );
6684667718
assert( u.bh.pC->pseudoTableReg==0 );
67719
+
67720
+ if( isSorter(u.bh.pC) ){
67721
+ assert( pOp->opcode==OP_RowKey );
67722
+ rc = sqlite3VdbeSorterRowkey(u.bh.pC, pOut);
67723
+ break;
67724
+ }
67725
+
6684767726
assert( u.bh.pC->pCursor!=0 );
6684867727
u.bh.pCrsr = u.bh.pC->pCursor;
6684967728
assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) );
6685067729
6685167730
/* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
@@ -66950,10 +67829,11 @@
6695067829
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
6695167830
u.bj.pC = p->apCsr[pOp->p1];
6695267831
assert( u.bj.pC!=0 );
6695367832
u.bj.pC->nullRow = 1;
6695467833
u.bj.pC->rowidIsValid = 0;
67834
+ assert( u.bj.pC->pCursor || u.bj.pC->pVtabCursor );
6695567835
if( u.bj.pC->pCursor ){
6695667836
sqlite3BtreeClearCursor(u.bj.pC->pCursor);
6695767837
}
6695867838
break;
6695967839
}
@@ -66975,11 +67855,11 @@
6697567855
6697667856
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
6697767857
u.bk.pC = p->apCsr[pOp->p1];
6697867858
assert( u.bk.pC!=0 );
6697967859
u.bk.pCrsr = u.bk.pC->pCursor;
66980
- if( u.bk.pCrsr==0 ){
67860
+ if( NEVER(u.bk.pCrsr==0) ){
6698167861
u.bk.res = 1;
6698267862
}else{
6698367863
rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res);
6698467864
}
6698567865
u.bk.pC->nullRow = (u8)u.bk.res;
@@ -67030,11 +67910,15 @@
6703067910
6703167911
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
6703267912
u.bl.pC = p->apCsr[pOp->p1];
6703367913
assert( u.bl.pC!=0 );
6703467914
u.bl.res = 1;
67035
- if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){
67915
+ if( isSorter(u.bl.pC) ){
67916
+ rc = sqlite3VdbeSorterRewind(db, u.bl.pC, &u.bl.res);
67917
+ }else{
67918
+ u.bl.pCrsr = u.bl.pC->pCursor;
67919
+ assert( u.bl.pCrsr );
6703667920
rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
6703767921
u.bl.pC->atFirst = u.bl.res==0 ?1:0;
6703867922
u.bl.pC->deferredMoveto = 0;
6703967923
u.bl.pC->cacheStatus = CACHE_STALE;
6704067924
u.bl.pC->rowidIsValid = 0;
@@ -67045,18 +67929,21 @@
6704567929
pc = pOp->p2 - 1;
6704667930
}
6704767931
break;
6704867932
}
6704967933
67050
-/* Opcode: Next P1 P2 * * P5
67934
+/* Opcode: Next P1 P2 * P4 P5
6705167935
**
6705267936
** Advance cursor P1 so that it points to the next key/data pair in its
6705367937
** table or index. If there are no more key/value pairs then fall through
6705467938
** to the following instruction. But if the cursor advance was successful,
6705567939
** jump immediately to P2.
6705667940
**
6705767941
** The P1 cursor must be for a real table, not a pseudo-table.
67942
+**
67943
+** P4 is always of type P4_ADVANCE. The function pointer points to
67944
+** sqlite3BtreeNext().
6705867945
**
6705967946
** If P5 is positive and the jump is taken, then event counter
6706067947
** number P5-1 in the prepared statement is incremented.
6706167948
**
6706267949
** See also: Prev
@@ -67067,19 +67954,21 @@
6706767954
** table or index. If there is no previous key/value pairs then fall through
6706867955
** to the following instruction. But if the cursor backup was successful,
6706967956
** jump immediately to P2.
6707067957
**
6707167958
** The P1 cursor must be for a real table, not a pseudo-table.
67959
+**
67960
+** P4 is always of type P4_ADVANCE. The function pointer points to
67961
+** sqlite3BtreePrevious().
6707267962
**
6707367963
** If P5 is positive and the jump is taken, then event counter
6707467964
** number P5-1 in the prepared statement is incremented.
6707567965
*/
6707667966
case OP_Prev: /* jump */
6707767967
case OP_Next: { /* jump */
6707867968
#if 0 /* local variables moved into u.bm */
6707967969
VdbeCursor *pC;
67080
- BtCursor *pCrsr;
6708167970
int res;
6708267971
#endif /* local variables moved into u.bm */
6708367972
6708467973
CHECK_FOR_INTERRUPT;
6708567974
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -67086,19 +67975,21 @@
6708667975
assert( pOp->p5<=ArraySize(p->aCounter) );
6708767976
u.bm.pC = p->apCsr[pOp->p1];
6708867977
if( u.bm.pC==0 ){
6708967978
break; /* See ticket #2273 */
6709067979
}
67091
- u.bm.pCrsr = u.bm.pC->pCursor;
67092
- if( u.bm.pCrsr==0 ){
67093
- u.bm.pC->nullRow = 1;
67094
- break;
67095
- }
67096
- u.bm.res = 1;
67097
- assert( u.bm.pC->deferredMoveto==0 );
67098
- rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(u.bm.pCrsr, &u.bm.res) :
67099
- sqlite3BtreePrevious(u.bm.pCrsr, &u.bm.res);
67980
+ if( isSorter(u.bm.pC) ){
67981
+ assert( pOp->opcode==OP_Next );
67982
+ rc = sqlite3VdbeSorterNext(db, u.bm.pC, &u.bm.res);
67983
+ }else{
67984
+ u.bm.res = 1;
67985
+ assert( u.bm.pC->deferredMoveto==0 );
67986
+ assert( u.bm.pC->pCursor );
67987
+ assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
67988
+ assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
67989
+ rc = pOp->p4.xAdvance(u.bm.pC->pCursor, &u.bm.res);
67990
+ }
6710067991
u.bm.pC->nullRow = (u8)u.bm.res;
6710167992
u.bm.pC->cacheStatus = CACHE_STALE;
6710267993
if( u.bm.res==0 ){
6710367994
pc = pOp->p2 - 1;
6710467995
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
@@ -67110,11 +68001,11 @@
6711068001
break;
6711168002
}
6711268003
6711368004
/* Opcode: IdxInsert P1 P2 P3 * P5
6711468005
**
67115
-** Register P2 holds a SQL index key made using the
68006
+** Register P2 holds an SQL index key made using the
6711668007
** MakeRecord instructions. This opcode writes that key
6711768008
** into the index P1. Data for the entry is nil.
6711868009
**
6711968010
** P3 is a flag that provides a hint to the b-tree layer that this
6712068011
** insert is likely to be an append.
@@ -67140,14 +68031,17 @@
6714068031
assert( u.bn.pC->isTable==0 );
6714168032
rc = ExpandBlob(pIn2);
6714268033
if( rc==SQLITE_OK ){
6714368034
u.bn.nKey = pIn2->n;
6714468035
u.bn.zKey = pIn2->z;
67145
- rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
67146
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
67147
- );
67148
- assert( u.bn.pC->deferredMoveto==0 );
68036
+ rc = sqlite3VdbeSorterWrite(db, u.bn.pC, u.bn.nKey);
68037
+ if( rc==SQLITE_OK ){
68038
+ rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
68039
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
68040
+ );
68041
+ assert( u.bn.pC->deferredMoveto==0 );
68042
+ }
6714968043
u.bn.pC->cacheStatus = CACHE_STALE;
6715068044
}
6715168045
}
6715268046
break;
6715368047
}
@@ -69323,10 +70217,722 @@
6932370217
}
6932470218
6932570219
#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
6932670220
6932770221
/************** End of vdbeblob.c ********************************************/
70222
+/************** Begin file vdbesort.c ****************************************/
70223
+/*
70224
+** 2011 July 9
70225
+**
70226
+** The author disclaims copyright to this source code. In place of
70227
+** a legal notice, here is a blessing:
70228
+**
70229
+** May you do good and not evil.
70230
+** May you find forgiveness for yourself and forgive others.
70231
+** May you share freely, never taking more than you give.
70232
+**
70233
+*************************************************************************
70234
+** This file contains code for the VdbeSorter object, used in concert with
70235
+** a VdbeCursor to sort large numbers of keys (as may be required, for
70236
+** example, by CREATE INDEX statements on tables too large to fit in main
70237
+** memory).
70238
+*/
70239
+
70240
+
70241
+#ifndef SQLITE_OMIT_MERGE_SORT
70242
+
70243
+typedef struct VdbeSorterIter VdbeSorterIter;
70244
+
70245
+/*
70246
+** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
70247
+**
70248
+** As keys are added to the sorter, they are written to disk in a series
70249
+** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly
70250
+** the same as the cache-size allowed for temporary databases. In order
70251
+** to allow the caller to extract keys from the sorter in sorted order,
70252
+** all PMAs currently stored on disk must be merged together. This comment
70253
+** describes the data structure used to do so. The structure supports
70254
+** merging any number of arrays in a single pass with no redundant comparison
70255
+** operations.
70256
+**
70257
+** The aIter[] array contains an iterator for each of the PMAs being merged.
70258
+** An aIter[] iterator either points to a valid key or else is at EOF. For
70259
+** the purposes of the paragraphs below, we assume that the array is actually
70260
+** N elements in size, where N is the smallest power of 2 greater to or equal
70261
+** to the number of iterators being merged. The extra aIter[] elements are
70262
+** treated as if they are empty (always at EOF).
70263
+**
70264
+** The aTree[] array is also N elements in size. The value of N is stored in
70265
+** the VdbeSorter.nTree variable.
70266
+**
70267
+** The final (N/2) elements of aTree[] contain the results of comparing
70268
+** pairs of iterator keys together. Element i contains the result of
70269
+** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the
70270
+** aTree element is set to the index of it.
70271
+**
70272
+** For the purposes of this comparison, EOF is considered greater than any
70273
+** other key value. If the keys are equal (only possible with two EOF
70274
+** values), it doesn't matter which index is stored.
70275
+**
70276
+** The (N/4) elements of aTree[] that preceed the final (N/2) described
70277
+** above contains the index of the smallest of each block of 4 iterators.
70278
+** And so on. So that aTree[1] contains the index of the iterator that
70279
+** currently points to the smallest key value. aTree[0] is unused.
70280
+**
70281
+** Example:
70282
+**
70283
+** aIter[0] -> Banana
70284
+** aIter[1] -> Feijoa
70285
+** aIter[2] -> Elderberry
70286
+** aIter[3] -> Currant
70287
+** aIter[4] -> Grapefruit
70288
+** aIter[5] -> Apple
70289
+** aIter[6] -> Durian
70290
+** aIter[7] -> EOF
70291
+**
70292
+** aTree[] = { X, 5 0, 5 0, 3, 5, 6 }
70293
+**
70294
+** The current element is "Apple" (the value of the key indicated by
70295
+** iterator 5). When the Next() operation is invoked, iterator 5 will
70296
+** be advanced to the next key in its segment. Say the next key is
70297
+** "Eggplant":
70298
+**
70299
+** aIter[5] -> Eggplant
70300
+**
70301
+** The contents of aTree[] are updated first by comparing the new iterator
70302
+** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator
70303
+** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
70304
+** The value of iterator 6 - "Durian" - is now smaller than that of iterator
70305
+** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Banana<Durian),
70306
+** so the value written into element 1 of the array is 0. As follows:
70307
+**
70308
+** aTree[] = { X, 0 0, 6 0, 3, 5, 6 }
70309
+**
70310
+** In other words, each time we advance to the next sorter element, log2(N)
70311
+** key comparison operations are required, where N is the number of segments
70312
+** being merged (rounded up to the next power of 2).
70313
+*/
70314
+struct VdbeSorter {
70315
+ int nWorking; /* Start a new b-tree after this many pages */
70316
+ int nBtree; /* Current size of b-tree contents as PMA */
70317
+ int nTree; /* Used size of aTree/aIter (power of 2) */
70318
+ VdbeSorterIter *aIter; /* Array of iterators to merge */
70319
+ int *aTree; /* Current state of incremental merge */
70320
+ i64 iWriteOff; /* Current write offset within file pTemp1 */
70321
+ i64 iReadOff; /* Current read offset within file pTemp1 */
70322
+ sqlite3_file *pTemp1; /* PMA file 1 */
70323
+ int nPMA; /* Number of PMAs stored in pTemp1 */
70324
+};
70325
+
70326
+/*
70327
+** The following type is an iterator for a PMA. It caches the current key in
70328
+** variables nKey/aKey. If the iterator is at EOF, pFile==0.
70329
+*/
70330
+struct VdbeSorterIter {
70331
+ i64 iReadOff; /* Current read offset */
70332
+ i64 iEof; /* 1 byte past EOF for this iterator */
70333
+ sqlite3_file *pFile; /* File iterator is reading from */
70334
+ int nAlloc; /* Bytes of space at aAlloc */
70335
+ u8 *aAlloc; /* Allocated space */
70336
+ int nKey; /* Number of bytes in key */
70337
+ u8 *aKey; /* Pointer to current key */
70338
+};
70339
+
70340
+/* Minimum allowable value for the VdbeSorter.nWorking variable */
70341
+#define SORTER_MIN_WORKING 10
70342
+
70343
+/* Maximum number of segments to merge in a single pass. */
70344
+#define SORTER_MAX_MERGE_COUNT 16
70345
+
70346
+/*
70347
+** Free all memory belonging to the VdbeSorterIter object passed as the second
70348
+** argument. All structure fields are set to zero before returning.
70349
+*/
70350
+static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
70351
+ sqlite3DbFree(db, pIter->aAlloc);
70352
+ memset(pIter, 0, sizeof(VdbeSorterIter));
70353
+}
70354
+
70355
+/*
70356
+** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
70357
+** no error occurs, or an SQLite error code if one does.
70358
+*/
70359
+static int vdbeSorterIterNext(
70360
+ sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */
70361
+ VdbeSorterIter *pIter /* Iterator to advance */
70362
+){
70363
+ int rc; /* Return Code */
70364
+ int nRead; /* Number of bytes read */
70365
+ int nRec; /* Size of record in bytes */
70366
+ int iOff; /* Size of serialized size varint in bytes */
70367
+
70368
+ nRead = pIter->iEof - pIter->iReadOff;
70369
+ if( nRead>5 ) nRead = 5;
70370
+ if( nRead<=0 ){
70371
+ /* This is an EOF condition */
70372
+ vdbeSorterIterZero(db, pIter);
70373
+ return SQLITE_OK;
70374
+ }
70375
+
70376
+ rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
70377
+ iOff = getVarint32(pIter->aAlloc, nRec);
70378
+
70379
+ if( rc==SQLITE_OK && (iOff+nRec)>nRead ){
70380
+ int nRead2; /* Number of extra bytes to read */
70381
+ if( (iOff+nRec)>pIter->nAlloc ){
70382
+ int nNew = pIter->nAlloc*2;
70383
+ while( (iOff+nRec)>nNew ) nNew = nNew*2;
70384
+ pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
70385
+ if( !pIter->aAlloc ) return SQLITE_NOMEM;
70386
+ pIter->nAlloc = nNew;
70387
+ }
70388
+
70389
+ nRead2 = iOff + nRec - nRead;
70390
+ rc = sqlite3OsRead(
70391
+ pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
70392
+ );
70393
+ }
70394
+
70395
+ assert( nRec>0 || rc!=SQLITE_OK );
70396
+ pIter->iReadOff += iOff+nRec;
70397
+ pIter->nKey = nRec;
70398
+ pIter->aKey = &pIter->aAlloc[iOff];
70399
+ return rc;
70400
+}
70401
+
70402
+/*
70403
+** Write a single varint, value iVal, to file-descriptor pFile. Return
70404
+** SQLITE_OK if successful, or an SQLite error code if some error occurs.
70405
+**
70406
+** The value of *piOffset when this function is called is used as the byte
70407
+** offset in file pFile to write to. Before returning, *piOffset is
70408
+** incremented by the number of bytes written.
70409
+*/
70410
+static int vdbeSorterWriteVarint(
70411
+ sqlite3_file *pFile, /* File to write to */
70412
+ i64 iVal, /* Value to write as a varint */
70413
+ i64 *piOffset /* IN/OUT: Write offset in file pFile */
70414
+){
70415
+ u8 aVarint[9]; /* Buffer large enough for a varint */
70416
+ int nVarint; /* Number of used bytes in varint */
70417
+ int rc; /* Result of write() call */
70418
+
70419
+ nVarint = sqlite3PutVarint(aVarint, iVal);
70420
+ rc = sqlite3OsWrite(pFile, aVarint, nVarint, *piOffset);
70421
+ *piOffset += nVarint;
70422
+
70423
+ return rc;
70424
+}
70425
+
70426
+/*
70427
+** Read a single varint from file-descriptor pFile. Return SQLITE_OK if
70428
+** successful, or an SQLite error code if some error occurs.
70429
+**
70430
+** The value of *piOffset when this function is called is used as the
70431
+** byte offset in file pFile from whence to read the varint. If successful
70432
+** (i.e. if no IO error occurs), then *piOffset is set to the offset of
70433
+** the first byte past the end of the varint before returning. *piVal is
70434
+** set to the integer value read. If an error occurs, the final values of
70435
+** both *piOffset and *piVal are undefined.
70436
+*/
70437
+static int vdbeSorterReadVarint(
70438
+ sqlite3_file *pFile, /* File to read from */
70439
+ i64 iEof, /* Total number of bytes in file */
70440
+ i64 *piOffset, /* IN/OUT: Read offset in pFile */
70441
+ i64 *piVal /* OUT: Value read from file */
70442
+){
70443
+ u8 aVarint[9]; /* Buffer large enough for a varint */
70444
+ i64 iOff = *piOffset; /* Offset in file to read from */
70445
+ int nRead = 9; /* Number of bytes to read from file */
70446
+ int rc; /* Return code */
70447
+
70448
+ assert( iEof>iOff );
70449
+ if( (iEof-iOff)<nRead ){
70450
+ nRead = iEof-iOff;
70451
+ }
70452
+
70453
+ rc = sqlite3OsRead(pFile, aVarint, nRead, iOff);
70454
+ if( rc==SQLITE_OK ){
70455
+ *piOffset += getVarint(aVarint, (u64 *)piVal);
70456
+ }
70457
+
70458
+ return rc;
70459
+}
70460
+
70461
+/*
70462
+** Initialize iterator pIter to scan through the PMA stored in file pFile
70463
+** starting at offset iStart and ending at offset iEof-1. This function
70464
+** leaves the iterator pointing to the first key in the PMA (or EOF if the
70465
+** PMA is empty).
70466
+*/
70467
+static int vdbeSorterIterInit(
70468
+ sqlite3 *db, /* Database handle */
70469
+ VdbeSorter *pSorter, /* Sorter object */
70470
+ i64 iStart, /* Start offset in pFile */
70471
+ VdbeSorterIter *pIter, /* Iterator to populate */
70472
+ i64 *pnByte /* IN/OUT: Increment this value by PMA size */
70473
+){
70474
+ int rc;
70475
+
70476
+ assert( pSorter->iWriteOff>iStart );
70477
+ assert( pIter->aAlloc==0 );
70478
+ pIter->pFile = pSorter->pTemp1;
70479
+ pIter->iReadOff = iStart;
70480
+ pIter->nAlloc = 128;
70481
+ pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
70482
+ if( !pIter->aAlloc ){
70483
+ rc = SQLITE_NOMEM;
70484
+ }else{
70485
+ i64 iEof = pSorter->iWriteOff; /* EOF of file pSorter->pTemp1 */
70486
+ i64 nByte; /* Total size of PMA in bytes */
70487
+ rc = vdbeSorterReadVarint(pSorter->pTemp1, iEof, &pIter->iReadOff, &nByte);
70488
+ *pnByte += nByte;
70489
+ pIter->iEof = pIter->iReadOff + nByte;
70490
+ }
70491
+ if( rc==SQLITE_OK ){
70492
+ rc = vdbeSorterIterNext(db, pIter);
70493
+ }
70494
+ return rc;
70495
+}
70496
+
70497
+/*
70498
+** This function is called to compare two iterator keys when merging
70499
+** multiple b-tree segments. Parameter iOut is the index of the aTree[]
70500
+** value to recalculate.
70501
+*/
70502
+static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
70503
+ VdbeSorter *pSorter = pCsr->pSorter;
70504
+ int i1;
70505
+ int i2;
70506
+ int iRes;
70507
+ VdbeSorterIter *p1;
70508
+ VdbeSorterIter *p2;
70509
+
70510
+ assert( iOut<pSorter->nTree && iOut>0 );
70511
+
70512
+ if( iOut>=(pSorter->nTree/2) ){
70513
+ i1 = (iOut - pSorter->nTree/2) * 2;
70514
+ i2 = i1 + 1;
70515
+ }else{
70516
+ i1 = pSorter->aTree[iOut*2];
70517
+ i2 = pSorter->aTree[iOut*2+1];
70518
+ }
70519
+
70520
+ p1 = &pSorter->aIter[i1];
70521
+ p2 = &pSorter->aIter[i2];
70522
+
70523
+ if( p1->pFile==0 ){
70524
+ iRes = i2;
70525
+ }else if( p2->pFile==0 ){
70526
+ iRes = i1;
70527
+ }else{
70528
+ char aSpace[150];
70529
+ UnpackedRecord *r1;
70530
+
70531
+ r1 = sqlite3VdbeRecordUnpack(
70532
+ pCsr->pKeyInfo, p1->nKey, p1->aKey, aSpace, sizeof(aSpace)
70533
+ );
70534
+ if( r1==0 ) return SQLITE_NOMEM;
70535
+
70536
+ if( sqlite3VdbeRecordCompare(p2->nKey, p2->aKey, r1)>=0 ){
70537
+ iRes = i1;
70538
+ }else{
70539
+ iRes = i2;
70540
+ }
70541
+ sqlite3VdbeDeleteUnpackedRecord(r1);
70542
+ }
70543
+
70544
+ pSorter->aTree[iOut] = iRes;
70545
+ return SQLITE_OK;
70546
+}
70547
+
70548
+/*
70549
+** Initialize the temporary index cursor just opened as a sorter cursor.
70550
+*/
70551
+SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
70552
+ assert( pCsr->pKeyInfo && pCsr->pBt );
70553
+ pCsr->pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
70554
+ return (pCsr->pSorter ? SQLITE_OK : SQLITE_NOMEM);
70555
+}
70556
+
70557
+/*
70558
+** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
70559
+*/
70560
+SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
70561
+ VdbeSorter *pSorter = pCsr->pSorter;
70562
+ if( pSorter ){
70563
+ if( pSorter->aIter ){
70564
+ int i;
70565
+ for(i=0; i<pSorter->nTree; i++){
70566
+ vdbeSorterIterZero(db, &pSorter->aIter[i]);
70567
+ }
70568
+ sqlite3DbFree(db, pSorter->aIter);
70569
+ }
70570
+ if( pSorter->pTemp1 ){
70571
+ sqlite3OsCloseFree(pSorter->pTemp1);
70572
+ }
70573
+ sqlite3DbFree(db, pSorter);
70574
+ pCsr->pSorter = 0;
70575
+ }
70576
+}
70577
+
70578
+/*
70579
+** Allocate space for a file-handle and open a temporary file. If successful,
70580
+** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK.
70581
+** Otherwise, set *ppFile to 0 and return an SQLite error code.
70582
+*/
70583
+static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
70584
+ int dummy;
70585
+ return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
70586
+ SQLITE_OPEN_TEMP_JOURNAL |
70587
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
70588
+ SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy
70589
+ );
70590
+}
70591
+
70592
+
70593
+/*
70594
+** Write the current contents of the b-tree to a PMA. Return SQLITE_OK
70595
+** if successful, or an SQLite error code otherwise.
70596
+**
70597
+** The format of a PMA is:
70598
+**
70599
+** * A varint. This varint contains the total number of bytes of content
70600
+** in the PMA (not including the varint itself).
70601
+**
70602
+** * One or more records packed end-to-end in order of ascending keys.
70603
+** Each record consists of a varint followed by a blob of data (the
70604
+** key). The varint is the number of bytes in the blob of data.
70605
+*/
70606
+static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){
70607
+ int rc = SQLITE_OK; /* Return code */
70608
+ VdbeSorter *pSorter = pCsr->pSorter;
70609
+ int res = 0;
70610
+
70611
+ /* sqlite3BtreeFirst() cannot fail because sorter btrees are always held
70612
+ ** in memory and so an I/O error is not possible. */
70613
+ rc = sqlite3BtreeFirst(pCsr->pCursor, &res);
70614
+ if( NEVER(rc!=SQLITE_OK) || res ) return rc;
70615
+ assert( pSorter->nBtree>0 );
70616
+
70617
+ /* If the first temporary PMA file has not been opened, open it now. */
70618
+ if( pSorter->pTemp1==0 ){
70619
+ rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
70620
+ assert( rc!=SQLITE_OK || pSorter->pTemp1 );
70621
+ assert( pSorter->iWriteOff==0 );
70622
+ assert( pSorter->nPMA==0 );
70623
+ }
70624
+
70625
+ if( rc==SQLITE_OK ){
70626
+ i64 iWriteOff = pSorter->iWriteOff;
70627
+ void *aMalloc = 0; /* Array used to hold a single record */
70628
+ int nMalloc = 0; /* Allocated size of aMalloc[] in bytes */
70629
+
70630
+ pSorter->nPMA++;
70631
+ for(
70632
+ rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nBtree, &iWriteOff);
70633
+ rc==SQLITE_OK && res==0;
70634
+ rc = sqlite3BtreeNext(pCsr->pCursor, &res)
70635
+ ){
70636
+ i64 nKey; /* Size of this key in bytes */
70637
+
70638
+ /* Write the size of the record in bytes to the output file */
70639
+ (void)sqlite3BtreeKeySize(pCsr->pCursor, &nKey);
70640
+ rc = vdbeSorterWriteVarint(pSorter->pTemp1, nKey, &iWriteOff);
70641
+
70642
+ /* Make sure the aMalloc[] buffer is large enough for the record */
70643
+ if( rc==SQLITE_OK && nKey>nMalloc ){
70644
+ aMalloc = sqlite3DbReallocOrFree(db, aMalloc, nKey);
70645
+ if( !aMalloc ){
70646
+ rc = SQLITE_NOMEM;
70647
+ }else{
70648
+ nMalloc = nKey;
70649
+ }
70650
+ }
70651
+
70652
+ /* Write the record itself to the output file */
70653
+ if( rc==SQLITE_OK ){
70654
+ /* sqlite3BtreeKey() cannot fail because sorter btrees held in memory */
70655
+ rc = sqlite3BtreeKey(pCsr->pCursor, 0, nKey, aMalloc);
70656
+ if( ALWAYS(rc==SQLITE_OK) ){
70657
+ rc = sqlite3OsWrite(pSorter->pTemp1, aMalloc, nKey, iWriteOff);
70658
+ iWriteOff += nKey;
70659
+ }
70660
+ }
70661
+
70662
+ if( rc!=SQLITE_OK ) break;
70663
+ }
70664
+
70665
+ /* This assert verifies that unless an error has occurred, the size of
70666
+ ** the PMA on disk is the same as the expected size stored in
70667
+ ** pSorter->nBtree. */
70668
+ assert( rc!=SQLITE_OK || pSorter->nBtree==(
70669
+ iWriteOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nBtree)
70670
+ ));
70671
+
70672
+ pSorter->iWriteOff = iWriteOff;
70673
+ sqlite3DbFree(db, aMalloc);
70674
+ }
70675
+
70676
+ pSorter->nBtree = 0;
70677
+ return rc;
70678
+}
70679
+
70680
+/*
70681
+** This function is called on a sorter cursor by the VDBE before each row
70682
+** is inserted into VdbeCursor.pCsr. Argument nKey is the size of the key, in
70683
+** bytes, about to be inserted.
70684
+**
70685
+** If it is determined that the temporary b-tree accessed via VdbeCursor.pCsr
70686
+** is large enough, its contents are written to a sorted PMA on disk and the
70687
+** tree emptied. This prevents the b-tree (which must be small enough to
70688
+** fit entirely in the cache in order to support efficient inserts) from
70689
+** growing too large.
70690
+**
70691
+** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK.
70692
+*/
70693
+SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *db, VdbeCursor *pCsr, int nKey){
70694
+ int rc = SQLITE_OK; /* Return code */
70695
+ VdbeSorter *pSorter = pCsr->pSorter;
70696
+ if( pSorter ){
70697
+ Pager *pPager = sqlite3BtreePager(pCsr->pBt);
70698
+ int nPage; /* Current size of temporary file in pages */
70699
+
70700
+ /* Sorters never spill to disk */
70701
+ assert( sqlite3PagerFile(pPager)->pMethods==0 );
70702
+
70703
+ /* Determine how many pages the temporary b-tree has grown to */
70704
+ sqlite3PagerPagecount(pPager, &nPage);
70705
+
70706
+ /* If pSorter->nWorking is still zero, but the temporary file has been
70707
+ ** created in the file-system, then the most recent insert into the
70708
+ ** current b-tree segment probably caused the cache to overflow (it is
70709
+ ** also possible that sqlite3_release_memory() was called). So set the
70710
+ ** size of the working set to a little less than the current size of the
70711
+ ** file in pages. */
70712
+ if( pSorter->nWorking==0 && sqlite3PagerUnderStress(pPager) ){
70713
+ pSorter->nWorking = nPage-5;
70714
+ if( pSorter->nWorking<SORTER_MIN_WORKING ){
70715
+ pSorter->nWorking = SORTER_MIN_WORKING;
70716
+ }
70717
+ }
70718
+
70719
+ /* If the number of pages used by the current b-tree segment is greater
70720
+ ** than the size of the working set (VdbeSorter.nWorking), start a new
70721
+ ** segment b-tree. */
70722
+ if( pSorter->nWorking && nPage>=pSorter->nWorking ){
70723
+ BtCursor *p = pCsr->pCursor;/* Cursor structure to close and reopen */
70724
+ int iRoot; /* Root page of new tree */
70725
+
70726
+ /* Copy the current contents of the b-tree into a PMA in sorted order.
70727
+ ** Close the currently open b-tree cursor. */
70728
+ rc = vdbeSorterBtreeToPMA(db, pCsr);
70729
+ sqlite3BtreeCloseCursor(p);
70730
+
70731
+ if( rc==SQLITE_OK ){
70732
+ rc = sqlite3BtreeDropTable(pCsr->pBt, 2, 0);
70733
+#ifdef SQLITE_DEBUG
70734
+ sqlite3PagerPagecount(pPager, &nPage);
70735
+ assert( rc!=SQLITE_OK || nPage==1 );
70736
+#endif
70737
+ }
70738
+ if( rc==SQLITE_OK ){
70739
+ rc = sqlite3BtreeCreateTable(pCsr->pBt, &iRoot, BTREE_BLOBKEY);
70740
+ }
70741
+ if( rc==SQLITE_OK ){
70742
+ assert( iRoot==2 );
70743
+ rc = sqlite3BtreeCursor(pCsr->pBt, iRoot, 1, pCsr->pKeyInfo, p);
70744
+ }
70745
+ }
70746
+
70747
+ pSorter->nBtree += sqlite3VarintLen(nKey) + nKey;
70748
+ }
70749
+ return rc;
70750
+}
70751
+
70752
+/*
70753
+** Helper function for sqlite3VdbeSorterRewind().
70754
+*/
70755
+static int vdbeSorterInitMerge(
70756
+ sqlite3 *db, /* Database handle */
70757
+ VdbeCursor *pCsr, /* Cursor handle for this sorter */
70758
+ i64 *pnByte /* Sum of bytes in all opened PMAs */
70759
+){
70760
+ VdbeSorter *pSorter = pCsr->pSorter;
70761
+ int rc = SQLITE_OK; /* Return code */
70762
+ int i; /* Used to iterator through aIter[] */
70763
+ i64 nByte = 0; /* Total bytes in all opened PMAs */
70764
+
70765
+ /* Initialize the iterators. */
70766
+ for(i=0; rc==SQLITE_OK && i<SORTER_MAX_MERGE_COUNT; i++){
70767
+ VdbeSorterIter *pIter = &pSorter->aIter[i];
70768
+ rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
70769
+ pSorter->iReadOff = pIter->iEof;
70770
+ assert( pSorter->iReadOff<=pSorter->iWriteOff || rc!=SQLITE_OK );
70771
+ if( pSorter->iReadOff>=pSorter->iWriteOff ) break;
70772
+ }
70773
+
70774
+ /* Initialize the aTree[] array. */
70775
+ for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
70776
+ rc = vdbeSorterDoCompare(pCsr, i);
70777
+ }
70778
+
70779
+ *pnByte = nByte;
70780
+ return rc;
70781
+}
70782
+
70783
+/*
70784
+** Once the sorter has been populated, this function is called to prepare
70785
+** for iterating through its contents in sorted order.
70786
+*/
70787
+SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
70788
+ VdbeSorter *pSorter = pCsr->pSorter;
70789
+ int rc; /* Return code */
70790
+ sqlite3_file *pTemp2 = 0; /* Second temp file to use */
70791
+ i64 iWrite2 = 0; /* Write offset for pTemp2 */
70792
+ int nIter; /* Number of iterators used */
70793
+ int nByte; /* Bytes of space required for aIter/aTree */
70794
+ int N = 2; /* Power of 2 >= nIter */
70795
+
70796
+ assert( pSorter );
70797
+
70798
+ /* Write the current b-tree to a PMA. Close the b-tree cursor. */
70799
+ rc = vdbeSorterBtreeToPMA(db, pCsr);
70800
+ sqlite3BtreeCloseCursor(pCsr->pCursor);
70801
+ if( rc!=SQLITE_OK ) return rc;
70802
+ if( pSorter->nPMA==0 ){
70803
+ *pbEof = 1;
70804
+ return SQLITE_OK;
70805
+ }
70806
+
70807
+ /* Allocate space for aIter[] and aTree[]. */
70808
+ nIter = pSorter->nPMA;
70809
+ if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
70810
+ assert( nIter>0 );
70811
+ while( N<nIter ) N += N;
70812
+ nByte = N * (sizeof(int) + sizeof(VdbeSorterIter));
70813
+ pSorter->aIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte);
70814
+ if( !pSorter->aIter ) return SQLITE_NOMEM;
70815
+ pSorter->aTree = (int *)&pSorter->aIter[N];
70816
+ pSorter->nTree = N;
70817
+
70818
+ do {
70819
+ int iNew; /* Index of new, merged, PMA */
70820
+
70821
+ for(iNew=0;
70822
+ rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA;
70823
+ iNew++
70824
+ ){
70825
+ i64 nWrite; /* Number of bytes in new PMA */
70826
+
70827
+ /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
70828
+ ** initialize an iterator for each of them and break out of the loop.
70829
+ ** These iterators will be incrementally merged as the VDBE layer calls
70830
+ ** sqlite3VdbeSorterNext().
70831
+ **
70832
+ ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs,
70833
+ ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs
70834
+ ** are merged into a single PMA that is written to file pTemp2.
70835
+ */
70836
+ rc = vdbeSorterInitMerge(db, pCsr, &nWrite);
70837
+ assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile );
70838
+ if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
70839
+ break;
70840
+ }
70841
+
70842
+ /* Open the second temp file, if it is not already open. */
70843
+ if( pTemp2==0 ){
70844
+ assert( iWrite2==0 );
70845
+ rc = vdbeSorterOpenTempFile(db, &pTemp2);
70846
+ }
70847
+
70848
+ if( rc==SQLITE_OK ){
70849
+ rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2);
70850
+ }
70851
+
70852
+ if( rc==SQLITE_OK ){
70853
+ int bEof = 0;
70854
+ while( rc==SQLITE_OK && bEof==0 ){
70855
+ int nToWrite;
70856
+ VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
70857
+ assert( pIter->pFile );
70858
+ nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey);
70859
+ rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2);
70860
+ iWrite2 += nToWrite;
70861
+ if( rc==SQLITE_OK ){
70862
+ rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
70863
+ }
70864
+ }
70865
+ }
70866
+ }
70867
+
70868
+ if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
70869
+ break;
70870
+ }else{
70871
+ sqlite3_file *pTmp = pSorter->pTemp1;
70872
+ pSorter->nPMA = iNew;
70873
+ pSorter->pTemp1 = pTemp2;
70874
+ pTemp2 = pTmp;
70875
+ pSorter->iWriteOff = iWrite2;
70876
+ pSorter->iReadOff = 0;
70877
+ iWrite2 = 0;
70878
+ }
70879
+ }while( rc==SQLITE_OK );
70880
+
70881
+ if( pTemp2 ){
70882
+ sqlite3OsCloseFree(pTemp2);
70883
+ }
70884
+ *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
70885
+ return rc;
70886
+}
70887
+
70888
+/*
70889
+** Advance to the next element in the sorter.
70890
+*/
70891
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
70892
+ VdbeSorter *pSorter = pCsr->pSorter;
70893
+ int iPrev = pSorter->aTree[1]; /* Index of iterator to advance */
70894
+ int i; /* Index of aTree[] to recalculate */
70895
+ int rc; /* Return code */
70896
+
70897
+ rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
70898
+ for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
70899
+ rc = vdbeSorterDoCompare(pCsr, i);
70900
+ }
70901
+
70902
+ *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
70903
+ return rc;
70904
+}
70905
+
70906
+/*
70907
+** Copy the current sorter key into the memory cell pOut.
70908
+*/
70909
+SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
70910
+ VdbeSorter *pSorter = pCsr->pSorter;
70911
+ VdbeSorterIter *pIter;
70912
+
70913
+ pIter = &pSorter->aIter[ pSorter->aTree[1] ];
70914
+
70915
+ /* Coverage testing note: As things are currently, this call will always
70916
+ ** succeed. This is because the memory cell passed by the VDBE layer
70917
+ ** happens to be the same one as was used to assemble the keys before they
70918
+ ** were passed to the sorter - meaning it is always large enough for the
70919
+ ** largest key. But this could change very easily, so we leave the call
70920
+ ** to sqlite3VdbeMemGrow() in. */
70921
+ if( NEVER(sqlite3VdbeMemGrow(pOut, pIter->nKey, 0)) ){
70922
+ return SQLITE_NOMEM;
70923
+ }
70924
+ pOut->n = pIter->nKey;
70925
+ MemSetTypeFlag(pOut, MEM_Blob);
70926
+ memcpy(pOut->z, pIter->aKey, pIter->nKey);
70927
+
70928
+ return SQLITE_OK;
70929
+}
70930
+
70931
+#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
70932
+
70933
+/************** End of vdbesort.c ********************************************/
6932870934
/************** Begin file journal.c *****************************************/
6932970935
/*
6933070936
** 2007 August 22
6933170937
**
6933270938
** The author disclaims copyright to this source code. In place of
@@ -69839,10 +71445,12 @@
6983971445
**
6984071446
*************************************************************************
6984171447
** This file contains routines used for walking the parser tree for
6984271448
** an SQL statement.
6984371449
*/
71450
+/* #include <stdlib.h> */
71451
+/* #include <string.h> */
6984471452
6984571453
6984671454
/*
6984771455
** Walk an expression tree. Invoke the callback once for each node
6984871456
** of the expression, while decending. (In other words, the callback
@@ -69977,10 +71585,12 @@
6997771585
**
6997871586
** This file contains routines used for walking the parser tree and
6997971587
** resolve all identifiers by associating them with a particular
6998071588
** table and column.
6998171589
*/
71590
+/* #include <stdlib.h> */
71591
+/* #include <string.h> */
6998271592
6998371593
/*
6998471594
** Turn the pExpr expression into an alias for the iCol-th column of the
6998571595
** result set in pEList.
6998671596
**
@@ -70956,15 +72566,29 @@
7095672566
/* Recursively resolve names in all subqueries
7095772567
*/
7095872568
for(i=0; i<p->pSrc->nSrc; i++){
7095972569
struct SrcList_item *pItem = &p->pSrc->a[i];
7096072570
if( pItem->pSelect ){
72571
+ NameContext *pNC; /* Used to iterate name contexts */
72572
+ int nRef = 0; /* Refcount for pOuterNC and outer contexts */
7096172573
const char *zSavedContext = pParse->zAuthContext;
72574
+
72575
+ /* Count the total number of references to pOuterNC and all of its
72576
+ ** parent contexts. After resolving references to expressions in
72577
+ ** pItem->pSelect, check if this value has changed. If so, then
72578
+ ** SELECT statement pItem->pSelect must be correlated. Set the
72579
+ ** pItem->isCorrelated flag if this is the case. */
72580
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
72581
+
7096272582
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
7096372583
sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
7096472584
pParse->zAuthContext = zSavedContext;
7096572585
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
72586
+
72587
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
72588
+ assert( pItem->isCorrelated==0 && nRef<=0 );
72589
+ pItem->isCorrelated = (nRef!=0);
7096672590
}
7096772591
}
7096872592
7096972593
/* If there are no aggregate functions in the result-set, and no GROUP BY
7097072594
** expression, do not allow aggregates in any of the other expressions.
@@ -72068,10 +73692,11 @@
7206873692
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
7206973693
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
7207073694
pNewItem->jointype = pOldItem->jointype;
7207173695
pNewItem->iCursor = pOldItem->iCursor;
7207273696
pNewItem->isPopulated = pOldItem->isPopulated;
73697
+ pNewItem->isCorrelated = pOldItem->isCorrelated;
7207373698
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
7207473699
pNewItem->notIndexed = pOldItem->notIndexed;
7207573700
pNewItem->pIndex = pOldItem->pIndex;
7207673701
pTab = pNewItem->pTab = pOldItem->pTab;
7207773702
if( pTab ){
@@ -78958,11 +80583,11 @@
7895880583
Table *p;
7895980584
int n;
7896080585
const char *z;
7896180586
Token sEnd;
7896280587
DbFixer sFix;
78963
- Token *pName;
80588
+ Token *pName = 0;
7896480589
int iDb;
7896580590
sqlite3 *db = pParse->db;
7896680591
7896780592
if( pParse->nVar>0 ){
7896880593
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
@@ -79263,10 +80888,33 @@
7926380888
iDestroyed = iLargest;
7926480889
}
7926580890
}
7926680891
#endif
7926780892
}
80893
+
80894
+/*
80895
+** Remove entries from the sqlite_stat1 and sqlite_stat2 tables
80896
+** after a DROP INDEX or DROP TABLE command.
80897
+*/
80898
+static void sqlite3ClearStatTables(
80899
+ Parse *pParse, /* The parsing context */
80900
+ int iDb, /* The database number */
80901
+ const char *zType, /* "idx" or "tbl" */
80902
+ const char *zName /* Name of index or table */
80903
+){
80904
+ static const char *azStatTab[] = { "sqlite_stat1", "sqlite_stat2" };
80905
+ int i;
80906
+ const char *zDbName = pParse->db->aDb[iDb].zName;
80907
+ for(i=0; i<ArraySize(azStatTab); i++){
80908
+ if( sqlite3FindTable(pParse->db, azStatTab[i], zDbName) ){
80909
+ sqlite3NestedParse(pParse,
80910
+ "DELETE FROM %Q.%s WHERE %s=%Q",
80911
+ zDbName, azStatTab[i], zType, zName
80912
+ );
80913
+ }
80914
+ }
80915
+}
7926880916
7926980917
/*
7927080918
** This routine is called to do the work of a DROP TABLE statement.
7927180919
** pName is the name of the table to be dropped.
7927280920
*/
@@ -79403,18 +81051,11 @@
7940381051
** database.
7940481052
*/
7940581053
sqlite3NestedParse(pParse,
7940681054
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
7940781055
pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
79408
-
79409
- /* Drop any statistics from the sqlite_stat1 table, if it exists */
79410
- if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
79411
- sqlite3NestedParse(pParse,
79412
- "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName
79413
- );
79414
- }
79415
-
81056
+ sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
7941681057
if( !isView && !IsVirtual(pTab) ){
7941781058
destroyTable(pParse, pTab);
7941881059
}
7941981060
7942081061
/* Remove the table entry from SQLite's internal schema and modify
@@ -79592,18 +81233,28 @@
7959281233
*/
7959381234
static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
7959481235
Table *pTab = pIndex->pTable; /* The table that is indexed */
7959581236
int iTab = pParse->nTab++; /* Btree cursor used for pTab */
7959681237
int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
81238
+ int iSorter = iTab; /* Cursor opened by OpenSorter (if in use) */
7959781239
int addr1; /* Address of top of loop */
7959881240
int tnum; /* Root page of index */
7959981241
Vdbe *v; /* Generate code into this virtual machine */
7960081242
KeyInfo *pKey; /* KeyInfo for index */
7960181243
int regIdxKey; /* Registers containing the index key */
7960281244
int regRecord; /* Register holding assemblied index record */
7960381245
sqlite3 *db = pParse->db; /* The database connection */
7960481246
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
81247
+
81248
+ /* Set bUseSorter to use OP_OpenSorter, or clear it to insert directly
81249
+ ** into the index. The sorter is used unless either OMIT_MERGE_SORT is
81250
+ ** defined or the system is configured to store temp files in-memory. */
81251
+#ifdef SQLITE_OMIT_MERGE_SORT
81252
+ static const int bUseSorter = 0;
81253
+#else
81254
+ const int bUseSorter = !sqlite3TempInMemory(pParse->db);
81255
+#endif
7960581256
7960681257
#ifndef SQLITE_OMIT_AUTHORIZATION
7960781258
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
7960881259
db->aDb[iDb].zName ) ){
7960981260
return;
@@ -79625,14 +81276,33 @@
7962581276
sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
7962681277
(char *)pKey, P4_KEYINFO_HANDOFF);
7962781278
if( memRootPage>=0 ){
7962881279
sqlite3VdbeChangeP5(v, 1);
7962981280
}
81281
+
81282
+ /* Open the sorter cursor if we are to use one. */
81283
+ if( bUseSorter ){
81284
+ iSorter = pParse->nTab++;
81285
+ sqlite3VdbeAddOp4(v, OP_OpenSorter, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
81286
+ sqlite3VdbeChangeP5(v, BTREE_SORTER);
81287
+ }
81288
+
81289
+ /* Open the table. Loop through all rows of the table, inserting index
81290
+ ** records into the sorter. */
7963081291
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
7963181292
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
7963281293
regRecord = sqlite3GetTempReg(pParse);
7963381294
regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
81295
+
81296
+ if( bUseSorter ){
81297
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iSorter, regRecord);
81298
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
81299
+ sqlite3VdbeJumpHere(v, addr1);
81300
+ addr1 = sqlite3VdbeAddOp2(v, OP_Sort, iSorter, 0);
81301
+ sqlite3VdbeAddOp2(v, OP_RowKey, iSorter, regRecord);
81302
+ }
81303
+
7963481304
if( pIndex->onError!=OE_None ){
7963581305
const int regRowid = regIdxKey + pIndex->nColumn;
7963681306
const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
7963781307
void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
7963881308
@@ -79647,17 +81317,19 @@
7964781317
*/
7964881318
sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
7964981319
sqlite3HaltConstraint(
7965081320
pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
7965181321
}
79652
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
81322
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, bUseSorter);
7965381323
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
7965481324
sqlite3ReleaseTempReg(pParse, regRecord);
79655
- sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
81325
+ sqlite3VdbeAddOp2(v, OP_Next, iSorter, addr1+1);
7965681326
sqlite3VdbeJumpHere(v, addr1);
81327
+
7965781328
sqlite3VdbeAddOp1(v, OP_Close, iTab);
7965881329
sqlite3VdbeAddOp1(v, OP_Close, iIdx);
81330
+ sqlite3VdbeAddOp1(v, OP_Close, iSorter);
7965981331
}
7966081332
7966181333
/*
7966281334
** Create a new index for an SQL table. pName1.pName2 is the name of the index
7966381335
** and pTblList is the name of the table that is to be indexed. Both will
@@ -80075,11 +81747,11 @@
8007581747
if( pStart ){
8007681748
assert( pEnd!=0 );
8007781749
/* A named index with an explicit CREATE INDEX statement */
8007881750
zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
8007981751
onError==OE_None ? "" : " UNIQUE",
80080
- pEnd->z - pName->z + 1,
81752
+ (int)(pEnd->z - pName->z) + 1,
8008181753
pName->z);
8008281754
}else{
8008381755
/* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
8008481756
/* zStmt = sqlite3MPrintf(""); */
8008581757
zStmt = 0;
@@ -80233,19 +81905,13 @@
8023381905
v = sqlite3GetVdbe(pParse);
8023481906
if( v ){
8023581907
sqlite3BeginWriteOperation(pParse, 1, iDb);
8023681908
sqlite3NestedParse(pParse,
8023781909
"DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
80238
- db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
80239
- pIndex->zName
80240
- );
80241
- if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
80242
- sqlite3NestedParse(pParse,
80243
- "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q",
80244
- db->aDb[iDb].zName, pIndex->zName
80245
- );
80246
- }
81910
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName
81911
+ );
81912
+ sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
8024781913
sqlite3ChangeCookie(pParse, iDb);
8024881914
destroyRootPage(pParse, pIndex->tnum, iDb);
8024981915
sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
8025081916
}
8025181917
@@ -80613,12 +82279,13 @@
8061382279
** The operator is "natural cross join". The A and B operands are stored
8061482280
** in p->a[0] and p->a[1], respectively. The parser initially stores the
8061582281
** operator with A. This routine shifts that operator over to B.
8061682282
*/
8061782283
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
80618
- if( p && p->a ){
82284
+ if( p ){
8061982285
int i;
82286
+ assert( p->a || p->nSrc==0 );
8062082287
for(i=p->nSrc-1; i>0; i--){
8062182288
p->a[i].jointype = p->a[i-1].jointype;
8062282289
}
8062382290
p->a[0].jointype = 0;
8062482291
}
@@ -81870,11 +83537,13 @@
8187083537
int regRowid; /* Actual register containing rowids */
8187183538
8187283539
/* Collect rowids of every row to be deleted.
8187383540
*/
8187483541
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
81875
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
83542
+ pWInfo = sqlite3WhereBegin(
83543
+ pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
83544
+ );
8187683545
if( pWInfo==0 ) goto delete_from_cleanup;
8187783546
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
8187883547
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
8187983548
if( db->flags & SQLITE_CountRows ){
8188083549
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
@@ -82135,12 +83804,18 @@
8213583804
sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
8213683805
sqlite3ColumnDefault(v, pTab, idx, -1);
8213783806
}
8213883807
}
8213983808
if( doMakeRec ){
83809
+ const char *zAff;
83810
+ if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
83811
+ zAff = 0;
83812
+ }else{
83813
+ zAff = sqlite3IndexAffinityStr(v, pIdx);
83814
+ }
8214083815
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
82141
- sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
83816
+ sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
8214283817
}
8214383818
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
8214483819
return regBase;
8214583820
}
8214683821
@@ -82162,10 +83837,12 @@
8216283837
**
8216383838
** There is only one exported symbol in this file - the function
8216483839
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
8216583840
** All other code has file scope.
8216683841
*/
83842
+/* #include <stdlib.h> */
83843
+/* #include <assert.h> */
8216783844
8216883845
/*
8216983846
** Return the collating function associated with a function.
8217083847
*/
8217183848
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
@@ -84311,11 +85988,11 @@
8431185988
8431285989
/* Create VDBE to loop through the entries in pSrc that match the WHERE
8431385990
** clause. If the constraint is not deferred, throw an exception for
8431485991
** each row found. Otherwise, for deferred constraints, increment the
8431585992
** deferred constraint counter by nIncr for each row selected. */
84316
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0);
85993
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
8431785994
if( nIncr>0 && pFKey->isDeferred==0 ){
8431885995
sqlite3ParseToplevel(pParse)->mayAbort = 1;
8431985996
}
8432085997
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
8432185998
if( pWInfo ){
@@ -84485,11 +86162,28 @@
8448586162
pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
8448686163
}else{
8448786164
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
8448886165
}
8448986166
if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
86167
+ assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
8449086168
if( !isIgnoreErrors || db->mallocFailed ) return;
86169
+ if( pTo==0 ){
86170
+ /* If isIgnoreErrors is true, then a table is being dropped. In this
86171
+ ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
86172
+ ** before actually dropping it in order to check FK constraints.
86173
+ ** If the parent table of an FK constraint on the current table is
86174
+ ** missing, behave as if it is empty. i.e. decrement the relevant
86175
+ ** FK counter for each row of the current table with non-NULL keys.
86176
+ */
86177
+ Vdbe *v = sqlite3GetVdbe(pParse);
86178
+ int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
86179
+ for(i=0; i<pFKey->nCol; i++){
86180
+ int iReg = pFKey->aCol[i].iFrom + regOld + 1;
86181
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump);
86182
+ }
86183
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
86184
+ }
8449186185
continue;
8449286186
}
8449386187
assert( pFKey->nCol==1 || (aiFree && pIdx) );
8449486188
8449586189
if( aiFree ){
@@ -87178,10 +88872,13 @@
8717888872
int (*strnicmp)(const char*,const char*,int);
8717988873
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
8718088874
int (*wal_autocheckpoint)(sqlite3*,int);
8718188875
int (*wal_checkpoint)(sqlite3*,const char*);
8718288876
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
88877
+ int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
88878
+ int (*vtab_config)(sqlite3*,int op,...);
88879
+ int (*vtab_on_conflict)(sqlite3*);
8718388880
};
8718488881
8718588882
/*
8718688883
** The following macros redefine the API routines so that they are
8718788884
** redirected throught the global sqlite3_api structure.
@@ -87378,19 +89075,23 @@
8737889075
#define sqlite3_strnicmp sqlite3_api->strnicmp
8737989076
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
8738089077
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
8738189078
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
8738289079
#define sqlite3_wal_hook sqlite3_api->wal_hook
89080
+#define sqlite3_blob_reopen sqlite3_api->blob_reopen
89081
+#define sqlite3_vtab_config sqlite3_api->vtab_config
89082
+#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
8738389083
#endif /* SQLITE_CORE */
8738489084
8738589085
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
8738689086
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
8738789087
8738889088
#endif /* _SQLITE3EXT_H_ */
8738989089
8739089090
/************** End of sqlite3ext.h ******************************************/
8739189091
/************** Continuing where we left off in loadext.c ********************/
89092
+/* #include <string.h> */
8739289093
8739389094
#ifndef SQLITE_OMIT_LOAD_EXTENSION
8739489095
8739589096
/*
8739689097
** Some API routines are omitted when various features are
@@ -87452,10 +89153,12 @@
8745289153
8745389154
#ifdef SQLITE_OMIT_VIRTUALTABLE
8745489155
# define sqlite3_create_module 0
8745589156
# define sqlite3_create_module_v2 0
8745689157
# define sqlite3_declare_vtab 0
89158
+# define sqlite3_vtab_config 0
89159
+# define sqlite3_vtab_on_conflict 0
8745789160
#endif
8745889161
8745989162
#ifdef SQLITE_OMIT_SHARED_CACHE
8746089163
# define sqlite3_enable_shared_cache 0
8746189164
#endif
@@ -87475,10 +89178,11 @@
8747589178
#define sqlite3_blob_bytes 0
8747689179
#define sqlite3_blob_close 0
8747789180
#define sqlite3_blob_open 0
8747889181
#define sqlite3_blob_read 0
8747989182
#define sqlite3_blob_write 0
89183
+#define sqlite3_blob_reopen 0
8748089184
#endif
8748189185
8748289186
/*
8748389187
** The following structure contains pointers to all SQLite API routines.
8748489188
** A pointer to this structure is passed into extensions when they are
@@ -87740,10 +89444,13 @@
8774089444
#else
8774189445
0,
8774289446
0,
8774389447
0,
8774489448
#endif
89449
+ sqlite3_blob_reopen,
89450
+ sqlite3_vtab_config,
89451
+ sqlite3_vtab_on_conflict,
8774589452
};
8774689453
8774789454
/*
8774889455
** Attempt to load an SQLite extension library contained in the file
8774989456
** zFile. The entry point is zProc. zProc may be 0 in which case a
@@ -94129,10 +95836,11 @@
9412995836
Expr *pHaving; /* The HAVING clause. May be NULL */
9413095837
int isDistinct; /* True if the DISTINCT keyword is present */
9413195838
int distinct; /* Table to use for the distinct set */
9413295839
int rc = 1; /* Value to return from this function */
9413395840
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
95841
+ int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
9413495842
AggInfo sAggInfo; /* Information used by aggregate queries */
9413595843
int iEnd; /* Address of the end of the query */
9413695844
sqlite3 *db; /* The database connection */
9413795845
9413895846
#ifndef SQLITE_OMIT_EXPLAIN
@@ -94255,20 +95963,10 @@
9425595963
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
9425695964
return rc;
9425795965
}
9425895966
#endif
9425995967
94260
- /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
94261
- ** GROUP BY might use an index, DISTINCT never does.
94262
- */
94263
- assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
94264
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
94265
- p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
94266
- pGroupBy = p->pGroupBy;
94267
- p->selFlags &= ~SF_Distinct;
94268
- }
94269
-
9427095968
/* If there is both a GROUP BY and an ORDER BY clause and they are
9427195969
** identical, then disable the ORDER BY clause since the GROUP BY
9427295970
** will cause elements to come out in the correct order. This is
9427395971
** an optimization - the correct answer should result regardless.
9427495972
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
@@ -94276,10 +95974,34 @@
9427695974
*/
9427795975
if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
9427895976
&& (db->flags & SQLITE_GroupByOrder)==0 ){
9427995977
pOrderBy = 0;
9428095978
}
95979
+
95980
+ /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
95981
+ ** if the select-list is the same as the ORDER BY list, then this query
95982
+ ** can be rewritten as a GROUP BY. In other words, this:
95983
+ **
95984
+ ** SELECT DISTINCT xyz FROM ... ORDER BY xyz
95985
+ **
95986
+ ** is transformed to:
95987
+ **
95988
+ ** SELECT xyz FROM ... GROUP BY xyz
95989
+ **
95990
+ ** The second form is preferred as a single index (or temp-table) may be
95991
+ ** used for both the ORDER BY and DISTINCT processing. As originally
95992
+ ** written the query must use a temp-table for at least one of the ORDER
95993
+ ** BY and DISTINCT, and an index or separate temp-table for the other.
95994
+ */
95995
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
95996
+ && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
95997
+ ){
95998
+ p->selFlags &= ~SF_Distinct;
95999
+ p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
96000
+ pGroupBy = p->pGroupBy;
96001
+ pOrderBy = 0;
96002
+ }
9428196003
9428296004
/* If there is an ORDER BY clause, then this sorting
9428396005
** index might end up being unused if the data can be
9428496006
** extracted in pre-sorted order. If that is the case, then the
9428596007
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
@@ -94312,26 +96034,25 @@
9431296034
9431396035
/* Open a virtual index to use for the distinct set.
9431496036
*/
9431596037
if( p->selFlags & SF_Distinct ){
9431696038
KeyInfo *pKeyInfo;
94317
- assert( isAgg || pGroupBy );
9431896039
distinct = pParse->nTab++;
9431996040
pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
94320
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
94321
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
96041
+ addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
96042
+ (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
9432296043
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
9432396044
}else{
94324
- distinct = -1;
96045
+ distinct = addrDistinctIndex = -1;
9432596046
}
9432696047
9432796048
/* Aggregate and non-aggregate queries are handled differently */
9432896049
if( !isAgg && pGroupBy==0 ){
94329
- /* This case is for non-aggregate queries
94330
- ** Begin the database scan
94331
- */
94332
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
96050
+ ExprList *pDist = (isDistinct ? p->pEList : 0);
96051
+
96052
+ /* Begin the database scan. */
96053
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
9433396054
if( pWInfo==0 ) goto select_end;
9433496055
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
9433596056
9433696057
/* If sorting index that was created by a prior OP_OpenEphemeral
9433796058
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -94340,14 +96061,56 @@
9434096061
if( addrSortIndex>=0 && pOrderBy==0 ){
9434196062
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
9434296063
p->addrOpenEphm[2] = -1;
9434396064
}
9434496065
94345
- /* Use the standard inner loop
94346
- */
94347
- assert(!isDistinct);
94348
- selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
96066
+ if( pWInfo->eDistinct ){
96067
+ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
96068
+
96069
+ assert( addrDistinctIndex>0 );
96070
+ pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
96071
+
96072
+ assert( isDistinct );
96073
+ assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
96074
+ || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
96075
+ );
96076
+ distinct = -1;
96077
+ if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
96078
+ int iJump;
96079
+ int iExpr;
96080
+ int iFlag = ++pParse->nMem;
96081
+ int iBase = pParse->nMem+1;
96082
+ int iBase2 = iBase + pEList->nExpr;
96083
+ pParse->nMem += (pEList->nExpr*2);
96084
+
96085
+ /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
96086
+ ** OP_Integer initializes the "first row" flag. */
96087
+ pOp->opcode = OP_Integer;
96088
+ pOp->p1 = 1;
96089
+ pOp->p2 = iFlag;
96090
+
96091
+ sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
96092
+ iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
96093
+ sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
96094
+ for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
96095
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
96096
+ sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
96097
+ sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
96098
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
96099
+ }
96100
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
96101
+
96102
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
96103
+ assert( sqlite3VdbeCurrentAddr(v)==iJump );
96104
+ sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
96105
+ }else{
96106
+ pOp->opcode = OP_Noop;
96107
+ }
96108
+ }
96109
+
96110
+ /* Use the standard inner loop. */
96111
+ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
9434996112
pWInfo->iContinue, pWInfo->iBreak);
9435096113
9435196114
/* End the database scan loop.
9435296115
*/
9435396116
sqlite3WhereEnd(pWInfo);
@@ -94453,11 +96216,11 @@
9445396216
** This might involve two separate loops with an OP_Sort in between, or
9445496217
** it might be a single loop that uses an index to extract information
9445596218
** in the right order to begin with.
9445696219
*/
9445796220
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
94458
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
96221
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
9445996222
if( pWInfo==0 ) goto select_end;
9446096223
if( pGroupBy==0 ){
9446196224
/* The optimizer is able to deliver rows in group by order so
9446296225
** we do not have to sort. The OP_OpenEphemeral table will be
9446396226
** cancelled later because we still need to use the pKeyInfo
@@ -94715,11 +96478,11 @@
9471596478
/* This case runs if the aggregate has no GROUP BY clause. The
9471696479
** processing is much simpler since there is only a single row
9471796480
** of output.
9471896481
*/
9471996482
resetAccumulator(pParse, &sAggInfo);
94720
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
96483
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
9472196484
if( pWInfo==0 ){
9472296485
sqlite3ExprListDelete(db, pDel);
9472396486
goto select_end;
9472496487
}
9472596488
updateAccumulator(pParse, &sAggInfo);
@@ -94894,10 +96657,12 @@
9489496657
** interface routine of sqlite3_exec().
9489596658
**
9489696659
** These routines are in a separate files so that they will not be linked
9489796660
** if they are not used.
9489896661
*/
96662
+/* #include <stdlib.h> */
96663
+/* #include <string.h> */
9489996664
9490096665
#ifndef SQLITE_OMIT_GET_TABLE
9490196666
9490296667
/*
9490396668
** This structure is used to pass data from sqlite3_get_table() through
@@ -95191,19 +96956,32 @@
9519196956
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
9519296957
if( iDb<0 ){
9519396958
goto trigger_cleanup;
9519496959
}
9519596960
}
96961
+ if( !pTableName || db->mallocFailed ){
96962
+ goto trigger_cleanup;
96963
+ }
96964
+
96965
+ /* A long-standing parser bug is that this syntax was allowed:
96966
+ **
96967
+ ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
96968
+ ** ^^^^^^^^
96969
+ **
96970
+ ** To maintain backwards compatibility, ignore the database
96971
+ ** name on pTableName if we are reparsing our of SQLITE_MASTER.
96972
+ */
96973
+ if( db->init.busy && iDb!=1 ){
96974
+ sqlite3DbFree(db, pTableName->a[0].zDatabase);
96975
+ pTableName->a[0].zDatabase = 0;
96976
+ }
9519696977
9519796978
/* If the trigger name was unqualified, and the table is a temp table,
9519896979
** then set iDb to 1 to create the trigger in the temporary database.
9519996980
** If sqlite3SrcListLookup() returns 0, indicating the table does not
9520096981
** exist, the error is caught by the block below.
9520196982
*/
95202
- if( !pTableName || db->mallocFailed ){
95203
- goto trigger_cleanup;
95204
- }
9520596983
pTab = sqlite3SrcListLookup(pParse, pTableName);
9520696984
if( db->init.busy==0 && pName2->n==0 && pTab
9520796985
&& pTab->pSchema==db->aDb[1].pSchema ){
9520896986
iDb = 1;
9520996987
}
@@ -96497,11 +98275,13 @@
9649798275
}
9649898276
9649998277
/* Begin the database scan
9650098278
*/
9650198279
sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
96502
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
98280
+ pWInfo = sqlite3WhereBegin(
98281
+ pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
98282
+ );
9650398283
if( pWInfo==0 ) goto update_cleanup;
9650498284
okOnePass = pWInfo->okOnePass;
9650598285
9650698286
/* Remember the rowid of every item to be updated.
9650798287
*/
@@ -98523,10 +100303,11 @@
98523100303
#define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
98524100304
#define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
98525100305
#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
98526100306
#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
98527100307
#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
100308
+#define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
98528100309
98529100310
/*
98530100311
** Initialize a preallocated WhereClause structure.
98531100312
*/
98532100313
static void whereClauseInit(
@@ -99667,10 +101448,166 @@
99667101448
}
99668101449
}
99669101450
return 0;
99670101451
}
99671101452
101453
+/*
101454
+** This function searches the expression list passed as the second argument
101455
+** for an expression of type TK_COLUMN that refers to the same column and
101456
+** uses the same collation sequence as the iCol'th column of index pIdx.
101457
+** Argument iBase is the cursor number used for the table that pIdx refers
101458
+** to.
101459
+**
101460
+** If such an expression is found, its index in pList->a[] is returned. If
101461
+** no expression is found, -1 is returned.
101462
+*/
101463
+static int findIndexCol(
101464
+ Parse *pParse, /* Parse context */
101465
+ ExprList *pList, /* Expression list to search */
101466
+ int iBase, /* Cursor for table associated with pIdx */
101467
+ Index *pIdx, /* Index to match column of */
101468
+ int iCol /* Column of index to match */
101469
+){
101470
+ int i;
101471
+ const char *zColl = pIdx->azColl[iCol];
101472
+
101473
+ for(i=0; i<pList->nExpr; i++){
101474
+ Expr *p = pList->a[i].pExpr;
101475
+ if( p->op==TK_COLUMN
101476
+ && p->iColumn==pIdx->aiColumn[iCol]
101477
+ && p->iTable==iBase
101478
+ ){
101479
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
101480
+ if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
101481
+ return i;
101482
+ }
101483
+ }
101484
+ }
101485
+
101486
+ return -1;
101487
+}
101488
+
101489
+/*
101490
+** This routine determines if pIdx can be used to assist in processing a
101491
+** DISTINCT qualifier. In other words, it tests whether or not using this
101492
+** index for the outer loop guarantees that rows with equal values for
101493
+** all expressions in the pDistinct list are delivered grouped together.
101494
+**
101495
+** For example, the query
101496
+**
101497
+** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
101498
+**
101499
+** can benefit from any index on columns "b" and "c".
101500
+*/
101501
+static int isDistinctIndex(
101502
+ Parse *pParse, /* Parsing context */
101503
+ WhereClause *pWC, /* The WHERE clause */
101504
+ Index *pIdx, /* The index being considered */
101505
+ int base, /* Cursor number for the table pIdx is on */
101506
+ ExprList *pDistinct, /* The DISTINCT expressions */
101507
+ int nEqCol /* Number of index columns with == */
101508
+){
101509
+ Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
101510
+ int i; /* Iterator variable */
101511
+
101512
+ if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
101513
+ testcase( pDistinct->nExpr==BMS-1 );
101514
+
101515
+ /* Loop through all the expressions in the distinct list. If any of them
101516
+ ** are not simple column references, return early. Otherwise, test if the
101517
+ ** WHERE clause contains a "col=X" clause. If it does, the expression
101518
+ ** can be ignored. If it does not, and the column does not belong to the
101519
+ ** same table as index pIdx, return early. Finally, if there is no
101520
+ ** matching "col=X" expression and the column is on the same table as pIdx,
101521
+ ** set the corresponding bit in variable mask.
101522
+ */
101523
+ for(i=0; i<pDistinct->nExpr; i++){
101524
+ WhereTerm *pTerm;
101525
+ Expr *p = pDistinct->a[i].pExpr;
101526
+ if( p->op!=TK_COLUMN ) return 0;
101527
+ pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
101528
+ if( pTerm ){
101529
+ Expr *pX = pTerm->pExpr;
101530
+ CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
101531
+ CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
101532
+ if( p1==p2 ) continue;
101533
+ }
101534
+ if( p->iTable!=base ) return 0;
101535
+ mask |= (((Bitmask)1) << i);
101536
+ }
101537
+
101538
+ for(i=nEqCol; mask && i<pIdx->nColumn; i++){
101539
+ int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
101540
+ if( iExpr<0 ) break;
101541
+ mask &= ~(((Bitmask)1) << iExpr);
101542
+ }
101543
+
101544
+ return (mask==0);
101545
+}
101546
+
101547
+
101548
+/*
101549
+** Return true if the DISTINCT expression-list passed as the third argument
101550
+** is redundant. A DISTINCT list is redundant if the database contains a
101551
+** UNIQUE index that guarantees that the result of the query will be distinct
101552
+** anyway.
101553
+*/
101554
+static int isDistinctRedundant(
101555
+ Parse *pParse,
101556
+ SrcList *pTabList,
101557
+ WhereClause *pWC,
101558
+ ExprList *pDistinct
101559
+){
101560
+ Table *pTab;
101561
+ Index *pIdx;
101562
+ int i;
101563
+ int iBase;
101564
+
101565
+ /* If there is more than one table or sub-select in the FROM clause of
101566
+ ** this query, then it will not be possible to show that the DISTINCT
101567
+ ** clause is redundant. */
101568
+ if( pTabList->nSrc!=1 ) return 0;
101569
+ iBase = pTabList->a[0].iCursor;
101570
+ pTab = pTabList->a[0].pTab;
101571
+
101572
+ /* If any of the expressions is an IPK column on table iBase, then return
101573
+ ** true. Note: The (p->iTable==iBase) part of this test may be false if the
101574
+ ** current SELECT is a correlated sub-query.
101575
+ */
101576
+ for(i=0; i<pDistinct->nExpr; i++){
101577
+ Expr *p = pDistinct->a[i].pExpr;
101578
+ if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
101579
+ }
101580
+
101581
+ /* Loop through all indices on the table, checking each to see if it makes
101582
+ ** the DISTINCT qualifier redundant. It does so if:
101583
+ **
101584
+ ** 1. The index is itself UNIQUE, and
101585
+ **
101586
+ ** 2. All of the columns in the index are either part of the pDistinct
101587
+ ** list, or else the WHERE clause contains a term of the form "col=X",
101588
+ ** where X is a constant value. The collation sequences of the
101589
+ ** comparison and select-list expressions must match those of the index.
101590
+ */
101591
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
101592
+ if( pIdx->onError==OE_None ) continue;
101593
+ for(i=0; i<pIdx->nColumn; i++){
101594
+ int iCol = pIdx->aiColumn[i];
101595
+ if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx)
101596
+ && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
101597
+ ){
101598
+ break;
101599
+ }
101600
+ }
101601
+ if( i==pIdx->nColumn ){
101602
+ /* This index implies that the DISTINCT qualifier is redundant. */
101603
+ return 1;
101604
+ }
101605
+ }
101606
+
101607
+ return 0;
101608
+}
99672101609
99673101610
/*
99674101611
** This routine decides if pIdx can be used to satisfy the ORDER BY
99675101612
** clause. If it can, it returns 1. If pIdx cannot satisfy the
99676101613
** ORDER BY clause, this routine returns 0.
@@ -99703,11 +101640,14 @@
99703101640
int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
99704101641
int nTerm; /* Number of ORDER BY terms */
99705101642
struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
99706101643
sqlite3 *db = pParse->db;
99707101644
99708
- assert( pOrderBy!=0 );
101645
+ if( !pOrderBy ) return 0;
101646
+ if( wsFlags & WHERE_COLUMN_IN ) return 0;
101647
+ if( pIdx->bUnordered ) return 0;
101648
+
99709101649
nTerm = pOrderBy->nExpr;
99710101650
assert( nTerm>0 );
99711101651
99712101652
/* Argument pIdx must either point to a 'real' named index structure,
99713101653
** or an index structure allocated on the stack by bestBtreeIndex() to
@@ -100016,10 +101956,14 @@
100016101956
double costTempIdx; /* per-query cost of the transient index */
100017101957
WhereTerm *pTerm; /* A single term of the WHERE clause */
100018101958
WhereTerm *pWCEnd; /* End of pWC->a[] */
100019101959
Table *pTable; /* Table tht might be indexed */
100020101960
101961
+ if( pParse->nQueryLoop<=(double)1 ){
101962
+ /* There is no point in building an automatic index for a single scan */
101963
+ return;
101964
+ }
100021101965
if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
100022101966
/* Automatic indices are disabled at run-time */
100023101967
return;
100024101968
}
100025101969
if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
@@ -100027,10 +101971,14 @@
100027101971
return;
100028101972
}
100029101973
if( pSrc->notIndexed ){
100030101974
/* The NOT INDEXED clause appears in the SQL. */
100031101975
return;
101976
+ }
101977
+ if( pSrc->isCorrelated ){
101978
+ /* The source is a correlated sub-query. No point in indexing it. */
101979
+ return;
100032101980
}
100033101981
100034101982
assert( pParse->nQueryLoop >= (double)1 );
100035101983
pTable = pSrc->pTab;
100036101984
nTableRow = pTable->nRowEst;
@@ -100244,10 +102192,11 @@
100244102192
if( pTerm->leftCursor != pSrc->iCursor ) continue;
100245102193
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
100246102194
testcase( pTerm->eOperator==WO_IN );
100247102195
testcase( pTerm->eOperator==WO_ISNULL );
100248102196
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
102197
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
100249102198
nTerm++;
100250102199
}
100251102200
100252102201
/* If the ORDER BY clause contains only columns in the current
100253102202
** virtual table then allocate space for the aOrderBy part of
@@ -100294,10 +102243,11 @@
100294102243
if( pTerm->leftCursor != pSrc->iCursor ) continue;
100295102244
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
100296102245
testcase( pTerm->eOperator==WO_IN );
100297102246
testcase( pTerm->eOperator==WO_ISNULL );
100298102247
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
102248
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
100299102249
pIdxCons[j].iColumn = pTerm->u.leftColumn;
100300102250
pIdxCons[j].iTermOffset = i;
100301102251
pIdxCons[j].op = (u8)pTerm->eOperator;
100302102252
/* The direct assignment in the previous line is possible only because
100303102253
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
@@ -100959,10 +102909,11 @@
100959102909
WhereClause *pWC, /* The WHERE clause */
100960102910
struct SrcList_item *pSrc, /* The FROM clause term to search */
100961102911
Bitmask notReady, /* Mask of cursors not available for indexing */
100962102912
Bitmask notValid, /* Cursors not available for any purpose */
100963102913
ExprList *pOrderBy, /* The ORDER BY clause */
102914
+ ExprList *pDistinct, /* The select-list if query is DISTINCT */
100964102915
WhereCost *pCost /* Lowest cost query plan */
100965102916
){
100966102917
int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
100967102918
Index *pProbe; /* An index we are evaluating */
100968102919
Index *pIdx; /* Copy of pProbe, or zero for IPK index */
@@ -101099,11 +103050,12 @@
101099103050
int nEq; /* Number of == or IN terms matching index */
101100103051
int bInEst = 0; /* True if "x IN (SELECT...)" seen */
101101103052
int nInMul = 1; /* Number of distinct equalities to lookup */
101102103053
int estBound = 100; /* Estimated reduction in search space */
101103103054
int nBound = 0; /* Number of range constraints seen */
101104
- int bSort = 0; /* True if external sort required */
103055
+ int bSort = !!pOrderBy; /* True if external sort required */
103056
+ int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */
101105103057
int bLookup = 0; /* True if not a covering index */
101106103058
WhereTerm *pTerm; /* A single term of the WHERE clause */
101107103059
#ifdef SQLITE_ENABLE_STAT2
101108103060
WhereTerm *pFirstTerm = 0; /* First term matching the index */
101109103061
#endif
@@ -101163,21 +103115,24 @@
101163103115
101164103116
/* If there is an ORDER BY clause and the index being considered will
101165103117
** naturally scan rows in the required order, set the appropriate flags
101166103118
** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
101167103119
** will scan rows in a different order, set the bSort variable. */
101168
- if( pOrderBy ){
101169
- if( (wsFlags & WHERE_COLUMN_IN)==0
101170
- && pProbe->bUnordered==0
101171
- && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
101172
- nEq, wsFlags, &rev)
101173
- ){
101174
- wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
101175
- wsFlags |= (rev ? WHERE_REVERSE : 0);
101176
- }else{
101177
- bSort = 1;
101178
- }
103120
+ if( isSortingIndex(
103121
+ pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
103122
+ ){
103123
+ bSort = 0;
103124
+ wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
103125
+ wsFlags |= (rev ? WHERE_REVERSE : 0);
103126
+ }
103127
+
103128
+ /* If there is a DISTINCT qualifier and this index will scan rows in
103129
+ ** order of the DISTINCT expressions, clear bDist and set the appropriate
103130
+ ** flags in wsFlags. */
103131
+ if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
103132
+ bDist = 0;
103133
+ wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
101179103134
}
101180103135
101181103136
/* If currently calculating the cost of using an index (not the IPK
101182103137
** index), determine if all required column data may be obtained without
101183103138
** using the main table (i.e. if the index is a covering
@@ -101208,16 +103163,17 @@
101208103163
nRow = aiRowEst[0]/2;
101209103164
nInMul = (int)(nRow / aiRowEst[nEq]);
101210103165
}
101211103166
101212103167
#ifdef SQLITE_ENABLE_STAT2
101213
- /* If the constraint is of the form x=VALUE and histogram
103168
+ /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
103169
+ ** and we do not think that values of x are unique and if histogram
101214103170
** data is available for column x, then it might be possible
101215103171
** to get a better estimate on the number of rows based on
101216103172
** VALUE and how common that value is according to the histogram.
101217103173
*/
101218
- if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
103174
+ if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
101219103175
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
101220103176
testcase( pFirstTerm->eOperator==WO_EQ );
101221103177
testcase( pFirstTerm->eOperator==WO_ISNULL );
101222103178
whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
101223103179
}else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
@@ -101290,10 +103246,13 @@
101290103246
** difference and select C of 3.0.
101291103247
*/
101292103248
if( bSort ){
101293103249
cost += nRow*estLog(nRow)*3;
101294103250
}
103251
+ if( bDist ){
103252
+ cost += nRow*estLog(nRow)*3;
103253
+ }
101295103254
101296103255
/**** Cost of using this index has now been computed ****/
101297103256
101298103257
/* If there are additional constraints on this table that cannot
101299103258
** be used with the current index, but which might lower the number
@@ -101435,11 +103394,11 @@
101435103394
}
101436103395
sqlite3DbFree(pParse->db, p);
101437103396
}else
101438103397
#endif
101439103398
{
101440
- bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
103399
+ bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
101441103400
}
101442103401
}
101443103402
101444103403
/*
101445103404
** Disable a term in the WHERE clause. Except, do not disable the term
@@ -102397,11 +104356,11 @@
102397104356
for(ii=0; ii<pOrWc->nTerm; ii++){
102398104357
WhereTerm *pOrTerm = &pOrWc->a[ii];
102399104358
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
102400104359
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
102401104360
/* Loop through table entries that match term pOrTerm. */
102402
- pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
104361
+ pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0, 0,
102403104362
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
102404104363
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
102405104364
if( pSubWInfo ){
102406104365
explainOneScan(
102407104366
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -102638,10 +104597,11 @@
102638104597
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
102639104598
Parse *pParse, /* The parser context */
102640104599
SrcList *pTabList, /* A list of all tables to be scanned */
102641104600
Expr *pWhere, /* The WHERE clause */
102642104601
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
104602
+ ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
102643104603
u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
102644104604
){
102645104605
int i; /* Loop counter */
102646104606
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
102647104607
int nTabList; /* Number of elements in pTabList */
@@ -102697,10 +104657,14 @@
102697104657
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
102698104658
pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
102699104659
pWInfo->wctrlFlags = wctrlFlags;
102700104660
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
102701104661
pMaskSet = (WhereMaskSet*)&pWC[1];
104662
+
104663
+ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
104664
+ ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
104665
+ if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
102702104666
102703104667
/* Split the WHERE clause into separate subexpressions where each
102704104668
** subexpression is separated by an AND operator.
102705104669
*/
102706104670
initMaskSet(pMaskSet);
@@ -102764,10 +104728,19 @@
102764104728
*/
102765104729
exprAnalyzeAll(pTabList, pWC);
102766104730
if( db->mallocFailed ){
102767104731
goto whereBeginError;
102768104732
}
104733
+
104734
+ /* Check if the DISTINCT qualifier, if there is one, is redundant.
104735
+ ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
104736
+ ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
104737
+ */
104738
+ if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
104739
+ pDistinct = 0;
104740
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
104741
+ }
102769104742
102770104743
/* Chose the best index to use for each table in the FROM clause.
102771104744
**
102772104745
** This loop fills in the following fields:
102773104746
**
@@ -102848,10 +104821,11 @@
102848104821
Bitmask mask; /* Mask of tables not yet ready */
102849104822
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
102850104823
int doNotReorder; /* True if this table should not be reordered */
102851104824
WhereCost sCost; /* Cost information from best[Virtual]Index() */
102852104825
ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
104826
+ ExprList *pDist; /* DISTINCT clause for index to optimize */
102853104827
102854104828
doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
102855104829
if( j!=iFrom && doNotReorder ) break;
102856104830
m = getMask(pMaskSet, pTabItem->iCursor);
102857104831
if( (m & notReady)==0 ){
@@ -102858,10 +104832,11 @@
102858104832
if( j==iFrom ) iFrom++;
102859104833
continue;
102860104834
}
102861104835
mask = (isOptimal ? m : notReady);
102862104836
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
104837
+ pDist = (i==0 ? pDistinct : 0);
102863104838
if( pTabItem->pIndex==0 ) nUnconstrained++;
102864104839
102865104840
WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
102866104841
j, isOptimal));
102867104842
assert( pTabItem->pTab );
@@ -102872,11 +104847,11 @@
102872104847
&sCost, pp);
102873104848
}else
102874104849
#endif
102875104850
{
102876104851
bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
102877
- &sCost);
104852
+ pDist, &sCost);
102878104853
}
102879104854
assert( isOptimal || (sCost.used&notReady)==0 );
102880104855
102881104856
/* If an INDEXED BY clause is present, then the plan must use that
102882104857
** index if it uses any index at all */
@@ -102932,10 +104907,14 @@
102932104907
WHERETRACE(("*** Optimizer selects table %d for loop %d"
102933104908
" with cost=%g and nRow=%g\n",
102934104909
bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
102935104910
if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
102936104911
*ppOrderBy = 0;
104912
+ }
104913
+ if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
104914
+ assert( pWInfo->eDistinct==0 );
104915
+ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
102937104916
}
102938104917
andFlags &= bestPlan.plan.wsFlags;
102939104918
pLevel->plan = bestPlan.plan;
102940104919
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
102941104920
testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
@@ -103267,10 +105246,11 @@
103267105246
** LALR(1) grammar but which are always false in the
103268105247
** specific grammar used by SQLite.
103269105248
*/
103270105249
/* First off, code is included that follows the "include" declaration
103271105250
** in the input grammar file. */
105251
+/* #include <stdio.h> */
103272105252
103273105253
103274105254
/*
103275105255
** Disable all error recovery processing in the parser push-down
103276105256
** automaton.
@@ -104127,10 +106107,11 @@
104127106107
#endif
104128106108
};
104129106109
typedef struct yyParser yyParser;
104130106110
104131106111
#ifndef NDEBUG
106112
+/* #include <stdio.h> */
104132106113
static FILE *yyTraceFILE = 0;
104133106114
static char *yyTracePrompt = 0;
104134106115
#endif /* NDEBUG */
104135106116
104136106117
#ifndef NDEBUG
@@ -106702,10 +108683,11 @@
106702108683
**
106703108684
** This file contains C code that splits an SQL input string up into
106704108685
** individual tokens and sends those tokens one-by-one over to the
106705108686
** parser for analysis.
106706108687
*/
108688
+/* #include <stdlib.h> */
106707108689
106708108690
/*
106709108691
** The charMap() macro maps alphabetic characters into their
106710108692
** lower-case ASCII equivalent. On ASCII machines, this is just
106711108693
** an upper-to-lower case map. On EBCDIC machines we also need
@@ -108093,10 +110075,20 @@
108093110075
memcpy(&y, &x, 8);
108094110076
assert( sqlite3IsNaN(y) );
108095110077
}
108096110078
#endif
108097110079
#endif
110080
+
110081
+ /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
110082
+ ** compile-time option.
110083
+ */
110084
+#ifdef SQLITE_EXTRA_INIT
110085
+ if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
110086
+ int SQLITE_EXTRA_INIT(void);
110087
+ rc = SQLITE_EXTRA_INIT();
110088
+ }
110089
+#endif
108098110090
108099110091
return rc;
108100110092
}
108101110093
108102110094
/*
@@ -110763,10 +112755,21 @@
110763112755
if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
110764112756
sqlite3ScratchFree(pFree);
110765112757
break;
110766112758
}
110767112759
112760
+ /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
112761
+ **
112762
+ ** If parameter onoff is non-zero, configure the wrappers so that all
112763
+ ** subsequent calls to localtime() and variants fail. If onoff is zero,
112764
+ ** undo this setting.
112765
+ */
112766
+ case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
112767
+ sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
112768
+ break;
112769
+ }
112770
+
110768112771
}
110769112772
va_end(ap);
110770112773
#endif /* SQLITE_OMIT_BUILTIN_TEST */
110771112774
return rc;
110772112775
}
@@ -111420,16 +113423,10 @@
111420113423
** TODO(shess) Provide a VACUUM type operation to clear out all
111421113424
** deletions and duplications. This would basically be a forced merge
111422113425
** into a single segment.
111423113426
*/
111424113427
111425
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
111426
-
111427
-#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
111428
-# define SQLITE_CORE 1
111429
-#endif
111430
-
111431113428
/************** Include fts3Int.h in the middle of fts3.c ********************/
111432113429
/************** Begin file fts3Int.h *****************************************/
111433113430
/*
111434113431
** 2009 Nov 12
111435113432
**
@@ -111441,18 +113438,33 @@
111441113438
** May you share freely, never taking more than you give.
111442113439
**
111443113440
******************************************************************************
111444113441
**
111445113442
*/
111446
-
111447113443
#ifndef _FTSINT_H
111448113444
#define _FTSINT_H
111449113445
111450113446
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
111451113447
# define NDEBUG 1
111452113448
#endif
111453113449
113450
+/*
113451
+** FTS4 is really an extension for FTS3. It is enabled using the
113452
+** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
113453
+** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
113454
+*/
113455
+#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
113456
+# define SQLITE_ENABLE_FTS3
113457
+#endif
113458
+
113459
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
113460
+
113461
+/* If not building as part of the core, include sqlite3ext.h. */
113462
+#ifndef SQLITE_CORE
113463
+SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
113464
+#endif
113465
+
111454113466
/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
111455113467
/************** Begin file fts3_tokenizer.h **********************************/
111456113468
/*
111457113469
** 2006 July 10
111458113470
**
@@ -111940,11 +113952,11 @@
111940113952
char *aDoclist; /* List of docids for full-text queries */
111941113953
int nDoclist; /* Size of buffer at aDoclist */
111942113954
u8 bDesc; /* True to sort in descending order */
111943113955
int eEvalmode; /* An FTS3_EVAL_XX constant */
111944113956
int nRowAvg; /* Average size of database rows, in pages */
111945
- int nDoc; /* Documents in table */
113957
+ sqlite3_int64 nDoc; /* Documents in table */
111946113958
111947113959
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
111948113960
u32 *aMatchinfo; /* Information about most recent match */
111949113961
int nMatchinfo; /* Number of elements in aMatchinfo[] */
111950113962
char *zMatchinfo; /* Matchinfo specification */
@@ -111981,11 +113993,11 @@
111981113993
111982113994
sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
111983113995
int bFreeList; /* True if pList should be sqlite3_free()d */
111984113996
char *pList; /* Pointer to position list following iDocid */
111985113997
int nList; /* Length of position list */
111986
-} doclist;
113998
+};
111987113999
111988114000
/*
111989114001
** A "phrase" is a sequence of one or more tokens that must match in
111990114002
** sequence. A single token is the base case and the most common case.
111991114003
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
@@ -111997,19 +114009,19 @@
111997114009
int isPrefix; /* True if token ends with a "*" character */
111998114010
111999114011
/* Variables above this point are populated when the expression is
112000114012
** parsed (by code in fts3_expr.c). Below this point the variables are
112001114013
** used when evaluating the expression. */
112002
- int bFulltext; /* True if full-text index was used */
112003114014
Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
112004114015
Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */
112005114016
};
112006114017
112007114018
struct Fts3Phrase {
112008114019
/* Cache of doclist for this phrase. */
112009114020
Fts3Doclist doclist;
112010114021
int bIncr; /* True if doclist is loaded incrementally */
114022
+ int iDoclistToken;
112011114023
112012114024
/* Variables below this point are populated by fts3_expr.c when parsing
112013114025
** a MATCH expression. Everything above is part of the evaluation phase.
112014114026
*/
112015114027
int nToken; /* Number of tokens in the phrase */
@@ -112130,10 +114142,11 @@
112130114142
Fts3SegFilter *pFilter; /* Pointer to filter object */
112131114143
char *aBuffer; /* Buffer to merge doclists in */
112132114144
int nBuffer; /* Allocated size of aBuffer[] in bytes */
112133114145
112134114146
int iColFilter; /* If >=0, filter for this column */
114147
+ int bRestart;
112135114148
112136114149
/* Used by fts3.c only. */
112137114150
int nCost; /* Cost of running iterator */
112138114151
int bLookup; /* True if a lookup of a single entry. */
112139114152
@@ -112180,43 +114193,49 @@
112180114193
#endif
112181114194
112182114195
/* fts3_aux.c */
112183114196
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
112184114197
112185
-SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
112186
- Fts3Cursor *pCsr, /* Virtual table cursor handle */
112187
- const char *zTerm, /* Term to query for */
112188
- int nTerm, /* Size of zTerm in bytes */
112189
- int isPrefix, /* True for a prefix search */
112190
- Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
112191
-);
112192
-
112193114198
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
112194114199
112195
-SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
112196
-SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
112197
-
112198114200
SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
112199114201
Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
112200114202
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
112201114203
Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
112202114204
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
112203114205
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
114206
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
112204114207
112205114208
SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
112206114209
112207
-
114210
+#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
112208114211
#endif /* _FTSINT_H */
112209114212
112210114213
/************** End of fts3Int.h *********************************************/
112211114214
/************** Continuing where we left off in fts3.c ***********************/
114215
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
112212114216
114217
+#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
114218
+# define SQLITE_CORE 1
114219
+#endif
114220
+
114221
+/* #include <assert.h> */
114222
+/* #include <stdlib.h> */
114223
+/* #include <stddef.h> */
114224
+/* #include <stdio.h> */
114225
+/* #include <string.h> */
114226
+/* #include <stdarg.h> */
112213114227
112214114228
#ifndef SQLITE_CORE
112215114229
SQLITE_EXTENSION_INIT1
112216114230
#endif
112217114231
114232
+static int fts3EvalNext(Fts3Cursor *pCsr);
114233
+static int fts3EvalStart(Fts3Cursor *pCsr);
114234
+static int fts3TermSegReaderCursor(
114235
+ Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
114236
+
112218114237
/*
112219114238
** Write a 64-bit variable-length integer to memory starting at p[0].
112220114239
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
112221114240
** The number of bytes written is returned.
112222114241
*/
@@ -112545,10 +114564,13 @@
112545114564
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
112546114565
if( rc==SQLITE_OK ){
112547114566
sqlite3_step(pStmt);
112548114567
p->nPgsz = sqlite3_column_int(pStmt, 0);
112549114568
rc = sqlite3_finalize(pStmt);
114569
+ }else if( rc==SQLITE_AUTH ){
114570
+ p->nPgsz = 1024;
114571
+ rc = SQLITE_OK;
112550114572
}
112551114573
}
112552114574
assert( p->nPgsz>0 || rc!=SQLITE_OK );
112553114575
sqlite3_free(zSql);
112554114576
*pRc = rc;
@@ -112718,31 +114740,60 @@
112718114740
}
112719114741
sqlite3_free(zFree);
112720114742
return zRet;
112721114743
}
112722114744
114745
+/*
114746
+** This function interprets the string at (*pp) as a non-negative integer
114747
+** value. It reads the integer and sets *pnOut to the value read, then
114748
+** sets *pp to point to the byte immediately following the last byte of
114749
+** the integer value.
114750
+**
114751
+** Only decimal digits ('0'..'9') may be part of an integer value.
114752
+**
114753
+** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
114754
+** the output value undefined. Otherwise SQLITE_OK is returned.
114755
+**
114756
+** This function is used when parsing the "prefix=" FTS4 parameter.
114757
+*/
112723114758
static int fts3GobbleInt(const char **pp, int *pnOut){
112724
- const char *p = *pp;
112725
- int nInt = 0;
114759
+ const char *p = *pp; /* Iterator pointer */
114760
+ int nInt = 0; /* Output value */
114761
+
112726114762
for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
112727114763
nInt = nInt * 10 + (p[0] - '0');
112728114764
}
112729114765
if( p==*pp ) return SQLITE_ERROR;
112730114766
*pnOut = nInt;
112731114767
*pp = p;
112732114768
return SQLITE_OK;
112733114769
}
112734114770
112735
-
114771
+/*
114772
+** This function is called to allocate an array of Fts3Index structures
114773
+** representing the indexes maintained by the current FTS table. FTS tables
114774
+** always maintain the main "terms" index, but may also maintain one or
114775
+** more "prefix" indexes, depending on the value of the "prefix=" parameter
114776
+** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
114777
+**
114778
+** Argument zParam is passed the value of the "prefix=" option if one was
114779
+** specified, or NULL otherwise.
114780
+**
114781
+** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
114782
+** the allocated array. *pnIndex is set to the number of elements in the
114783
+** array. If an error does occur, an SQLite error code is returned.
114784
+**
114785
+** Regardless of whether or not an error is returned, it is the responsibility
114786
+** of the caller to call sqlite3_free() on the output array to free it.
114787
+*/
112736114788
static int fts3PrefixParameter(
112737114789
const char *zParam, /* ABC in prefix=ABC parameter to parse */
112738114790
int *pnIndex, /* OUT: size of *apIndex[] array */
112739
- struct Fts3Index **apIndex, /* OUT: Array of indexes for this table */
112740
- struct Fts3Index **apFree /* OUT: Free this with sqlite3_free() */
114791
+ struct Fts3Index **apIndex /* OUT: Array of indexes for this table */
112741114792
){
112742
- struct Fts3Index *aIndex;
112743
- int nIndex = 1;
114793
+ struct Fts3Index *aIndex; /* Allocated array */
114794
+ int nIndex = 1; /* Number of entries in array */
112744114795
112745114796
if( zParam && zParam[0] ){
112746114797
const char *p;
112747114798
nIndex++;
112748114799
for(p=zParam; *p; p++){
@@ -112749,11 +114800,11 @@
112749114800
if( *p==',' ) nIndex++;
112750114801
}
112751114802
}
112752114803
112753114804
aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
112754
- *apIndex = *apFree = aIndex;
114805
+ *apIndex = aIndex;
112755114806
*pnIndex = nIndex;
112756114807
if( !aIndex ){
112757114808
return SQLITE_NOMEM;
112758114809
}
112759114810
@@ -112806,12 +114857,11 @@
112806114857
int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
112807114858
const char **aCol; /* Array of column names */
112808114859
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
112809114860
112810114861
int nIndex; /* Size of aIndex[] array */
112811
- struct Fts3Index *aIndex; /* Array of indexes for this table */
112812
- struct Fts3Index *aFree = 0; /* Free this before returning */
114862
+ struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
112813114863
112814114864
/* The results of parsing supported FTS4 key=value options: */
112815114865
int bNoDocsize = 0; /* True to omit %_docsize table */
112816114866
int bDescIdx = 0; /* True to store descending indexes */
112817114867
char *zPrefix = 0; /* Prefix parameter value (or NULL) */
@@ -112944,11 +114994,11 @@
112944114994
rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
112945114995
if( rc!=SQLITE_OK ) goto fts3_init_out;
112946114996
}
112947114997
assert( pTokenizer );
112948114998
112949
- rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
114999
+ rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
112950115000
if( rc==SQLITE_ERROR ){
112951115001
assert( zPrefix );
112952115002
*pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
112953115003
}
112954115004
if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -112995,11 +115045,11 @@
112995115045
zCsr += nDb;
112996115046
112997115047
/* Fill in the azColumn array */
112998115048
for(iCol=0; iCol<nCol; iCol++){
112999115049
char *z;
113000
- int n;
115050
+ int n = 0;
113001115051
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
113002115052
memcpy(zCsr, z, n);
113003115053
zCsr[n] = '\0';
113004115054
sqlite3Fts3Dequote(zCsr);
113005115055
p->azColumn[iCol] = zCsr;
@@ -113031,11 +115081,11 @@
113031115081
/* Declare the table schema to SQLite. */
113032115082
fts3DeclareVtab(&rc, p);
113033115083
113034115084
fts3_init_out:
113035115085
sqlite3_free(zPrefix);
113036
- sqlite3_free(aFree);
115086
+ sqlite3_free(aIndex);
113037115087
sqlite3_free(zCompress);
113038115088
sqlite3_free(zUncompress);
113039115089
sqlite3_free((void *)aCol);
113040115090
if( rc!=SQLITE_OK ){
113041115091
if( p ){
@@ -113622,12 +115672,10 @@
113622115672
*pp1 = p1 + 1;
113623115673
*pp2 = p2 + 1;
113624115674
}
113625115675
113626115676
/*
113627
-** nToken==1 searches for adjacent positions.
113628
-**
113629115677
** This function is used to merge two position lists into one. When it is
113630115678
** called, *pp1 and *pp2 must both point to position lists. A position-list is
113631115679
** the part of a doclist that follows each document id. For example, if a row
113632115680
** contains:
113633115681
**
@@ -113643,10 +115691,12 @@
113643115691
** If isSaveLeft is 0, an entry is added to the output position list for
113644115692
** each position in *pp2 for which there exists one or more positions in
113645115693
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
113646115694
** when the *pp1 token appears before the *pp2 token, but not more than nToken
113647115695
** slots before it.
115696
+**
115697
+** e.g. nToken==1 searches for adjacent positions.
113648115698
*/
113649115699
static int fts3PoslistPhraseMerge(
113650115700
char **pp, /* IN/OUT: Preallocated output buffer */
113651115701
int nToken, /* Maximum difference in token positions */
113652115702
int isSaveLeft, /* Save the left position */
@@ -113809,26 +115859,38 @@
113809115859
113810115860
return res;
113811115861
}
113812115862
113813115863
/*
113814
-** A pointer to an instance of this structure is used as the context
113815
-** argument to sqlite3Fts3SegReaderIterate()
115864
+** An instance of this function is used to merge together the (potentially
115865
+** large number of) doclists for each term that matches a prefix query.
115866
+** See function fts3TermSelectMerge() for details.
113816115867
*/
113817115868
typedef struct TermSelect TermSelect;
113818115869
struct TermSelect {
113819
- int isReqPos;
113820
- char *aaOutput[16]; /* Malloc'd output buffer */
113821
- int anOutput[16]; /* Size of output in bytes */
115870
+ char *aaOutput[16]; /* Malloc'd output buffers */
115871
+ int anOutput[16]; /* Size each output buffer in bytes */
113822115872
};
113823115873
113824
-
115874
+/*
115875
+** This function is used to read a single varint from a buffer. Parameter
115876
+** pEnd points 1 byte past the end of the buffer. When this function is
115877
+** called, if *pp points to pEnd or greater, then the end of the buffer
115878
+** has been reached. In this case *pp is set to 0 and the function returns.
115879
+**
115880
+** If *pp does not point to or past pEnd, then a single varint is read
115881
+** from *pp. *pp is then set to point 1 byte past the end of the read varint.
115882
+**
115883
+** If bDescIdx is false, the value read is added to *pVal before returning.
115884
+** If it is true, the value read is subtracted from *pVal before this
115885
+** function returns.
115886
+*/
113825115887
static void fts3GetDeltaVarint3(
113826
- char **pp,
113827
- char *pEnd,
113828
- int bDescIdx,
113829
- sqlite3_int64 *pVal
115888
+ char **pp, /* IN/OUT: Point to read varint from */
115889
+ char *pEnd, /* End of buffer */
115890
+ int bDescIdx, /* True if docids are descending */
115891
+ sqlite3_int64 *pVal /* IN/OUT: Integer value */
113830115892
){
113831115893
if( *pp>=pEnd ){
113832115894
*pp = 0;
113833115895
}else{
113834115896
sqlite3_int64 iVal;
@@ -113839,10 +115901,25 @@
113839115901
*pVal += iVal;
113840115902
}
113841115903
}
113842115904
}
113843115905
115906
+/*
115907
+** This function is used to write a single varint to a buffer. The varint
115908
+** is written to *pp. Before returning, *pp is set to point 1 byte past the
115909
+** end of the value written.
115910
+**
115911
+** If *pbFirst is zero when this function is called, the value written to
115912
+** the buffer is that of parameter iVal.
115913
+**
115914
+** If *pbFirst is non-zero when this function is called, then the value
115915
+** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
115916
+** (if bDescIdx is non-zero).
115917
+**
115918
+** Before returning, this function always sets *pbFirst to 1 and *piPrev
115919
+** to the value of parameter iVal.
115920
+*/
113844115921
static void fts3PutDeltaVarint3(
113845115922
char **pp, /* IN/OUT: Output pointer */
113846115923
int bDescIdx, /* True for descending docids */
113847115924
sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
113848115925
int *pbFirst, /* IN/OUT: True after first int written */
@@ -113859,14 +115936,38 @@
113859115936
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
113860115937
*piPrev = iVal;
113861115938
*pbFirst = 1;
113862115939
}
113863115940
113864
-#define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))
113865115941
115942
+/*
115943
+** This macro is used by various functions that merge doclists. The two
115944
+** arguments are 64-bit docid values. If the value of the stack variable
115945
+** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
115946
+** Otherwise, (i2-i1).
115947
+**
115948
+** Using this makes it easier to write code that can merge doclists that are
115949
+** sorted in either ascending or descending order.
115950
+*/
115951
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
115952
+
115953
+/*
115954
+** This function does an "OR" merge of two doclists (output contains all
115955
+** positions contained in either argument doclist). If the docids in the
115956
+** input doclists are sorted in ascending order, parameter bDescDoclist
115957
+** should be false. If they are sorted in ascending order, it should be
115958
+** passed a non-zero value.
115959
+**
115960
+** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
115961
+** containing the output doclist and SQLITE_OK is returned. In this case
115962
+** *pnOut is set to the number of bytes in the output doclist.
115963
+**
115964
+** If an error occurs, an SQLite error code is returned. The output values
115965
+** are undefined in this case.
115966
+*/
113866115967
static int fts3DoclistOrMerge(
113867
- int bDescIdx, /* True if arguments are desc */
115968
+ int bDescDoclist, /* True if arguments are desc */
113868115969
char *a1, int n1, /* First doclist */
113869115970
char *a2, int n2, /* Second doclist */
113870115971
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
113871115972
){
113872115973
sqlite3_int64 i1 = 0;
@@ -113887,35 +115988,47 @@
113887115988
113888115989
p = aOut;
113889115990
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113890115991
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113891115992
while( p1 || p2 ){
113892
- sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
115993
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
113893115994
113894115995
if( p2 && p1 && iDiff==0 ){
113895
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
115996
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
113896115997
fts3PoslistMerge(&p, &p1, &p2);
113897
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113898
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
115998
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
115999
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
113899116000
}else if( !p2 || (p1 && iDiff<0) ){
113900
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
116001
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
113901116002
fts3PoslistCopy(&p, &p1);
113902
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
116003
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
113903116004
}else{
113904
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
116005
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
113905116006
fts3PoslistCopy(&p, &p2);
113906
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
116007
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
113907116008
}
113908116009
}
113909116010
113910116011
*paOut = aOut;
113911116012
*pnOut = (p-aOut);
113912116013
return SQLITE_OK;
113913116014
}
113914116015
116016
+/*
116017
+** This function does a "phrase" merge of two doclists. In a phrase merge,
116018
+** the output contains a copy of each position from the right-hand input
116019
+** doclist for which there is a position in the left-hand input doclist
116020
+** exactly nDist tokens before it.
116021
+**
116022
+** If the docids in the input doclists are sorted in ascending order,
116023
+** parameter bDescDoclist should be false. If they are sorted in ascending
116024
+** order, it should be passed a non-zero value.
116025
+**
116026
+** The right-hand input doclist is overwritten by this function.
116027
+*/
113915116028
static void fts3DoclistPhraseMerge(
113916
- int bDescIdx, /* True if arguments are desc */
116029
+ int bDescDoclist, /* True if arguments are desc */
113917116030
int nDist, /* Distance from left to right (1=adjacent) */
113918116031
char *aLeft, int nLeft, /* Left doclist */
113919116032
char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
113920116033
){
113921116034
sqlite3_int64 i1 = 0;
@@ -113934,30 +116047,30 @@
113934116047
p = aOut;
113935116048
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113936116049
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113937116050
113938116051
while( p1 && p2 ){
113939
- sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
116052
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
113940116053
if( iDiff==0 ){
113941116054
char *pSave = p;
113942116055
sqlite3_int64 iPrevSave = iPrev;
113943116056
int bFirstOutSave = bFirstOut;
113944116057
113945
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
116058
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
113946116059
if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
113947116060
p = pSave;
113948116061
iPrev = iPrevSave;
113949116062
bFirstOut = bFirstOutSave;
113950116063
}
113951
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113952
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
116064
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
116065
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
113953116066
}else if( iDiff<0 ){
113954116067
fts3PoslistCopy(0, &p1);
113955
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
116068
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
113956116069
}else{
113957116070
fts3PoslistCopy(0, &p2);
113958
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
116071
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
113959116072
}
113960116073
}
113961116074
113962116075
*pnRight = p - aOut;
113963116076
}
@@ -113970,11 +116083,11 @@
113970116083
**
113971116084
** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
113972116085
** the responsibility of the caller to free any doclists left in the
113973116086
** TermSelect.aaOutput[] array.
113974116087
*/
113975
-static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
116088
+static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
113976116089
char *aOut = 0;
113977116090
int nOut = 0;
113978116091
int i;
113979116092
113980116093
/* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -114011,28 +116124,29 @@
114011116124
pTS->anOutput[0] = nOut;
114012116125
return SQLITE_OK;
114013116126
}
114014116127
114015116128
/*
114016
-** This function is used as the sqlite3Fts3SegReaderIterate() callback when
114017
-** querying the full-text index for a doclist associated with a term or
114018
-** term-prefix.
116129
+** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
116130
+** as the first argument. The merge is an "OR" merge (see function
116131
+** fts3DoclistOrMerge() for details).
116132
+**
116133
+** This function is called with the doclist for each term that matches
116134
+** a queried prefix. It merges all these doclists into one, the doclist
116135
+** for the specified prefix. Since there can be a very large number of
116136
+** doclists to merge, the merging is done pair-wise using the TermSelect
116137
+** object.
116138
+**
116139
+** This function returns SQLITE_OK if the merge is successful, or an
116140
+** SQLite error code (SQLITE_NOMEM) if an error occurs.
114019116141
*/
114020
-static int fts3TermSelectCb(
114021
- Fts3Table *p, /* Virtual table object */
114022
- void *pContext, /* Pointer to TermSelect structure */
114023
- char *zTerm,
114024
- int nTerm,
114025
- char *aDoclist,
114026
- int nDoclist
116142
+static int fts3TermSelectMerge(
116143
+ Fts3Table *p, /* FTS table handle */
116144
+ TermSelect *pTS, /* TermSelect object to merge into */
116145
+ char *aDoclist, /* Pointer to doclist */
116146
+ int nDoclist /* Size of aDoclist in bytes */
114027116147
){
114028
- TermSelect *pTS = (TermSelect *)pContext;
114029
-
114030
- UNUSED_PARAMETER(p);
114031
- UNUSED_PARAMETER(zTerm);
114032
- UNUSED_PARAMETER(nTerm);
114033
-
114034116148
if( pTS->aaOutput[0]==0 ){
114035116149
/* If this is the first term selected, copy the doclist to the output
114036116150
** buffer using memcpy(). */
114037116151
pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
114038116152
pTS->anOutput[0] = nDoclist;
@@ -114099,23 +116213,30 @@
114099116213
}
114100116214
pCsr->apSegment[pCsr->nSegment++] = pNew;
114101116215
return SQLITE_OK;
114102116216
}
114103116217
116218
+/*
116219
+** Add seg-reader objects to the Fts3MultiSegReader object passed as the
116220
+** 8th argument.
116221
+**
116222
+** This function returns SQLITE_OK if successful, or an SQLite error code
116223
+** otherwise.
116224
+*/
114104116225
static int fts3SegReaderCursor(
114105116226
Fts3Table *p, /* FTS3 table handle */
114106116227
int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114107116228
int iLevel, /* Level of segments to scan */
114108116229
const char *zTerm, /* Term to query for */
114109116230
int nTerm, /* Size of zTerm in bytes */
114110116231
int isPrefix, /* True for a prefix search */
114111116232
int isScan, /* True to scan from zTerm to EOF */
114112
- Fts3MultiSegReader *pCsr /* Cursor object to populate */
116233
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
114113116234
){
114114
- int rc = SQLITE_OK;
114115
- int rc2;
114116
- sqlite3_stmt *pStmt = 0;
116235
+ int rc = SQLITE_OK; /* Error code */
116236
+ sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
116237
+ int rc2; /* Result of sqlite3_reset() */
114117116238
114118116239
/* If iLevel is less than 0 and this is not a scan, include a seg-reader
114119116240
** for the pending-terms. If this is a scan, then this call must be being
114120116241
** made by an fts4aux module, not an FTS table. In this case calling
114121116242
** Fts3SegReaderPending might segfault, as the data structures used by
@@ -114200,28 +116321,46 @@
114200116321
return fts3SegReaderCursor(
114201116322
p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
114202116323
);
114203116324
}
114204116325
116326
+/*
116327
+** In addition to its current configuration, have the Fts3MultiSegReader
116328
+** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
116329
+**
116330
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
116331
+*/
114205116332
static int fts3SegReaderCursorAddZero(
114206
- Fts3Table *p,
114207
- const char *zTerm,
114208
- int nTerm,
114209
- Fts3MultiSegReader *pCsr
116333
+ Fts3Table *p, /* FTS virtual table handle */
116334
+ const char *zTerm, /* Term to scan doclist of */
116335
+ int nTerm, /* Number of bytes in zTerm */
116336
+ Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
114210116337
){
114211116338
return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
114212116339
}
114213116340
114214
-
114215
-SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
116341
+/*
116342
+** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
116343
+** if isPrefix is true, to scan the doclist for all terms for which
116344
+** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
116345
+** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
116346
+** an SQLite error code.
116347
+**
116348
+** It is the responsibility of the caller to free this object by eventually
116349
+** passing it to fts3SegReaderCursorFree()
116350
+**
116351
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
116352
+** Output parameter *ppSegcsr is set to 0 if an error occurs.
116353
+*/
116354
+static int fts3TermSegReaderCursor(
114216116355
Fts3Cursor *pCsr, /* Virtual table cursor handle */
114217116356
const char *zTerm, /* Term to query for */
114218116357
int nTerm, /* Size of zTerm in bytes */
114219116358
int isPrefix, /* True for a prefix search */
114220116359
Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
114221116360
){
114222
- Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
116361
+ Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114223116362
int rc = SQLITE_NOMEM; /* Return code */
114224116363
114225116364
pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
114226116365
if( pSegcsr ){
114227116366
int i;
@@ -114261,62 +116400,53 @@
114261116400
114262116401
*ppSegcsr = pSegcsr;
114263116402
return rc;
114264116403
}
114265116404
116405
+/*
116406
+** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
116407
+*/
114266116408
static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
114267116409
sqlite3Fts3SegReaderFinish(pSegcsr);
114268116410
sqlite3_free(pSegcsr);
114269116411
}
114270116412
114271116413
/*
114272116414
** This function retreives the doclist for the specified term (or term
114273
-** prefix) from the database.
114274
-**
114275
-** The returned doclist may be in one of two formats, depending on the
114276
-** value of parameter isReqPos. If isReqPos is zero, then the doclist is
114277
-** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
114278
-** is non-zero, then the returned list is in the same format as is stored
114279
-** in the database without the found length specifier at the start of on-disk
114280
-** doclists.
116415
+** prefix) from the database.
114281116416
*/
114282116417
static int fts3TermSelect(
114283116418
Fts3Table *p, /* Virtual table handle */
114284116419
Fts3PhraseToken *pTok, /* Token to query for */
114285116420
int iColumn, /* Column to query (or -ve for all columns) */
114286
- int isReqPos, /* True to include position lists in output */
114287116421
int *pnOut, /* OUT: Size of buffer at *ppOut */
114288116422
char **ppOut /* OUT: Malloced result buffer */
114289116423
){
114290116424
int rc; /* Return code */
114291
- Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114292
- TermSelect tsc; /* Context object for fts3TermSelectCb() */
116425
+ Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
116426
+ TermSelect tsc; /* Object for pair-wise doclist merging */
114293116427
Fts3SegFilter filter; /* Segment term filter configuration */
114294116428
114295116429
pSegcsr = pTok->pSegcsr;
114296116430
memset(&tsc, 0, sizeof(TermSelect));
114297
- tsc.isReqPos = isReqPos;
114298116431
114299
- filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
116432
+ filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
114300116433
| (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
114301
- | (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
114302116434
| (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
114303116435
filter.iCol = iColumn;
114304116436
filter.zTerm = pTok->z;
114305116437
filter.nTerm = pTok->n;
114306116438
114307116439
rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
114308116440
while( SQLITE_OK==rc
114309116441
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
114310116442
){
114311
- rc = fts3TermSelectCb(p, (void *)&tsc,
114312
- pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
114313
- );
116443
+ rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
114314116444
}
114315116445
114316116446
if( rc==SQLITE_OK ){
114317
- rc = fts3TermSelectMerge(p, &tsc);
116447
+ rc = fts3TermSelectFinishMerge(p, &tsc);
114318116448
}
114319116449
if( rc==SQLITE_OK ){
114320116450
*ppOut = tsc.aaOutput[0];
114321116451
*pnOut = tsc.anOutput[0];
114322116452
}else{
@@ -114338,28 +116468,19 @@
114338116468
** If the isPoslist argument is true, then it is assumed that the doclist
114339116469
** contains a position-list following each docid. Otherwise, it is assumed
114340116470
** that the doclist is simply a list of docids stored as delta encoded
114341116471
** varints.
114342116472
*/
114343
-static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
116473
+static int fts3DoclistCountDocids(char *aList, int nList){
114344116474
int nDoc = 0; /* Return value */
114345116475
if( aList ){
114346116476
char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
114347116477
char *p = aList; /* Cursor */
114348
- if( !isPoslist ){
114349
- /* The number of docids in the list is the same as the number of
114350
- ** varints. In FTS3 a varint consists of a single byte with the 0x80
114351
- ** bit cleared and zero or more bytes with the 0x80 bit set. So to
114352
- ** count the varints in the buffer, just count the number of bytes
114353
- ** with the 0x80 bit clear. */
114354
- while( p<aEnd ) nDoc += (((*p++)&0x80)==0);
114355
- }else{
114356
- while( p<aEnd ){
114357
- nDoc++;
114358
- while( (*p++)&0x80 ); /* Skip docid varint */
114359
- fts3PoslistCopy(0, &p); /* Skip over position list */
114360
- }
116478
+ while( p<aEnd ){
116479
+ nDoc++;
116480
+ while( (*p++)&0x80 ); /* Skip docid varint */
116481
+ fts3PoslistCopy(0, &p); /* Skip over position list */
114361116482
}
114362116483
}
114363116484
114364116485
return nDoc;
114365116486
}
@@ -114385,11 +116506,11 @@
114385116506
}else{
114386116507
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114387116508
rc = SQLITE_OK;
114388116509
}
114389116510
}else{
114390
- rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
116511
+ rc = fts3EvalNext((Fts3Cursor *)pCursor);
114391116512
}
114392116513
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
114393116514
return rc;
114394116515
}
114395116516
@@ -114462,11 +116583,11 @@
114462116583
}
114463116584
114464116585
rc = sqlite3Fts3ReadLock(p);
114465116586
if( rc!=SQLITE_OK ) return rc;
114466116587
114467
- rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
116588
+ rc = fts3EvalStart(pCsr);
114468116589
114469116590
sqlite3Fts3SegmentsClose(p);
114470116591
if( rc!=SQLITE_OK ) return rc;
114471116592
pCsr->pNextId = pCsr->aDoclist;
114472116593
pCsr->iPrevId = 0;
@@ -114581,12 +116702,12 @@
114581116702
114582116703
/*
114583116704
** Implementation of xBegin() method. This is a no-op.
114584116705
*/
114585116706
static int fts3BeginMethod(sqlite3_vtab *pVtab){
114586
- UNUSED_PARAMETER(pVtab);
114587116707
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
116708
+ UNUSED_PARAMETER(pVtab);
114588116709
assert( p->pSegments==0 );
114589116710
assert( p->nPendingData==0 );
114590116711
assert( p->inTransaction!=1 );
114591116712
TESTONLY( p->inTransaction = 1 );
114592116713
TESTONLY( p->mxSavepoint = -1; );
@@ -114597,12 +116718,12 @@
114597116718
** Implementation of xCommit() method. This is a no-op. The contents of
114598116719
** the pending-terms hash-table have already been flushed into the database
114599116720
** by fts3SyncMethod().
114600116721
*/
114601116722
static int fts3CommitMethod(sqlite3_vtab *pVtab){
114602
- UNUSED_PARAMETER(pVtab);
114603116723
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
116724
+ UNUSED_PARAMETER(pVtab);
114604116725
assert( p->nPendingData==0 );
114605116726
assert( p->inTransaction!=0 );
114606116727
assert( p->pSegments==0 );
114607116728
TESTONLY( p->inTransaction = 0 );
114608116729
TESTONLY( p->mxSavepoint = -1; );
@@ -114869,26 +116990,43 @@
114869116990
p->zDb, p->zName, zName
114870116991
);
114871116992
return rc;
114872116993
}
114873116994
116995
+/*
116996
+** The xSavepoint() method.
116997
+**
116998
+** Flush the contents of the pending-terms table to disk.
116999
+*/
114874117000
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
114875117001
UNUSED_PARAMETER(iSavepoint);
114876117002
assert( ((Fts3Table *)pVtab)->inTransaction );
114877117003
assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
114878117004
TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
114879117005
return fts3SyncMethod(pVtab);
114880117006
}
117007
+
117008
+/*
117009
+** The xRelease() method.
117010
+**
117011
+** This is a no-op.
117012
+*/
114881117013
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
114882117014
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114883117015
UNUSED_PARAMETER(iSavepoint);
114884117016
UNUSED_PARAMETER(pVtab);
114885117017
assert( p->inTransaction );
114886117018
assert( p->mxSavepoint >= iSavepoint );
114887117019
TESTONLY( p->mxSavepoint = iSavepoint-1 );
114888117020
return SQLITE_OK;
114889117021
}
117022
+
117023
+/*
117024
+** The xRollbackTo() method.
117025
+**
117026
+** Discard the contents of the pending terms table.
117027
+*/
114890117028
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
114891117029
Fts3Table *p = (Fts3Table*)pVtab;
114892117030
UNUSED_PARAMETER(iSavepoint);
114893117031
assert( p->inTransaction );
114894117032
assert( p->mxSavepoint >= iSavepoint );
@@ -115033,22 +117171,10 @@
115033117171
sqlite3Fts3HashClear(pHash);
115034117172
sqlite3_free(pHash);
115035117173
}
115036117174
return rc;
115037117175
}
115038
-
115039
-#if !SQLITE_CORE
115040
-SQLITE_API int sqlite3_extension_init(
115041
- sqlite3 *db,
115042
- char **pzErrMsg,
115043
- const sqlite3_api_routines *pApi
115044
-){
115045
- SQLITE_EXTENSION_INIT2(pApi)
115046
- return sqlite3Fts3Init(db);
115047
-}
115048
-#endif
115049
-
115050117176
115051117177
/*
115052117178
** Allocate an Fts3MultiSegReader for each token in the expression headed
115053117179
** by pExpr.
115054117180
**
@@ -115062,99 +117188,151 @@
115062117188
** there exists prefix b-tree of the right length) then it may be traversed
115063117189
** and merged incrementally. Otherwise, it has to be merged into an in-memory
115064117190
** doclist and then traversed.
115065117191
*/
115066117192
static void fts3EvalAllocateReaders(
115067
- Fts3Cursor *pCsr,
115068
- Fts3Expr *pExpr,
117193
+ Fts3Cursor *pCsr, /* FTS cursor handle */
117194
+ Fts3Expr *pExpr, /* Allocate readers for this expression */
115069117195
int *pnToken, /* OUT: Total number of tokens in phrase. */
115070117196
int *pnOr, /* OUT: Total number of OR nodes in expr. */
115071
- int *pRc
117197
+ int *pRc /* IN/OUT: Error code */
115072117198
){
115073117199
if( pExpr && SQLITE_OK==*pRc ){
115074117200
if( pExpr->eType==FTSQUERY_PHRASE ){
115075117201
int i;
115076117202
int nToken = pExpr->pPhrase->nToken;
115077117203
*pnToken += nToken;
115078117204
for(i=0; i<nToken; i++){
115079117205
Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
115080
- int rc = sqlite3Fts3TermSegReaderCursor(pCsr,
117206
+ int rc = fts3TermSegReaderCursor(pCsr,
115081117207
pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115082117208
);
115083117209
if( rc!=SQLITE_OK ){
115084117210
*pRc = rc;
115085117211
return;
115086117212
}
115087117213
}
117214
+ assert( pExpr->pPhrase->iDoclistToken==0 );
117215
+ pExpr->pPhrase->iDoclistToken = -1;
115088117216
}else{
115089117217
*pnOr += (pExpr->eType==FTSQUERY_OR);
115090117218
fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
115091117219
fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
115092117220
}
115093117221
}
115094117222
}
115095117223
117224
+/*
117225
+** Arguments pList/nList contain the doclist for token iToken of phrase p.
117226
+** It is merged into the main doclist stored in p->doclist.aAll/nAll.
117227
+**
117228
+** This function assumes that pList points to a buffer allocated using
117229
+** sqlite3_malloc(). This function takes responsibility for eventually
117230
+** freeing the buffer.
117231
+*/
117232
+static void fts3EvalPhraseMergeToken(
117233
+ Fts3Table *pTab, /* FTS Table pointer */
117234
+ Fts3Phrase *p, /* Phrase to merge pList/nList into */
117235
+ int iToken, /* Token pList/nList corresponds to */
117236
+ char *pList, /* Pointer to doclist */
117237
+ int nList /* Number of bytes in pList */
117238
+){
117239
+ assert( iToken!=p->iDoclistToken );
117240
+
117241
+ if( pList==0 ){
117242
+ sqlite3_free(p->doclist.aAll);
117243
+ p->doclist.aAll = 0;
117244
+ p->doclist.nAll = 0;
117245
+ }
117246
+
117247
+ else if( p->iDoclistToken<0 ){
117248
+ p->doclist.aAll = pList;
117249
+ p->doclist.nAll = nList;
117250
+ }
117251
+
117252
+ else if( p->doclist.aAll==0 ){
117253
+ sqlite3_free(pList);
117254
+ }
117255
+
117256
+ else {
117257
+ char *pLeft;
117258
+ char *pRight;
117259
+ int nLeft;
117260
+ int nRight;
117261
+ int nDiff;
117262
+
117263
+ if( p->iDoclistToken<iToken ){
117264
+ pLeft = p->doclist.aAll;
117265
+ nLeft = p->doclist.nAll;
117266
+ pRight = pList;
117267
+ nRight = nList;
117268
+ nDiff = iToken - p->iDoclistToken;
117269
+ }else{
117270
+ pRight = p->doclist.aAll;
117271
+ nRight = p->doclist.nAll;
117272
+ pLeft = pList;
117273
+ nLeft = nList;
117274
+ nDiff = p->iDoclistToken - iToken;
117275
+ }
117276
+
117277
+ fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight);
117278
+ sqlite3_free(pLeft);
117279
+ p->doclist.aAll = pRight;
117280
+ p->doclist.nAll = nRight;
117281
+ }
117282
+
117283
+ if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
117284
+}
117285
+
117286
+/*
117287
+** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
117288
+** does not take deferred tokens into account.
117289
+**
117290
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
117291
+*/
115096117292
static int fts3EvalPhraseLoad(
115097
- Fts3Cursor *pCsr,
115098
- Fts3Phrase *p
117293
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
117294
+ Fts3Phrase *p /* Phrase object */
115099117295
){
115100117296
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115101117297
int iToken;
115102117298
int rc = SQLITE_OK;
115103117299
115104
- char *aDoclist = 0;
115105
- int nDoclist = 0;
115106
- int iPrev = -1;
115107
-
115108117300
for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
115109117301
Fts3PhraseToken *pToken = &p->aToken[iToken];
115110
- assert( pToken->pSegcsr || pToken->pDeferred );
117302
+ assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
115111117303
115112
- if( pToken->pDeferred==0 ){
117304
+ if( pToken->pSegcsr ){
115113117305
int nThis = 0;
115114117306
char *pThis = 0;
115115
- rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
115116
- if( rc==SQLITE_OK ){
115117
- if( pThis==0 ){
115118
- sqlite3_free(aDoclist);
115119
- aDoclist = 0;
115120
- nDoclist = 0;
115121
- break;
115122
- }else if( aDoclist==0 ){
115123
- aDoclist = pThis;
115124
- nDoclist = nThis;
115125
- }else{
115126
- assert( iPrev>=0 );
115127
- fts3DoclistPhraseMerge(pTab->bDescIdx,
115128
- iToken-iPrev, aDoclist, nDoclist, pThis, &nThis
115129
- );
115130
- sqlite3_free(aDoclist);
115131
- aDoclist = pThis;
115132
- nDoclist = nThis;
115133
- }
115134
- iPrev = iToken;
115135
- }
115136
- }
115137
- }
115138
-
115139
- if( rc==SQLITE_OK ){
115140
- p->doclist.aAll = aDoclist;
115141
- p->doclist.nAll = nDoclist;
115142
- }else{
115143
- sqlite3_free(aDoclist);
115144
- }
115145
- return rc;
115146
-}
115147
-
117307
+ rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
117308
+ if( rc==SQLITE_OK ){
117309
+ fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
117310
+ }
117311
+ }
117312
+ assert( pToken->pSegcsr==0 );
117313
+ }
117314
+
117315
+ return rc;
117316
+}
117317
+
117318
+/*
117319
+** This function is called on each phrase after the position lists for
117320
+** any deferred tokens have been loaded into memory. It updates the phrases
117321
+** current position list to include only those positions that are really
117322
+** instances of the phrase (after considering deferred tokens). If this
117323
+** means that the phrase does not appear in the current row, doclist.pList
117324
+** and doclist.nList are both zeroed.
117325
+**
117326
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
117327
+*/
115148117328
static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
115149
- int iToken;
115150
- int rc = SQLITE_OK;
115151
-
115152
- int nMaxUndeferred = -1;
115153
- char *aPoslist = 0;
115154
- int nPoslist = 0;
115155
- int iPrev = -1;
117329
+ int iToken; /* Used to iterate through phrase tokens */
117330
+ int rc = SQLITE_OK; /* Return code */
117331
+ char *aPoslist = 0; /* Position list for deferred tokens */
117332
+ int nPoslist = 0; /* Number of bytes in aPoslist */
117333
+ int iPrev = -1; /* Token number of previous deferred token */
115156117334
115157117335
assert( pPhrase->doclist.bFreeList==0 );
115158117336
115159117337
for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
115160117338
Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -115192,16 +117370,15 @@
115192117370
pPhrase->doclist.nList = 0;
115193117371
return SQLITE_OK;
115194117372
}
115195117373
}
115196117374
iPrev = iToken;
115197
- }else{
115198
- nMaxUndeferred = iToken;
115199117375
}
115200117376
}
115201117377
115202117378
if( iPrev>=0 ){
117379
+ int nMaxUndeferred = pPhrase->iDoclistToken;
115203117380
if( nMaxUndeferred<0 ){
115204117381
pPhrase->doclist.pList = aPoslist;
115205117382
pPhrase->doclist.nList = nPoslist;
115206117383
pPhrase->doclist.iDocid = pCsr->iPrevId;
115207117384
pPhrase->doclist.bFreeList = 1;
@@ -115246,19 +117423,27 @@
115246117423
/*
115247117424
** This function is called for each Fts3Phrase in a full-text query
115248117425
** expression to initialize the mechanism for returning rows. Once this
115249117426
** function has been called successfully on an Fts3Phrase, it may be
115250117427
** used with fts3EvalPhraseNext() to iterate through the matching docids.
117428
+**
117429
+** If parameter bOptOk is true, then the phrase may (or may not) use the
117430
+** incremental loading strategy. Otherwise, the entire doclist is loaded into
117431
+** memory within this call.
117432
+**
117433
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
115251117434
*/
115252117435
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
115253
- int rc;
117436
+ int rc; /* Error code */
115254117437
Fts3PhraseToken *pFirst = &p->aToken[0];
115255117438
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115256117439
115257
- assert( p->doclist.aAll==0 );
115258
- if( pCsr->bDesc==pTab->bDescIdx && bOptOk==1 && p->nToken==1
115259
- && pFirst->pSegcsr && pFirst->pSegcsr->bLookup
117440
+ if( pCsr->bDesc==pTab->bDescIdx
117441
+ && bOptOk==1
117442
+ && p->nToken==1
117443
+ && pFirst->pSegcsr
117444
+ && pFirst->pSegcsr->bLookup
115260117445
){
115261117446
/* Use the incremental approach. */
115262117447
int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
115263117448
rc = sqlite3Fts3MsrIncrStart(
115264117449
pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
@@ -115274,11 +117459,17 @@
115274117459
return rc;
115275117460
}
115276117461
115277117462
/*
115278117463
** This function is used to iterate backwards (from the end to start)
115279
-** through doclists.
117464
+** through doclists. It is used by this module to iterate through phrase
117465
+** doclists in reverse and by the fts3_write.c module to iterate through
117466
+** pending-terms lists when writing to databases with "order=desc".
117467
+**
117468
+** The doclist may be sorted in ascending (parameter bDescIdx==0) or
117469
+** descending (parameter bDescIdx==1) order of docid. Regardless, this
117470
+** function iterates from the end of the doclist to the beginning.
115280117471
*/
115281117472
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
115282117473
int bDescIdx, /* True if the doclist is desc */
115283117474
char *aDoclist, /* Pointer to entire doclist */
115284117475
int nDoclist, /* Length of aDoclist in bytes */
@@ -115339,13 +117530,13 @@
115339117530
** If there is no "next" entry and no error occurs, then *pbEof is set to
115340117531
** 1 before returning. Otherwise, if no error occurs and the iterator is
115341117532
** successfully advanced, *pbEof is set to 0.
115342117533
*/
115343117534
static int fts3EvalPhraseNext(
115344
- Fts3Cursor *pCsr,
115345
- Fts3Phrase *p,
115346
- u8 *pbEof
117535
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
117536
+ Fts3Phrase *p, /* Phrase object to advance to next docid */
117537
+ u8 *pbEof /* OUT: Set to 1 if EOF */
115347117538
){
115348117539
int rc = SQLITE_OK;
115349117540
Fts3Doclist *pDL = &p->doclist;
115350117541
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115351117542
@@ -115387,30 +117578,46 @@
115387117578
fts3PoslistCopy(0, &pIter);
115388117579
pDL->nList = (pIter - pDL->pList);
115389117580
115390117581
/* pIter now points just past the 0x00 that terminates the position-
115391117582
** list for document pDL->iDocid. However, if this position-list was
115392
- ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
117583
+ ** edited in place by fts3EvalNearTrim(), then pIter may not actually
115393117584
** point to the start of the next docid value. The following line deals
115394117585
** with this case by advancing pIter past the zero-padding added by
115395
- ** fts3EvalNearTrim2(). */
117586
+ ** fts3EvalNearTrim(). */
115396117587
while( pIter<pEnd && *pIter==0 ) pIter++;
115397117588
115398117589
pDL->pNextDocid = pIter;
115399
- assert( *pIter || pIter>=&pDL->aAll[pDL->nAll] );
117590
+ assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
115400117591
*pbEof = 0;
115401117592
}
115402117593
}
115403117594
115404117595
return rc;
115405117596
}
115406117597
117598
+/*
117599
+**
117600
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
117601
+** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
117602
+** expression. Also the Fts3Expr.bDeferred variable is set to true for any
117603
+** expressions for which all descendent tokens are deferred.
117604
+**
117605
+** If parameter bOptOk is zero, then it is guaranteed that the
117606
+** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
117607
+** each phrase in the expression (subject to deferred token processing).
117608
+** Or, if bOptOk is non-zero, then one or more tokens within the expression
117609
+** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
117610
+**
117611
+** If an error occurs within this function, *pRc is set to an SQLite error
117612
+** code before returning.
117613
+*/
115407117614
static void fts3EvalStartReaders(
115408
- Fts3Cursor *pCsr,
115409
- Fts3Expr *pExpr,
115410
- int bOptOk,
115411
- int *pRc
117615
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
117616
+ Fts3Expr *pExpr, /* Expression to initialize phrases in */
117617
+ int bOptOk, /* True to enable incremental loading */
117618
+ int *pRc /* IN/OUT: Error code */
115412117619
){
115413117620
if( pExpr && SQLITE_OK==*pRc ){
115414117621
if( pExpr->eType==FTSQUERY_PHRASE ){
115415117622
int i;
115416117623
int nToken = pExpr->pPhrase->nToken;
@@ -115425,33 +117632,55 @@
115425117632
pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
115426117633
}
115427117634
}
115428117635
}
115429117636
115430
-
117637
+/*
117638
+** An array of the following structures is assembled as part of the process
117639
+** of selecting tokens to defer before the query starts executing (as part
117640
+** of the xFilter() method). There is one element in the array for each
117641
+** token in the FTS expression.
117642
+**
117643
+** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
117644
+** to phrases that are connected only by AND and NEAR operators (not OR or
117645
+** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
117646
+** separately. The root of a tokens AND/NEAR cluster is stored in
117647
+** Fts3TokenAndCost.pRoot.
117648
+*/
115431117649
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
115432117650
struct Fts3TokenAndCost {
115433
- Fts3PhraseToken *pToken;
115434
- Fts3Expr *pRoot;
115435
- int nOvfl;
115436
- int iCol;
117651
+ Fts3Phrase *pPhrase; /* The phrase the token belongs to */
117652
+ int iToken; /* Position of token in phrase */
117653
+ Fts3PhraseToken *pToken; /* The token itself */
117654
+ Fts3Expr *pRoot; /* Root of NEAR/AND cluster */
117655
+ int nOvfl; /* Number of overflow pages to load doclist */
117656
+ int iCol; /* The column the token must match */
115437117657
};
115438117658
117659
+/*
117660
+** This function is used to populate an allocated Fts3TokenAndCost array.
117661
+**
117662
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
117663
+** Otherwise, if an error occurs during execution, *pRc is set to an
117664
+** SQLite error code.
117665
+*/
115439117666
static void fts3EvalTokenCosts(
115440
- Fts3Cursor *pCsr,
115441
- Fts3Expr *pRoot,
115442
- Fts3Expr *pExpr,
115443
- Fts3TokenAndCost **ppTC,
115444
- Fts3Expr ***ppOr,
115445
- int *pRc
117667
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
117668
+ Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */
117669
+ Fts3Expr *pExpr, /* Expression to consider */
117670
+ Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */
117671
+ Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */
117672
+ int *pRc /* IN/OUT: Error code */
115446117673
){
115447117674
if( *pRc==SQLITE_OK && pExpr ){
115448117675
if( pExpr->eType==FTSQUERY_PHRASE ){
115449117676
Fts3Phrase *pPhrase = pExpr->pPhrase;
115450117677
int i;
115451117678
for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
115452117679
Fts3TokenAndCost *pTC = (*ppTC)++;
117680
+ pTC->pPhrase = pPhrase;
117681
+ pTC->iToken = i;
115453117682
pTC->pRoot = pRoot;
115454117683
pTC->pToken = &pPhrase->aToken[i];
115455117684
pTC->iCol = pPhrase->iColumn;
115456117685
*pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
115457117686
}
@@ -115470,23 +117699,34 @@
115470117699
fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
115471117700
}
115472117701
}
115473117702
}
115474117703
117704
+/*
117705
+** Determine the average document (row) size in pages. If successful,
117706
+** write this value to *pnPage and return SQLITE_OK. Otherwise, return
117707
+** an SQLite error code.
117708
+**
117709
+** The average document size in pages is calculated by first calculating
117710
+** determining the average size in bytes, B. If B is less than the amount
117711
+** of data that will fit on a single leaf page of an intkey table in
117712
+** this database, then the average docsize is 1. Otherwise, it is 1 plus
117713
+** the number of overflow pages consumed by a record B bytes in size.
117714
+*/
115475117715
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
115476117716
if( pCsr->nRowAvg==0 ){
115477117717
/* The average document size, which is required to calculate the cost
115478
- ** of each doclist, has not yet been determined. Read the required
115479
- ** data from the %_stat table to calculate it.
115480
- **
115481
- ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
115482
- ** varints, where nCol is the number of columns in the FTS3 table.
115483
- ** The first varint is the number of documents currently stored in
115484
- ** the table. The following nCol varints contain the total amount of
115485
- ** data stored in all rows of each column of the table, from left
115486
- ** to right.
115487
- */
117718
+ ** of each doclist, has not yet been determined. Read the required
117719
+ ** data from the %_stat table to calculate it.
117720
+ **
117721
+ ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
117722
+ ** varints, where nCol is the number of columns in the FTS3 table.
117723
+ ** The first varint is the number of documents currently stored in
117724
+ ** the table. The following nCol varints contain the total amount of
117725
+ ** data stored in all rows of each column of the table, from left
117726
+ ** to right.
117727
+ */
115488117728
int rc;
115489117729
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
115490117730
sqlite3_stmt *pStmt;
115491117731
sqlite3_int64 nDoc = 0;
115492117732
sqlite3_int64 nByte = 0;
@@ -115517,113 +117757,151 @@
115517117757
115518117758
*pnPage = pCsr->nRowAvg;
115519117759
return SQLITE_OK;
115520117760
}
115521117761
117762
+/*
117763
+** This function is called to select the tokens (if any) that will be
117764
+** deferred. The array aTC[] has already been populated when this is
117765
+** called.
117766
+**
117767
+** This function is called once for each AND/NEAR cluster in the
117768
+** expression. Each invocation determines which tokens to defer within
117769
+** the cluster with root node pRoot. See comments above the definition
117770
+** of struct Fts3TokenAndCost for more details.
117771
+**
117772
+** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
117773
+** called on each token to defer. Otherwise, an SQLite error code is
117774
+** returned.
117775
+*/
115522117776
static int fts3EvalSelectDeferred(
115523
- Fts3Cursor *pCsr,
115524
- Fts3Expr *pRoot,
115525
- Fts3TokenAndCost *aTC,
115526
- int nTC
117777
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
117778
+ Fts3Expr *pRoot, /* Consider tokens with this root node */
117779
+ Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */
117780
+ int nTC /* Number of entries in aTC[] */
115527117781
){
115528
- int nDocSize = 0;
115529
- int nDocEst = 0;
115530
- int rc = SQLITE_OK;
115531117782
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115532
- int ii;
117783
+ int nDocSize = 0; /* Number of pages per doc loaded */
117784
+ int rc = SQLITE_OK; /* Return code */
117785
+ int ii; /* Iterator variable for various purposes */
117786
+ int nOvfl = 0; /* Total overflow pages used by doclists */
117787
+ int nToken = 0; /* Total number of tokens in cluster */
115533117788
115534
- int nOvfl = 0;
115535
- int nTerm = 0;
117789
+ int nMinEst = 0; /* The minimum count for any phrase so far. */
117790
+ int nLoad4 = 1; /* (Phrases that will be loaded)^4. */
115536117791
117792
+ /* Count the tokens in this AND/NEAR cluster. If none of the doclists
117793
+ ** associated with the tokens spill onto overflow pages, or if there is
117794
+ ** only 1 token, exit early. No tokens to defer in this case. */
115537117795
for(ii=0; ii<nTC; ii++){
115538117796
if( aTC[ii].pRoot==pRoot ){
115539117797
nOvfl += aTC[ii].nOvfl;
115540
- nTerm++;
117798
+ nToken++;
115541117799
}
115542117800
}
115543
- if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
117801
+ if( nOvfl==0 || nToken<2 ) return SQLITE_OK;
115544117802
117803
+ /* Obtain the average docsize (in pages). */
115545117804
rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
115546
-
115547
- for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
115548
- int jj;
115549
- Fts3TokenAndCost *pTC = 0;
115550
-
115551
- for(jj=0; jj<nTC; jj++){
115552
- if( aTC[jj].pToken && aTC[jj].pRoot==pRoot
115553
- && (!pTC || aTC[jj].nOvfl<pTC->nOvfl)
117805
+ assert( rc!=SQLITE_OK || nDocSize>0 );
117806
+
117807
+
117808
+ /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
117809
+ ** of the number of overflow pages that will be loaded by the pager layer
117810
+ ** to retrieve the entire doclist for the token from the full-text index.
117811
+ ** Load the doclists for tokens that are either:
117812
+ **
117813
+ ** a. The cheapest token in the entire query (i.e. the one visited by the
117814
+ ** first iteration of this loop), or
117815
+ **
117816
+ ** b. Part of a multi-token phrase.
117817
+ **
117818
+ ** After each token doclist is loaded, merge it with the others from the
117819
+ ** same phrase and count the number of documents that the merged doclist
117820
+ ** contains. Set variable "nMinEst" to the smallest number of documents in
117821
+ ** any phrase doclist for which 1 or more token doclists have been loaded.
117822
+ ** Let nOther be the number of other phrases for which it is certain that
117823
+ ** one or more tokens will not be deferred.
117824
+ **
117825
+ ** Then, for each token, defer it if loading the doclist would result in
117826
+ ** loading N or more overflow pages into memory, where N is computed as:
117827
+ **
117828
+ ** (nMinEst + 4^nOther - 1) / (4^nOther)
117829
+ */
117830
+ for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
117831
+ int iTC; /* Used to iterate through aTC[] array. */
117832
+ Fts3TokenAndCost *pTC = 0; /* Set to cheapest remaining token. */
117833
+
117834
+ /* Set pTC to point to the cheapest remaining token. */
117835
+ for(iTC=0; iTC<nTC; iTC++){
117836
+ if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
117837
+ && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
115554117838
){
115555
- pTC = &aTC[jj];
117839
+ pTC = &aTC[iTC];
115556117840
}
115557117841
}
115558117842
assert( pTC );
115559117843
115560
- /* At this point pTC points to the cheapest remaining token. */
115561
- if( ii==0 ){
115562
- if( pTC->nOvfl ){
115563
- nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
115564
- }else{
115565
- /* TODO: Fix this so that the doclist need not be read twice. */
117844
+ if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
117845
+ /* The number of overflow pages to load for this (and therefore all
117846
+ ** subsequent) tokens is greater than the estimated number of pages
117847
+ ** that will be loaded if all subsequent tokens are deferred.
117848
+ */
117849
+ Fts3PhraseToken *pToken = pTC->pToken;
117850
+ rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
117851
+ fts3SegReaderCursorFree(pToken->pSegcsr);
117852
+ pToken->pSegcsr = 0;
117853
+ }else{
117854
+ nLoad4 = nLoad4*4;
117855
+ if( ii==0 || pTC->pPhrase->nToken>1 ){
117856
+ /* Either this is the cheapest token in the entire query, or it is
117857
+ ** part of a multi-token phrase. Either way, the entire doclist will
117858
+ ** (eventually) be loaded into memory. It may as well be now. */
115566117859
Fts3PhraseToken *pToken = pTC->pToken;
115567117860
int nList = 0;
115568117861
char *pList = 0;
115569
- rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
115570
- if( rc==SQLITE_OK ){
115571
- nDocEst = fts3DoclistCountDocids(1, pList, nList);
115572
- }
115573
- sqlite3_free(pList);
115574
- if( rc==SQLITE_OK ){
115575
- rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115576
- pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
117862
+ rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
117863
+ assert( rc==SQLITE_OK || pList==0 );
117864
+ if( rc==SQLITE_OK ){
117865
+ int nCount;
117866
+ fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
117867
+ nCount = fts3DoclistCountDocids(
117868
+ pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
115577117869
);
117870
+ if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
115578117871
}
115579117872
}
115580
- }else{
115581
- if( pTC->nOvfl>=(nDocEst*nDocSize) ){
115582
- Fts3PhraseToken *pToken = pTC->pToken;
115583
- rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
115584
- fts3SegReaderCursorFree(pToken->pSegcsr);
115585
- pToken->pSegcsr = 0;
115586
- }
115587
- nDocEst = 1 + (nDocEst/4);
115588117873
}
115589117874
pTC->pToken = 0;
115590117875
}
115591117876
115592117877
return rc;
115593117878
}
115594117879
115595
-SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
117880
+/*
117881
+** This function is called from within the xFilter method. It initializes
117882
+** the full-text query currently stored in pCsr->pExpr. To iterate through
117883
+** the results of a query, the caller does:
117884
+**
117885
+** fts3EvalStart(pCsr);
117886
+** while( 1 ){
117887
+** fts3EvalNext(pCsr);
117888
+** if( pCsr->bEof ) break;
117889
+** ... return row pCsr->iPrevId to the caller ...
117890
+** }
117891
+*/
117892
+static int fts3EvalStart(Fts3Cursor *pCsr){
115596117893
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115597117894
int rc = SQLITE_OK;
115598117895
int nToken = 0;
115599117896
int nOr = 0;
115600117897
115601117898
/* Allocate a MultiSegReader for each token in the expression. */
115602
- fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
115603
-
115604
- /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
115605
- ** This call will eventually also be responsible for determining which
115606
- ** tokens are 'deferred' until the document text is loaded into memory.
115607
- **
115608
- ** Each token in each phrase is dealt with using one of the following
115609
- ** three strategies:
115610
- **
115611
- ** 1. Entire doclist loaded into memory as part of the
115612
- ** fts3EvalStartReaders() call.
115613
- **
115614
- ** 2. Doclist loaded into memory incrementally, as part of each
115615
- ** sqlite3Fts3EvalNext() call.
115616
- **
115617
- ** 3. Token doclist is never loaded. Instead, documents are loaded into
115618
- ** memory and scanned for the token as part of the sqlite3Fts3EvalNext()
115619
- ** call. This is known as a "deferred" token.
115620
- */
115621
-
115622
- /* If bOptOk is true, check if there are any tokens that should be deferred.
115623
- */
115624
- if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
117899
+ fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
117900
+
117901
+ /* Determine which, if any, tokens in the expression should be deferred. */
117902
+ if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
115625117903
Fts3TokenAndCost *aTC;
115626117904
Fts3Expr **apOr;
115627117905
aTC = (Fts3TokenAndCost *)sqlite3_malloc(
115628117906
sizeof(Fts3TokenAndCost) * nToken
115629117907
+ sizeof(Fts3Expr *) * nOr * 2
@@ -115635,11 +117913,11 @@
115635117913
}else{
115636117914
int ii;
115637117915
Fts3TokenAndCost *pTC = aTC;
115638117916
Fts3Expr **ppOr = apOr;
115639117917
115640
- fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
117918
+ fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
115641117919
nToken = pTC-aTC;
115642117920
nOr = ppOr-apOr;
115643117921
115644117922
if( rc==SQLITE_OK ){
115645117923
rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
@@ -115650,25 +117928,50 @@
115650117928
115651117929
sqlite3_free(aTC);
115652117930
}
115653117931
}
115654117932
115655
- fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
117933
+ fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
115656117934
return rc;
115657117935
}
115658117936
115659
-static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
117937
+/*
117938
+** Invalidate the current position list for phrase pPhrase.
117939
+*/
117940
+static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
115660117941
if( pPhrase->doclist.bFreeList ){
115661117942
sqlite3_free(pPhrase->doclist.pList);
115662117943
}
115663117944
pPhrase->doclist.pList = 0;
115664117945
pPhrase->doclist.nList = 0;
115665117946
pPhrase->doclist.bFreeList = 0;
115666117947
}
115667117948
115668
-static int fts3EvalNearTrim2(
115669
- int nNear,
117949
+/*
117950
+** This function is called to edit the position list associated with
117951
+** the phrase object passed as the fifth argument according to a NEAR
117952
+** condition. For example:
117953
+**
117954
+** abc NEAR/5 "def ghi"
117955
+**
117956
+** Parameter nNear is passed the NEAR distance of the expression (5 in
117957
+** the example above). When this function is called, *paPoslist points to
117958
+** the position list, and *pnToken is the number of phrase tokens in, the
117959
+** phrase on the other side of the NEAR operator to pPhrase. For example,
117960
+** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
117961
+** the position list associated with phrase "abc".
117962
+**
117963
+** All positions in the pPhrase position list that are not sufficiently
117964
+** close to a position in the *paPoslist position list are removed. If this
117965
+** leaves 0 positions, zero is returned. Otherwise, non-zero.
117966
+**
117967
+** Before returning, *paPoslist is set to point to the position lsit
117968
+** associated with pPhrase. And *pnToken is set to the number of tokens in
117969
+** pPhrase.
117970
+*/
117971
+static int fts3EvalNearTrim(
117972
+ int nNear, /* NEAR distance. As in "NEAR/nNear". */
115670117973
char *aTmp, /* Temporary space to use */
115671117974
char **paPoslist, /* IN/OUT: Position list */
115672117975
int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
115673117976
Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
115674117977
){
@@ -115696,10 +117999,176 @@
115696117999
}
115697118000
115698118001
return res;
115699118002
}
115700118003
118004
+/*
118005
+** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
118006
+** Otherwise, it advances the expression passed as the second argument to
118007
+** point to the next matching row in the database. Expressions iterate through
118008
+** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
118009
+** or descending if it is non-zero.
118010
+**
118011
+** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
118012
+** successful, the following variables in pExpr are set:
118013
+**
118014
+** Fts3Expr.bEof (non-zero if EOF - there is no next row)
118015
+** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row)
118016
+**
118017
+** If the expression is of type FTSQUERY_PHRASE, and the expression is not
118018
+** at EOF, then the following variables are populated with the position list
118019
+** for the phrase for the visited row:
118020
+**
118021
+** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes)
118022
+** FTs3Expr.pPhrase->doclist.pList (pointer to position list)
118023
+**
118024
+** It says above that this function advances the expression to the next
118025
+** matching row. This is usually true, but there are the following exceptions:
118026
+**
118027
+** 1. Deferred tokens are not taken into account. If a phrase consists
118028
+** entirely of deferred tokens, it is assumed to match every row in
118029
+** the db. In this case the position-list is not populated at all.
118030
+**
118031
+** Or, if a phrase contains one or more deferred tokens and one or
118032
+** more non-deferred tokens, then the expression is advanced to the
118033
+** next possible match, considering only non-deferred tokens. In other
118034
+** words, if the phrase is "A B C", and "B" is deferred, the expression
118035
+** is advanced to the next row that contains an instance of "A * C",
118036
+** where "*" may match any single token. The position list in this case
118037
+** is populated as for "A * C" before returning.
118038
+**
118039
+** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
118040
+** advanced to point to the next row that matches "x AND y".
118041
+**
118042
+** See fts3EvalTestDeferredAndNear() for details on testing if a row is
118043
+** really a match, taking into account deferred tokens and NEAR operators.
118044
+*/
118045
+static void fts3EvalNextRow(
118046
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
118047
+ Fts3Expr *pExpr, /* Expr. to advance to next matching row */
118048
+ int *pRc /* IN/OUT: Error code */
118049
+){
118050
+ if( *pRc==SQLITE_OK ){
118051
+ int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */
118052
+ assert( pExpr->bEof==0 );
118053
+ pExpr->bStart = 1;
118054
+
118055
+ switch( pExpr->eType ){
118056
+ case FTSQUERY_NEAR:
118057
+ case FTSQUERY_AND: {
118058
+ Fts3Expr *pLeft = pExpr->pLeft;
118059
+ Fts3Expr *pRight = pExpr->pRight;
118060
+ assert( !pLeft->bDeferred || !pRight->bDeferred );
118061
+
118062
+ if( pLeft->bDeferred ){
118063
+ /* LHS is entirely deferred. So we assume it matches every row.
118064
+ ** Advance the RHS iterator to find the next row visited. */
118065
+ fts3EvalNextRow(pCsr, pRight, pRc);
118066
+ pExpr->iDocid = pRight->iDocid;
118067
+ pExpr->bEof = pRight->bEof;
118068
+ }else if( pRight->bDeferred ){
118069
+ /* RHS is entirely deferred. So we assume it matches every row.
118070
+ ** Advance the LHS iterator to find the next row visited. */
118071
+ fts3EvalNextRow(pCsr, pLeft, pRc);
118072
+ pExpr->iDocid = pLeft->iDocid;
118073
+ pExpr->bEof = pLeft->bEof;
118074
+ }else{
118075
+ /* Neither the RHS or LHS are deferred. */
118076
+ fts3EvalNextRow(pCsr, pLeft, pRc);
118077
+ fts3EvalNextRow(pCsr, pRight, pRc);
118078
+ while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
118079
+ sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
118080
+ if( iDiff==0 ) break;
118081
+ if( iDiff<0 ){
118082
+ fts3EvalNextRow(pCsr, pLeft, pRc);
118083
+ }else{
118084
+ fts3EvalNextRow(pCsr, pRight, pRc);
118085
+ }
118086
+ }
118087
+ pExpr->iDocid = pLeft->iDocid;
118088
+ pExpr->bEof = (pLeft->bEof || pRight->bEof);
118089
+ }
118090
+ break;
118091
+ }
118092
+
118093
+ case FTSQUERY_OR: {
118094
+ Fts3Expr *pLeft = pExpr->pLeft;
118095
+ Fts3Expr *pRight = pExpr->pRight;
118096
+ sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
118097
+
118098
+ assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
118099
+ assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
118100
+
118101
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
118102
+ fts3EvalNextRow(pCsr, pLeft, pRc);
118103
+ }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
118104
+ fts3EvalNextRow(pCsr, pRight, pRc);
118105
+ }else{
118106
+ fts3EvalNextRow(pCsr, pLeft, pRc);
118107
+ fts3EvalNextRow(pCsr, pRight, pRc);
118108
+ }
118109
+
118110
+ pExpr->bEof = (pLeft->bEof && pRight->bEof);
118111
+ iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
118112
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
118113
+ pExpr->iDocid = pLeft->iDocid;
118114
+ }else{
118115
+ pExpr->iDocid = pRight->iDocid;
118116
+ }
118117
+
118118
+ break;
118119
+ }
118120
+
118121
+ case FTSQUERY_NOT: {
118122
+ Fts3Expr *pLeft = pExpr->pLeft;
118123
+ Fts3Expr *pRight = pExpr->pRight;
118124
+
118125
+ if( pRight->bStart==0 ){
118126
+ fts3EvalNextRow(pCsr, pRight, pRc);
118127
+ assert( *pRc!=SQLITE_OK || pRight->bStart );
118128
+ }
118129
+
118130
+ fts3EvalNextRow(pCsr, pLeft, pRc);
118131
+ if( pLeft->bEof==0 ){
118132
+ while( !*pRc
118133
+ && !pRight->bEof
118134
+ && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
118135
+ ){
118136
+ fts3EvalNextRow(pCsr, pRight, pRc);
118137
+ }
118138
+ }
118139
+ pExpr->iDocid = pLeft->iDocid;
118140
+ pExpr->bEof = pLeft->bEof;
118141
+ break;
118142
+ }
118143
+
118144
+ default: {
118145
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
118146
+ fts3EvalInvalidatePoslist(pPhrase);
118147
+ *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
118148
+ pExpr->iDocid = pPhrase->doclist.iDocid;
118149
+ break;
118150
+ }
118151
+ }
118152
+ }
118153
+}
118154
+
118155
+/*
118156
+** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
118157
+** cluster, then this function returns 1 immediately.
118158
+**
118159
+** Otherwise, it checks if the current row really does match the NEAR
118160
+** expression, using the data currently stored in the position lists
118161
+** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
118162
+**
118163
+** If the current row is a match, the position list associated with each
118164
+** phrase in the NEAR expression is edited in place to contain only those
118165
+** phrase instances sufficiently close to their peers to satisfy all NEAR
118166
+** constraints. In this case it returns 1. If the NEAR expression does not
118167
+** match the current row, 0 is returned. The position lists may or may not
118168
+** be edited if 0 is returned.
118169
+*/
115701118170
static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
115702118171
int res = 1;
115703118172
115704118173
/* The following block runs if pExpr is the root of a NEAR query.
115705118174
** For example, the query:
@@ -115717,11 +118186,11 @@
115717118186
** | |
115718118187
** "w" "x"
115719118188
**
115720118189
** The right-hand child of a NEAR node is always a phrase. The
115721118190
** left-hand child may be either a phrase or a NEAR node. There are
115722
- ** no exceptions to this.
118191
+ ** no exceptions to this - it's the way the parser in fts3_expr.c works.
115723118192
*/
115724118193
if( *pRc==SQLITE_OK
115725118194
&& pExpr->eType==FTSQUERY_NEAR
115726118195
&& pExpr->bEof==0
115727118196
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
@@ -115744,21 +118213,21 @@
115744118213
int nToken = p->pPhrase->nToken;
115745118214
115746118215
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
115747118216
Fts3Phrase *pPhrase = p->pRight->pPhrase;
115748118217
int nNear = p->nNear;
115749
- res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
118218
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115750118219
}
115751118220
115752118221
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
115753118222
nToken = pExpr->pRight->pPhrase->nToken;
115754118223
for(p=pExpr->pLeft; p && res; p=p->pLeft){
115755118224
int nNear = p->pParent->nNear;
115756118225
Fts3Phrase *pPhrase = (
115757118226
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
115758118227
);
115759
- res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
118228
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115760118229
}
115761118230
}
115762118231
115763118232
sqlite3_free(aTmp);
115764118233
}
@@ -115765,132 +118234,33 @@
115765118234
115766118235
return res;
115767118236
}
115768118237
115769118238
/*
115770
-** This macro is used by the fts3EvalNext() function. The two arguments are
115771
-** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
115772
-** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
115773
-** it returns (i2 - i1). This allows the same code to be used for merging
115774
-** doclists in ascending or descending order.
118239
+** This function is a helper function for fts3EvalTestDeferredAndNear().
118240
+** Assuming no error occurs or has occurred, It returns non-zero if the
118241
+** expression passed as the second argument matches the row that pCsr
118242
+** currently points to, or zero if it does not.
118243
+**
118244
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
118245
+** If an error occurs during execution of this function, *pRc is set to
118246
+** the appropriate SQLite error code. In this case the returned value is
118247
+** undefined.
115775118248
*/
115776
-#define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
115777
-
115778
-static void fts3EvalNext(
115779
- Fts3Cursor *pCsr,
115780
- Fts3Expr *pExpr,
115781
- int *pRc
115782
-){
115783
- if( *pRc==SQLITE_OK ){
115784
- assert( pExpr->bEof==0 );
115785
- pExpr->bStart = 1;
115786
-
115787
- switch( pExpr->eType ){
115788
- case FTSQUERY_NEAR:
115789
- case FTSQUERY_AND: {
115790
- Fts3Expr *pLeft = pExpr->pLeft;
115791
- Fts3Expr *pRight = pExpr->pRight;
115792
- assert( !pLeft->bDeferred || !pRight->bDeferred );
115793
- if( pLeft->bDeferred ){
115794
- fts3EvalNext(pCsr, pRight, pRc);
115795
- pExpr->iDocid = pRight->iDocid;
115796
- pExpr->bEof = pRight->bEof;
115797
- }else if( pRight->bDeferred ){
115798
- fts3EvalNext(pCsr, pLeft, pRc);
115799
- pExpr->iDocid = pLeft->iDocid;
115800
- pExpr->bEof = pLeft->bEof;
115801
- }else{
115802
- fts3EvalNext(pCsr, pLeft, pRc);
115803
- fts3EvalNext(pCsr, pRight, pRc);
115804
-
115805
- while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
115806
- sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115807
- if( iDiff==0 ) break;
115808
- if( iDiff<0 ){
115809
- fts3EvalNext(pCsr, pLeft, pRc);
115810
- }else{
115811
- fts3EvalNext(pCsr, pRight, pRc);
115812
- }
115813
- }
115814
-
115815
- pExpr->iDocid = pLeft->iDocid;
115816
- pExpr->bEof = (pLeft->bEof || pRight->bEof);
115817
- }
115818
- break;
115819
- }
115820
-
115821
- case FTSQUERY_OR: {
115822
- Fts3Expr *pLeft = pExpr->pLeft;
115823
- Fts3Expr *pRight = pExpr->pRight;
115824
- sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115825
-
115826
- assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
115827
- assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
115828
-
115829
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115830
- fts3EvalNext(pCsr, pLeft, pRc);
115831
- }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
115832
- fts3EvalNext(pCsr, pRight, pRc);
115833
- }else{
115834
- fts3EvalNext(pCsr, pLeft, pRc);
115835
- fts3EvalNext(pCsr, pRight, pRc);
115836
- }
115837
-
115838
- pExpr->bEof = (pLeft->bEof && pRight->bEof);
115839
- iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115840
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115841
- pExpr->iDocid = pLeft->iDocid;
115842
- }else{
115843
- pExpr->iDocid = pRight->iDocid;
115844
- }
115845
-
115846
- break;
115847
- }
115848
-
115849
- case FTSQUERY_NOT: {
115850
- Fts3Expr *pLeft = pExpr->pLeft;
115851
- Fts3Expr *pRight = pExpr->pRight;
115852
-
115853
- if( pRight->bStart==0 ){
115854
- fts3EvalNext(pCsr, pRight, pRc);
115855
- assert( *pRc!=SQLITE_OK || pRight->bStart );
115856
- }
115857
-
115858
- fts3EvalNext(pCsr, pLeft, pRc);
115859
- if( pLeft->bEof==0 ){
115860
- while( !*pRc
115861
- && !pRight->bEof
115862
- && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
115863
- ){
115864
- fts3EvalNext(pCsr, pRight, pRc);
115865
- }
115866
- }
115867
- pExpr->iDocid = pLeft->iDocid;
115868
- pExpr->bEof = pLeft->bEof;
115869
- break;
115870
- }
115871
-
115872
- default: {
115873
- Fts3Phrase *pPhrase = pExpr->pPhrase;
115874
- fts3EvalZeroPoslist(pPhrase);
115875
- *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
115876
- pExpr->iDocid = pPhrase->doclist.iDocid;
115877
- break;
115878
- }
115879
- }
115880
- }
115881
-}
115882
-
115883
-static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
115884
- int bHit = 1;
118249
+static int fts3EvalTestExpr(
118250
+ Fts3Cursor *pCsr, /* FTS cursor handle */
118251
+ Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
118252
+ int *pRc /* IN/OUT: Error code */
118253
+){
118254
+ int bHit = 1; /* Return value */
115885118255
if( *pRc==SQLITE_OK ){
115886118256
switch( pExpr->eType ){
115887118257
case FTSQUERY_NEAR:
115888118258
case FTSQUERY_AND:
115889118259
bHit = (
115890
- fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115891
- && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
118260
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
118261
+ && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
115892118262
&& fts3EvalNearTest(pExpr, pRc)
115893118263
);
115894118264
115895118265
/* If the NEAR expression does not match any rows, zero the doclist for
115896118266
** all phrases involved in the NEAR. This is because the snippet(),
@@ -115912,31 +118282,31 @@
115912118282
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
115913118283
){
115914118284
Fts3Expr *p;
115915118285
for(p=pExpr; p->pPhrase==0; p=p->pLeft){
115916118286
if( p->pRight->iDocid==pCsr->iPrevId ){
115917
- fts3EvalZeroPoslist(p->pRight->pPhrase);
118287
+ fts3EvalInvalidatePoslist(p->pRight->pPhrase);
115918118288
}
115919118289
}
115920118290
if( p->iDocid==pCsr->iPrevId ){
115921
- fts3EvalZeroPoslist(p->pPhrase);
118291
+ fts3EvalInvalidatePoslist(p->pPhrase);
115922118292
}
115923118293
}
115924118294
115925118295
break;
115926118296
115927118297
case FTSQUERY_OR: {
115928
- int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
115929
- int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
118298
+ int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
118299
+ int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
115930118300
bHit = bHit1 || bHit2;
115931118301
break;
115932118302
}
115933118303
115934118304
case FTSQUERY_NOT:
115935118305
bHit = (
115936
- fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115937
- && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
118306
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
118307
+ && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
115938118308
);
115939118309
break;
115940118310
115941118311
default: {
115942118312
if( pCsr->pDeferred
@@ -115943,11 +118313,11 @@
115943118313
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
115944118314
){
115945118315
Fts3Phrase *pPhrase = pExpr->pPhrase;
115946118316
assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
115947118317
if( pExpr->bDeferred ){
115948
- fts3EvalZeroPoslist(pPhrase);
118318
+ fts3EvalInvalidatePoslist(pPhrase);
115949118319
}
115950118320
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
115951118321
bHit = (pPhrase->doclist.pList!=0);
115952118322
pExpr->iDocid = pCsr->iPrevId;
115953118323
}else{
@@ -115959,31 +118329,53 @@
115959118329
}
115960118330
return bHit;
115961118331
}
115962118332
115963118333
/*
115964
-** Return 1 if both of the following are true:
118334
+** This function is called as the second part of each xNext operation when
118335
+** iterating through the results of a full-text query. At this point the
118336
+** cursor points to a row that matches the query expression, with the
118337
+** following caveats:
118338
+**
118339
+** * Up until this point, "NEAR" operators in the expression have been
118340
+** treated as "AND".
118341
+**
118342
+** * Deferred tokens have not yet been considered.
118343
+**
118344
+** If *pRc is not SQLITE_OK when this function is called, it immediately
118345
+** returns 0. Otherwise, it tests whether or not after considering NEAR
118346
+** operators and deferred tokens the current row is still a match for the
118347
+** expression. It returns 1 if both of the following are true:
115965118348
**
115966118349
** 1. *pRc is SQLITE_OK when this function returns, and
115967118350
**
115968118351
** 2. After scanning the current FTS table row for the deferred tokens,
115969
-** it is determined that the row does not match the query.
118352
+** it is determined that the row does *not* match the query.
115970118353
**
115971118354
** Or, if no error occurs and it seems the current row does match the FTS
115972118355
** query, return 0.
115973118356
*/
115974
-static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
118357
+static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
115975118358
int rc = *pRc;
115976118359
int bMiss = 0;
115977118360
if( rc==SQLITE_OK ){
118361
+
118362
+ /* If there are one or more deferred tokens, load the current row into
118363
+ ** memory and scan it to determine the position list for each deferred
118364
+ ** token. Then, see if this row is really a match, considering deferred
118365
+ ** tokens and NEAR operators (neither of which were taken into account
118366
+ ** earlier, by fts3EvalNextRow()).
118367
+ */
115978118368
if( pCsr->pDeferred ){
115979118369
rc = fts3CursorSeek(0, pCsr);
115980118370
if( rc==SQLITE_OK ){
115981118371
rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
115982118372
}
115983118373
}
115984
- bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
118374
+ bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
118375
+
118376
+ /* Free the position-lists accumulated for each deferred token above. */
115985118377
sqlite3Fts3FreeDeferredDoclists(pCsr);
115986118378
*pRc = rc;
115987118379
}
115988118380
return (rc==SQLITE_OK && bMiss);
115989118381
}
@@ -115990,11 +118382,11 @@
115990118382
115991118383
/*
115992118384
** Advance to the next document that matches the FTS expression in
115993118385
** Fts3Cursor.pExpr.
115994118386
*/
115995
-SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
118387
+static int fts3EvalNext(Fts3Cursor *pCsr){
115996118388
int rc = SQLITE_OK; /* Return Code */
115997118389
Fts3Expr *pExpr = pCsr->pExpr;
115998118390
assert( pCsr->isEof==0 );
115999118391
if( pExpr==0 ){
116000118392
pCsr->isEof = 1;
@@ -116002,23 +118394,23 @@
116002118394
do {
116003118395
if( pCsr->isRequireSeek==0 ){
116004118396
sqlite3_reset(pCsr->pStmt);
116005118397
}
116006118398
assert( sqlite3_data_count(pCsr->pStmt)==0 );
116007
- fts3EvalNext(pCsr, pExpr, &rc);
118399
+ fts3EvalNextRow(pCsr, pExpr, &rc);
116008118400
pCsr->isEof = pExpr->bEof;
116009118401
pCsr->isRequireSeek = 1;
116010118402
pCsr->isMatchinfoNeeded = 1;
116011118403
pCsr->iPrevId = pExpr->iDocid;
116012
- }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
118404
+ }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
116013118405
}
116014118406
return rc;
116015118407
}
116016118408
116017118409
/*
116018118410
** Restart interation for expression pExpr so that the next call to
116019
-** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental
118411
+** fts3EvalNext() visits the first row. Do not allow incremental
116020118412
** loading or merging of phrase doclists for this iteration.
116021118413
**
116022118414
** If *pRc is other than SQLITE_OK when this function is called, it is
116023118415
** a no-op. If an error occurs within this function, *pRc is set to an
116024118416
** SQLite error code before returning.
@@ -116030,19 +118422,20 @@
116030118422
){
116031118423
if( pExpr && *pRc==SQLITE_OK ){
116032118424
Fts3Phrase *pPhrase = pExpr->pPhrase;
116033118425
116034118426
if( pPhrase ){
116035
- fts3EvalZeroPoslist(pPhrase);
118427
+ fts3EvalInvalidatePoslist(pPhrase);
116036118428
if( pPhrase->bIncr ){
116037
- sqlite3Fts3EvalPhraseCleanup(pPhrase);
116038
- memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116039
- *pRc = sqlite3Fts3EvalStart(pCsr, pExpr, 0);
116040
- }else{
116041
- pPhrase->doclist.pNextDocid = 0;
116042
- pPhrase->doclist.iDocid = 0;
118429
+ assert( pPhrase->nToken==1 );
118430
+ assert( pPhrase->aToken[0].pSegcsr );
118431
+ sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
118432
+ *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
116043118433
}
118434
+
118435
+ pPhrase->doclist.pNextDocid = 0;
118436
+ pPhrase->doclist.iDocid = 0;
116044118437
}
116045118438
116046118439
pExpr->iDocid = 0;
116047118440
pExpr->bEof = 0;
116048118441
pExpr->bStart = 0;
@@ -116145,18 +118538,18 @@
116145118538
/* Ensure the %_content statement is reset. */
116146118539
if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
116147118540
assert( sqlite3_data_count(pCsr->pStmt)==0 );
116148118541
116149118542
/* Advance to the next document */
116150
- fts3EvalNext(pCsr, pRoot, &rc);
118543
+ fts3EvalNextRow(pCsr, pRoot, &rc);
116151118544
pCsr->isEof = pRoot->bEof;
116152118545
pCsr->isRequireSeek = 1;
116153118546
pCsr->isMatchinfoNeeded = 1;
116154118547
pCsr->iPrevId = pRoot->iDocid;
116155118548
}while( pCsr->isEof==0
116156118549
&& pRoot->eType==FTSQUERY_NEAR
116157
- && fts3EvalLoadDeferred(pCsr, &rc)
118550
+ && fts3EvalTestDeferredAndNear(pCsr, &rc)
116158118551
);
116159118552
116160118553
if( rc==SQLITE_OK && pCsr->isEof==0 ){
116161118554
fts3EvalUpdateCounts(pRoot);
116162118555
}
@@ -116174,14 +118567,14 @@
116174118567
**
116175118568
** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
116176118569
*/
116177118570
fts3EvalRestart(pCsr, pRoot, &rc);
116178118571
do {
116179
- fts3EvalNext(pCsr, pRoot, &rc);
118572
+ fts3EvalNextRow(pCsr, pRoot, &rc);
116180118573
assert( pRoot->bEof==0 );
116181118574
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
116182
- fts3EvalLoadDeferred(pCsr, &rc);
118575
+ fts3EvalTestDeferredAndNear(pCsr, &rc);
116183118576
}
116184118577
}
116185118578
return rc;
116186118579
}
116187118580
@@ -116225,12 +118618,12 @@
116225118618
int iCol;
116226118619
116227118620
if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
116228118621
assert( pCsr->nDoc>0 );
116229118622
for(iCol=0; iCol<pTab->nColumn; iCol++){
116230
- aiOut[iCol*3 + 1] = pCsr->nDoc;
116231
- aiOut[iCol*3 + 2] = pCsr->nDoc;
118623
+ aiOut[iCol*3 + 1] = (u32)pCsr->nDoc;
118624
+ aiOut[iCol*3 + 2] = (u32)pCsr->nDoc;
116232118625
}
116233118626
}else{
116234118627
rc = fts3EvalGatherStats(pCsr, pExpr);
116235118628
if( rc==SQLITE_OK ){
116236118629
assert( pExpr->aMI );
@@ -116308,18 +118701,32 @@
116308118701
*/
116309118702
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
116310118703
if( pPhrase ){
116311118704
int i;
116312118705
sqlite3_free(pPhrase->doclist.aAll);
116313
- fts3EvalZeroPoslist(pPhrase);
118706
+ fts3EvalInvalidatePoslist(pPhrase);
116314118707
memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116315118708
for(i=0; i<pPhrase->nToken; i++){
116316118709
fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
116317118710
pPhrase->aToken[i].pSegcsr = 0;
116318118711
}
116319118712
}
116320118713
}
118714
+
118715
+#if !SQLITE_CORE
118716
+/*
118717
+** Initialize API pointer table, if required.
118718
+*/
118719
+SQLITE_API int sqlite3_extension_init(
118720
+ sqlite3 *db,
118721
+ char **pzErrMsg,
118722
+ const sqlite3_api_routines *pApi
118723
+){
118724
+ SQLITE_EXTENSION_INIT2(pApi)
118725
+ return sqlite3Fts3Init(db);
118726
+}
118727
+#endif
116321118728
116322118729
#endif
116323118730
116324118731
/************** End of fts3.c ************************************************/
116325118732
/************** Begin file fts3_aux.c ****************************************/
@@ -116334,13 +118741,14 @@
116334118741
** May you share freely, never taking more than you give.
116335118742
**
116336118743
******************************************************************************
116337118744
**
116338118745
*/
116339
-
116340118746
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
116341118747
118748
+/* #include <string.h> */
118749
+/* #include <assert.h> */
116342118750
116343118751
typedef struct Fts3auxTable Fts3auxTable;
116344118752
typedef struct Fts3auxCursor Fts3auxCursor;
116345118753
116346118754
struct Fts3auxTable {
@@ -116875,10 +119283,12 @@
116875119283
/*
116876119284
** Default span for NEAR operators.
116877119285
*/
116878119286
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
116879119287
119288
+/* #include <string.h> */
119289
+/* #include <assert.h> */
116880119290
116881119291
/*
116882119292
** isNot:
116883119293
** This variable is used by function getNextNode(). When getNextNode() is
116884119294
** called, it sets ParseContext.isNot to true if the 'next node' is a
@@ -117576,10 +119986,11 @@
117576119986
** Everything after this point is just test code.
117577119987
*/
117578119988
117579119989
#ifdef SQLITE_TEST
117580119990
119991
+/* #include <stdio.h> */
117581119992
117582119993
/*
117583119994
** Function to query the hash-table of tokenizers (see README.tokenizers).
117584119995
*/
117585119996
static int queryTestTokenizer(
@@ -117786,10 +120197,13 @@
117786120197
** * The FTS3 module is being built into the core of
117787120198
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
117788120199
*/
117789120200
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
117790120201
120202
+/* #include <assert.h> */
120203
+/* #include <stdlib.h> */
120204
+/* #include <string.h> */
117791120205
117792120206
117793120207
/*
117794120208
** Malloc and Free functions
117795120209
*/
@@ -118166,11 +120580,14 @@
118166120580
** * The FTS3 module is being built into the core of
118167120581
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
118168120582
*/
118169120583
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
118170120584
118171
-
120585
+/* #include <assert.h> */
120586
+/* #include <stdlib.h> */
120587
+/* #include <stdio.h> */
120588
+/* #include <string.h> */
118172120589
118173120590
118174120591
/*
118175120592
** Class derived from sqlite3_tokenizer
118176120593
*/
@@ -118810,14 +121227,12 @@
118810121227
** * The FTS3 module is being built into the core of
118811121228
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
118812121229
*/
118813121230
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
118814121231
118815
-#ifndef SQLITE_CORE
118816
- SQLITE_EXTENSION_INIT1
118817
-#endif
118818
-
121232
+/* #include <assert.h> */
121233
+/* #include <string.h> */
118819121234
118820121235
/*
118821121236
** Implementation of the SQL scalar function for accessing the underlying
118822121237
** hash table. This function may be called as follows:
118823121238
**
@@ -118937,11 +121352,11 @@
118937121352
sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
118938121353
char **pzErr /* OUT: Set to malloced error message */
118939121354
){
118940121355
int rc;
118941121356
char *z = (char *)zArg;
118942
- int n;
121357
+ int n = 0;
118943121358
char *zCopy;
118944121359
char *zEnd; /* Pointer to nul-term of zCopy */
118945121360
sqlite3_tokenizer_module *m;
118946121361
118947121362
zCopy = sqlite3_mprintf("%s", zArg);
@@ -118989,10 +121404,12 @@
118989121404
}
118990121405
118991121406
118992121407
#ifdef SQLITE_TEST
118993121408
121409
+/* #include <tcl.h> */
121410
+/* #include <string.h> */
118994121411
118995121412
/*
118996121413
** Implementation of a special SQL scalar function for testing tokenizers
118997121414
** designed to be used in concert with the Tcl testing framework. This
118998121415
** function must be called with two arguments:
@@ -119300,11 +121717,14 @@
119300121717
** * The FTS3 module is being built into the core of
119301121718
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
119302121719
*/
119303121720
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
119304121721
119305
-
121722
+/* #include <assert.h> */
121723
+/* #include <stdlib.h> */
121724
+/* #include <stdio.h> */
121725
+/* #include <string.h> */
119306121726
119307121727
119308121728
typedef struct simple_tokenizer {
119309121729
sqlite3_tokenizer base;
119310121730
char delim[128]; /* flag ASCII delimiters */
@@ -119526,10 +121946,13 @@
119526121946
** code in fts3.c.
119527121947
*/
119528121948
119529121949
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
119530121950
121951
+/* #include <string.h> */
121952
+/* #include <assert.h> */
121953
+/* #include <stdlib.h> */
119531121954
119532121955
/*
119533121956
** When full-text index nodes are loaded from disk, the buffer that they
119534121957
** are loaded into has the following number of bytes of padding at the end
119535121958
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
@@ -120750,10 +123173,11 @@
120750123173
pReader->pOffsetList = 0;
120751123174
}else{
120752123175
pReader->pOffsetList = p;
120753123176
}
120754123177
}else{
123178
+ char *pEnd = &pReader->aDoclist[pReader->nDoclist];
120755123179
120756123180
/* Pointer p currently points at the first byte of an offset list. The
120757123181
** following block advances it to point one byte past the end of
120758123182
** the same offset list. */
120759123183
while( 1 ){
@@ -120778,17 +123202,19 @@
120778123202
*/
120779123203
if( ppOffsetList ){
120780123204
*ppOffsetList = pReader->pOffsetList;
120781123205
*pnOffsetList = (int)(p - pReader->pOffsetList - 1);
120782123206
}
123207
+
123208
+ while( p<pEnd && *p==0 ) p++;
120783123209
120784123210
/* If there are no more entries in the doclist, set pOffsetList to
120785123211
** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
120786123212
** Fts3SegReader.pOffsetList to point to the next offset list before
120787123213
** returning.
120788123214
*/
120789
- if( p>=&pReader->aDoclist[pReader->nDoclist] ){
123215
+ if( p>=pEnd ){
120790123216
pReader->pOffsetList = 0;
120791123217
}else{
120792123218
rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
120793123219
if( rc==SQLITE_OK ){
120794123220
sqlite3_int64 iDelta;
@@ -120823,11 +123249,11 @@
120823123249
for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
120824123250
Fts3SegReader *pReader = pMsr->apSegment[ii];
120825123251
if( !fts3SegReaderIsPending(pReader)
120826123252
&& !fts3SegReaderIsRootOnly(pReader)
120827123253
){
120828
- int jj;
123254
+ sqlite3_int64 jj;
120829123255
for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
120830123256
int nBlob;
120831123257
rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
120832123258
if( rc!=SQLITE_OK ) break;
120833123259
if( (nBlob+35)>pgsz ){
@@ -121768,55 +124194,31 @@
121768124194
121769124195
*ppList = pList;
121770124196
*pnList = nList;
121771124197
}
121772124198
121773
-SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
121774
- Fts3Table *p, /* Virtual table handle */
121775
- Fts3MultiSegReader *pCsr, /* Cursor object */
121776
- int iCol, /* Column to match on. */
121777
- const char *zTerm, /* Term to iterate through a doclist for */
121778
- int nTerm /* Number of bytes in zTerm */
124199
+/*
124200
+** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
124201
+** existing data). Grow the buffer if required.
124202
+**
124203
+** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered
124204
+** trying to resize the buffer, return SQLITE_NOMEM.
124205
+*/
124206
+static int fts3MsrBufferData(
124207
+ Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
124208
+ char *pList,
124209
+ int nList
121779124210
){
121780
- int i;
121781
- int nSegment = pCsr->nSegment;
121782
- int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121783
- p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121784
- );
121785
-
121786
- assert( pCsr->pFilter==0 );
121787
- assert( zTerm && nTerm>0 );
121788
-
121789
- /* Advance each segment iterator until it points to the term zTerm/nTerm. */
121790
- for(i=0; i<nSegment; i++){
121791
- Fts3SegReader *pSeg = pCsr->apSegment[i];
121792
- do {
121793
- int rc = fts3SegReaderNext(p, pSeg, 1);
121794
- if( rc!=SQLITE_OK ) return rc;
121795
- }while( fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
121796
- }
121797
- fts3SegReaderSort(pCsr->apSegment, nSegment, nSegment, fts3SegReaderCmp);
121798
-
121799
- /* Determine how many of the segments actually point to zTerm/nTerm. */
121800
- for(i=0; i<nSegment; i++){
121801
- Fts3SegReader *pSeg = pCsr->apSegment[i];
121802
- if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
121803
- break;
121804
- }
121805
- }
121806
- pCsr->nAdvance = i;
121807
-
121808
- /* Advance each of the segments to point to the first docid. */
121809
- for(i=0; i<pCsr->nAdvance; i++){
121810
- int rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
121811
- if( rc!=SQLITE_OK ) return rc;
121812
- }
121813
- fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
121814
-
121815
- assert( iCol<0 || iCol<p->nColumn );
121816
- pCsr->iColFilter = iCol;
121817
-
124211
+ if( nList>pMsr->nBuffer ){
124212
+ char *pNew;
124213
+ pMsr->nBuffer = nList*2;
124214
+ pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
124215
+ if( !pNew ) return SQLITE_NOMEM;
124216
+ pMsr->aBuffer = pNew;
124217
+ }
124218
+
124219
+ memcpy(pMsr->aBuffer, pList, nList);
121818124220
return SQLITE_OK;
121819124221
}
121820124222
121821124223
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
121822124224
Fts3Table *p, /* Virtual table handle */
@@ -121866,52 +124268,138 @@
121866124268
if( pMsr->iColFilter>=0 ){
121867124269
fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
121868124270
}
121869124271
121870124272
if( nList>0 ){
124273
+ if( fts3SegReaderIsPending(apSegment[0]) ){
124274
+ rc = fts3MsrBufferData(pMsr, pList, nList+1);
124275
+ if( rc!=SQLITE_OK ) return rc;
124276
+ *paPoslist = pMsr->aBuffer;
124277
+ assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
124278
+ }else{
124279
+ *paPoslist = pList;
124280
+ }
121871124281
*piDocid = iDocid;
121872
- *paPoslist = pList;
121873124282
*pnPoslist = nList;
121874124283
break;
121875124284
}
121876124285
}
121877
-
121878124286
}
121879124287
124288
+ return SQLITE_OK;
124289
+}
124290
+
124291
+static int fts3SegReaderStart(
124292
+ Fts3Table *p, /* Virtual table handle */
124293
+ Fts3MultiSegReader *pCsr, /* Cursor object */
124294
+ const char *zTerm, /* Term searched for (or NULL) */
124295
+ int nTerm /* Length of zTerm in bytes */
124296
+){
124297
+ int i;
124298
+ int nSeg = pCsr->nSegment;
124299
+
124300
+ /* If the Fts3SegFilter defines a specific term (or term prefix) to search
124301
+ ** for, then advance each segment iterator until it points to a term of
124302
+ ** equal or greater value than the specified term. This prevents many
124303
+ ** unnecessary merge/sort operations for the case where single segment
124304
+ ** b-tree leaf nodes contain more than one term.
124305
+ */
124306
+ for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
124307
+ Fts3SegReader *pSeg = pCsr->apSegment[i];
124308
+ do {
124309
+ int rc = fts3SegReaderNext(p, pSeg, 0);
124310
+ if( rc!=SQLITE_OK ) return rc;
124311
+ }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
124312
+ }
124313
+ fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
124314
+
121880124315
return SQLITE_OK;
121881124316
}
121882124317
121883124318
SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
121884124319
Fts3Table *p, /* Virtual table handle */
121885124320
Fts3MultiSegReader *pCsr, /* Cursor object */
121886124321
Fts3SegFilter *pFilter /* Restrictions on range of iteration */
121887124322
){
121888
- int i;
121889
-
121890
- /* Initialize the cursor object */
121891124323
pCsr->pFilter = pFilter;
121892
-
121893
- /* If the Fts3SegFilter defines a specific term (or term prefix) to search
121894
- ** for, then advance each segment iterator until it points to a term of
121895
- ** equal or greater value than the specified term. This prevents many
121896
- ** unnecessary merge/sort operations for the case where single segment
121897
- ** b-tree leaf nodes contain more than one term.
121898
- */
121899
- for(i=0; i<pCsr->nSegment; i++){
121900
- int nTerm = pFilter->nTerm;
121901
- const char *zTerm = pFilter->zTerm;
124324
+ return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm);
124325
+}
124326
+
124327
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
124328
+ Fts3Table *p, /* Virtual table handle */
124329
+ Fts3MultiSegReader *pCsr, /* Cursor object */
124330
+ int iCol, /* Column to match on. */
124331
+ const char *zTerm, /* Term to iterate through a doclist for */
124332
+ int nTerm /* Number of bytes in zTerm */
124333
+){
124334
+ int i;
124335
+ int rc;
124336
+ int nSegment = pCsr->nSegment;
124337
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
124338
+ p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
124339
+ );
124340
+
124341
+ assert( pCsr->pFilter==0 );
124342
+ assert( zTerm && nTerm>0 );
124343
+
124344
+ /* Advance each segment iterator until it points to the term zTerm/nTerm. */
124345
+ rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm);
124346
+ if( rc!=SQLITE_OK ) return rc;
124347
+
124348
+ /* Determine how many of the segments actually point to zTerm/nTerm. */
124349
+ for(i=0; i<nSegment; i++){
121902124350
Fts3SegReader *pSeg = pCsr->apSegment[i];
121903
- do {
121904
- int rc = fts3SegReaderNext(p, pSeg, 0);
121905
- if( rc!=SQLITE_OK ) return rc;
121906
- }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
124351
+ if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
124352
+ break;
124353
+ }
121907124354
}
121908
- fts3SegReaderSort(
121909
- pCsr->apSegment, pCsr->nSegment, pCsr->nSegment, fts3SegReaderCmp);
124355
+ pCsr->nAdvance = i;
124356
+
124357
+ /* Advance each of the segments to point to the first docid. */
124358
+ for(i=0; i<pCsr->nAdvance; i++){
124359
+ rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
124360
+ if( rc!=SQLITE_OK ) return rc;
124361
+ }
124362
+ fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
124363
+
124364
+ assert( iCol<0 || iCol<p->nColumn );
124365
+ pCsr->iColFilter = iCol;
124366
+
124367
+ return SQLITE_OK;
124368
+}
124369
+
124370
+/*
124371
+** This function is called on a MultiSegReader that has been started using
124372
+** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also
124373
+** have been made. Calling this function puts the MultiSegReader in such
124374
+** a state that if the next two calls are:
124375
+**
124376
+** sqlite3Fts3SegReaderStart()
124377
+** sqlite3Fts3SegReaderStep()
124378
+**
124379
+** then the entire doclist for the term is available in
124380
+** MultiSegReader.aDoclist/nDoclist.
124381
+*/
124382
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
124383
+ int i; /* Used to iterate through segment-readers */
124384
+
124385
+ assert( pCsr->zTerm==0 );
124386
+ assert( pCsr->nTerm==0 );
124387
+ assert( pCsr->aDoclist==0 );
124388
+ assert( pCsr->nDoclist==0 );
124389
+
124390
+ pCsr->nAdvance = 0;
124391
+ pCsr->bRestart = 1;
124392
+ for(i=0; i<pCsr->nSegment; i++){
124393
+ pCsr->apSegment[i]->pOffsetList = 0;
124394
+ pCsr->apSegment[i]->nOffsetList = 0;
124395
+ pCsr->apSegment[i]->iDocid = 0;
124396
+ }
121910124397
121911124398
return SQLITE_OK;
121912124399
}
124400
+
121913124401
121914124402
SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
121915124403
Fts3Table *p, /* Virtual table handle */
121916124404
Fts3MultiSegReader *pCsr /* Cursor object */
121917124405
){
@@ -121981,13 +124469,18 @@
121981124469
assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
121982124470
if( nMerge==1
121983124471
&& !isIgnoreEmpty
121984124472
&& (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
121985124473
){
121986
- pCsr->aDoclist = apSegment[0]->aDoclist;
121987124474
pCsr->nDoclist = apSegment[0]->nDoclist;
121988
- rc = SQLITE_ROW;
124475
+ if( fts3SegReaderIsPending(apSegment[0]) ){
124476
+ rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
124477
+ pCsr->aDoclist = pCsr->aBuffer;
124478
+ }else{
124479
+ pCsr->aDoclist = apSegment[0]->aDoclist;
124480
+ }
124481
+ if( rc==SQLITE_OK ) rc = SQLITE_ROW;
121989124482
}else{
121990124483
int nDoclist = 0; /* Size of doclist */
121991124484
sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */
121992124485
121993124486
/* The current term of the first nMerge entries in the array
@@ -122717,10 +125210,12 @@
122717125210
******************************************************************************
122718125211
*/
122719125212
122720125213
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
122721125214
125215
+/* #include <string.h> */
125216
+/* #include <assert.h> */
122722125217
122723125218
/*
122724125219
** Characters that may appear in the second argument to matchinfo().
122725125220
*/
122726125221
#define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */
@@ -123725,11 +126220,11 @@
123725126220
if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
123726126221
break;
123727126222
123728126223
case FTS3_MATCHINFO_NDOC:
123729126224
if( bGlobal ){
123730
- sqlite3_int64 nDoc;
126225
+ sqlite3_int64 nDoc = 0;
123731126226
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
123732126227
pInfo->aMatchinfo[0] = (u32)nDoc;
123733126228
}
123734126229
break;
123735126230
@@ -124304,10 +126799,12 @@
124304126799
#ifndef SQLITE_CORE
124305126800
SQLITE_EXTENSION_INIT1
124306126801
#else
124307126802
#endif
124308126803
126804
+/* #include <string.h> */
126805
+/* #include <assert.h> */
124309126806
124310126807
#ifndef SQLITE_AMALGAMATION
124311126808
#include "sqlite3rtree.h"
124312126809
typedef sqlite3_int64 i64;
124313126810
typedef unsigned char u8;
@@ -125620,11 +128117,11 @@
125620128117
*/
125621128118
static float cellArea(Rtree *pRtree, RtreeCell *p){
125622128119
float area = 1.0;
125623128120
int ii;
125624128121
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
125625
- area = area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
128122
+ area = (float)(area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])));
125626128123
}
125627128124
return area;
125628128125
}
125629128126
125630128127
/*
@@ -125633,11 +128130,11 @@
125633128130
*/
125634128131
static float cellMargin(Rtree *pRtree, RtreeCell *p){
125635128132
float margin = 0.0;
125636128133
int ii;
125637128134
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
125638
- margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
128135
+ margin += (float)(DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
125639128136
}
125640128137
return margin;
125641128138
}
125642128139
125643128140
/*
@@ -125718,11 +128215,11 @@
125718128215
125719128216
if( x2<x1 ){
125720128217
o = 0.0;
125721128218
break;
125722128219
}else{
125723
- o = o * (x2-x1);
128220
+ o = o * (float)(x2-x1);
125724128221
}
125725128222
}
125726128223
overlap += o;
125727128224
}
125728128225
}
@@ -125737,16 +128234,16 @@
125737128234
RtreeCell *pInsert,
125738128235
RtreeCell *aCell,
125739128236
int nCell,
125740128237
int iExclude
125741128238
){
125742
- float before;
125743
- float after;
128239
+ double before;
128240
+ double after;
125744128241
before = cellOverlap(pRtree, p, aCell, nCell, iExclude);
125745128242
cellUnion(pRtree, p, pInsert);
125746128243
after = cellOverlap(pRtree, p, aCell, nCell, iExclude);
125747
- return after-before;
128244
+ return (float)(after-before);
125748128245
}
125749128246
#endif
125750128247
125751128248
125752128249
/*
@@ -125764,15 +128261,15 @@
125764128261
RtreeNode *pNode;
125765128262
rc = nodeAcquire(pRtree, 1, 0, &pNode);
125766128263
125767128264
for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
125768128265
int iCell;
125769
- sqlite3_int64 iBest;
128266
+ sqlite3_int64 iBest = 0;
125770128267
125771
- float fMinGrowth;
125772
- float fMinArea;
125773
- float fMinOverlap;
128268
+ float fMinGrowth = 0.0;
128269
+ float fMinArea = 0.0;
128270
+ float fMinOverlap = 0.0;
125774128271
125775128272
int nCell = NCELL(pNode);
125776128273
RtreeCell cell;
125777128274
RtreeNode *pChild;
125778128275
@@ -126198,13 +128695,13 @@
126198128695
){
126199128696
int **aaSorted;
126200128697
int *aSpare;
126201128698
int ii;
126202128699
126203
- int iBestDim;
126204
- int iBestSplit;
126205
- float fBestMargin;
128700
+ int iBestDim = 0;
128701
+ int iBestSplit = 0;
128702
+ float fBestMargin = 0.0;
126206128703
126207128704
int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
126208128705
126209128706
aaSorted = (int **)sqlite3_malloc(nByte);
126210128707
if( !aaSorted ){
@@ -126222,13 +128719,13 @@
126222128719
SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);
126223128720
}
126224128721
126225128722
for(ii=0; ii<pRtree->nDim; ii++){
126226128723
float margin = 0.0;
126227
- float fBestOverlap;
126228
- float fBestArea;
126229
- int iBestLeft;
128724
+ float fBestOverlap = 0.0;
128725
+ float fBestArea = 0.0;
128726
+ int iBestLeft = 0;
126230128727
int nLeft;
126231128728
126232128729
for(
126233128730
nLeft=RTREE_MINCELLS(pRtree);
126234128731
nLeft<=(nCell-RTREE_MINCELLS(pRtree));
@@ -126539,11 +129036,11 @@
126539129036
static int deleteCell(Rtree *, RtreeNode *, int, int);
126540129037
126541129038
static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
126542129039
int rc;
126543129040
int rc2;
126544
- RtreeNode *pParent;
129041
+ RtreeNode *pParent = 0;
126545129042
int iCell;
126546129043
126547129044
assert( pNode->nRef==1 );
126548129045
126549129046
/* Remove the entry in the parent cell. */
@@ -126687,23 +129184,23 @@
126687129184
}else{
126688129185
nodeGetCell(pRtree, pNode, ii, &aCell[ii]);
126689129186
}
126690129187
aOrder[ii] = ii;
126691129188
for(iDim=0; iDim<pRtree->nDim; iDim++){
126692
- aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);
126693
- aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);
129189
+ aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2]);
129190
+ aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2+1]);
126694129191
}
126695129192
}
126696129193
for(iDim=0; iDim<pRtree->nDim; iDim++){
126697
- aCenterCoord[iDim] = aCenterCoord[iDim]/((float)nCell*2.0);
129194
+ aCenterCoord[iDim] = (float)(aCenterCoord[iDim]/((float)nCell*2.0));
126698129195
}
126699129196
126700129197
for(ii=0; ii<nCell; ii++){
126701129198
aDistance[ii] = 0.0;
126702129199
for(iDim=0; iDim<pRtree->nDim; iDim++){
126703
- float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) -
126704
- DCOORD(aCell[ii].aCoord[iDim*2]);
129200
+ float coord = (float)(DCOORD(aCell[ii].aCoord[iDim*2+1]) -
129201
+ DCOORD(aCell[ii].aCoord[iDim*2]));
126705129202
aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
126706129203
}
126707129204
}
126708129205
126709129206
SortByDistance(aOrder, nCell, aDistance, aSpare);
@@ -126798,14 +129295,14 @@
126798129295
nodeGetCell(pRtree, pNode, ii, &cell);
126799129296
126800129297
/* Find a node to store this cell in. pNode->iNode currently contains
126801129298
** the height of the sub-tree headed by the cell.
126802129299
*/
126803
- rc = ChooseLeaf(pRtree, &cell, pNode->iNode, &pInsert);
129300
+ rc = ChooseLeaf(pRtree, &cell, (int)pNode->iNode, &pInsert);
126804129301
if( rc==SQLITE_OK ){
126805129302
int rc2;
126806
- rc = rtreeInsertCell(pRtree, pInsert, &cell, pNode->iNode);
129303
+ rc = rtreeInsertCell(pRtree, pInsert, &cell, (int)pNode->iNode);
126807129304
rc2 = nodeRelease(pRtree, pInsert);
126808129305
if( rc==SQLITE_OK ){
126809129306
rc = rc2;
126810129307
}
126811129308
}
@@ -127190,11 +129687,11 @@
127190129687
int isCreate /* True for xCreate, false for xConnect */
127191129688
){
127192129689
int rc;
127193129690
char *zSql;
127194129691
if( isCreate ){
127195
- int iPageSize;
129692
+ int iPageSize = 0;
127196129693
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
127197129694
rc = getIntFromStmt(db, zSql, &iPageSize);
127198129695
if( rc==SQLITE_OK ){
127199129696
pRtree->iNodeSize = iPageSize-64;
127200129697
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
@@ -127518,10 +130015,11 @@
127518130015
#include <unicode/utypes.h>
127519130016
#include <unicode/uregex.h>
127520130017
#include <unicode/ustring.h>
127521130018
#include <unicode/ucol.h>
127522130019
130020
+/* #include <assert.h> */
127523130021
127524130022
#ifndef SQLITE_CORE
127525130023
SQLITE_EXTENSION_INIT1
127526130024
#else
127527130025
#endif
@@ -127993,19 +130491,20 @@
127993130491
** May you find forgiveness for yourself and forgive others.
127994130492
** May you share freely, never taking more than you give.
127995130493
**
127996130494
*************************************************************************
127997130495
** This file implements a tokenizer for fts3 based on the ICU library.
127998
-**
127999
-** $Id: fts3_icu.c,v 1.3 2008/09/01 18:34:20 danielk1977 Exp $
128000130496
*/
128001
-
128002130497
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
128003130498
#ifdef SQLITE_ENABLE_ICU
128004130499
130500
+/* #include <assert.h> */
130501
+/* #include <string.h> */
128005130502
128006130503
#include <unicode/ubrk.h>
130504
+/* #include <unicode/ucol.h> */
130505
+/* #include <unicode/ustring.h> */
128007130506
#include <unicode/utf16.h>
128008130507
128009130508
typedef struct IcuTokenizer IcuTokenizer;
128010130509
typedef struct IcuCursor IcuCursor;
128011130510
128012130511
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.7. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -385,23 +385,29 @@
385 /*
386 ** Exactly one of the following macros must be defined in order to
387 ** specify which memory allocation subsystem to use.
388 **
389 ** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
 
390 ** SQLITE_MEMDEBUG // Debugging version of system malloc()
 
 
 
 
 
391 **
392 ** (Historical note: There used to be several other options, but we've
393 ** pared it down to just these two.)
394 **
395 ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
396 ** the default.
397 */
398 #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
399 # error "At most one of the following compile-time configuration options\
400 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
401 #endif
402 #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
403 # define SQLITE_SYSTEM_MALLOC 1
404 #endif
405
406 /*
407 ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
@@ -648,13 +654,13 @@
648 **
649 ** See also: [sqlite3_libversion()],
650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651 ** [sqlite_version()] and [sqlite_source_id()].
652 */
653 #define SQLITE_VERSION "3.7.7"
654 #define SQLITE_VERSION_NUMBER 3007007
655 #define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -851,11 +857,11 @@
851 ** semicolon-separate SQL statements passed into its 2nd argument,
852 ** in the context of the [database connection] passed in as its 1st
853 ** argument. ^If the callback function of the 3rd argument to
854 ** sqlite3_exec() is not NULL, then it is invoked for each result row
855 ** coming out of the evaluated SQL statements. ^The 4th argument to
856 ** to sqlite3_exec() is relayed through to the 1st argument of each
857 ** callback invocation. ^If the callback pointer to sqlite3_exec()
858 ** is NULL, then no callback is ever invoked and result rows are
859 ** ignored.
860 **
861 ** ^If an error occurs while evaluating the SQL statements passed into
@@ -1282,20 +1288,52 @@
1282 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
1283 ** VFSes do not need this signal and should silently ignore this opcode.
1284 ** Applications should not call [sqlite3_file_control()] with this
1285 ** opcode as doing so may disrupt the operation of the specialized VFSes
1286 ** that do require it.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1287 */
1288 #define SQLITE_FCNTL_LOCKSTATE 1
1289 #define SQLITE_GET_LOCKPROXYFILE 2
1290 #define SQLITE_SET_LOCKPROXYFILE 3
1291 #define SQLITE_LAST_ERRNO 4
1292 #define SQLITE_FCNTL_SIZE_HINT 5
1293 #define SQLITE_FCNTL_CHUNK_SIZE 6
1294 #define SQLITE_FCNTL_FILE_POINTER 7
1295 #define SQLITE_FCNTL_SYNC_OMITTED 8
1296
 
1297
1298 /*
1299 ** CAPI3REF: Mutex Handle
1300 **
1301 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -1443,11 +1481,11 @@
1443 ** The xSleep() method causes the calling thread to sleep for at
1444 ** least the number of microseconds given. ^The xCurrentTime()
1445 ** method returns a Julian Day Number for the current date and time as
1446 ** a floating point value.
1447 ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
1448 ** Day Number multipled by 86400000 (the number of milliseconds in
1449 ** a 24-hour day).
1450 ** ^SQLite will use the xCurrentTimeInt64() method to get the current
1451 ** date and time if that method is available (if iVersion is 2 or
1452 ** greater and the function pointer is not NULL) and will fall back
1453 ** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
@@ -1719,20 +1757,14 @@
1719 ** also used during testing of SQLite in order to specify an alternative
1720 ** memory allocator that simulates memory out-of-memory conditions in
1721 ** order to verify that SQLite recovers gracefully from such
1722 ** conditions.
1723 **
1724 ** The xMalloc and xFree methods must work like the
1725 ** malloc() and free() functions from the standard C library.
1726 ** The xRealloc method must work like realloc() from the standard C library
1727 ** with the exception that if the second argument to xRealloc is zero,
1728 ** xRealloc must be a no-op - it must not perform any allocation or
1729 ** deallocation. ^SQLite guarantees that the second argument to
1730 ** xRealloc is always a value returned by a prior call to xRoundup.
1731 ** And so in cases where xRoundup always returns a positive number,
1732 ** xRealloc can perform exactly as the standard library realloc() and
1733 ** still be in compliance with this specification.
1734 **
1735 ** xSize should return the allocated size of a memory allocation
1736 ** previously obtained from xMalloc or xRealloc. The allocated size
1737 ** is always at least as big as the requested size but may be larger.
1738 **
@@ -1881,11 +1913,11 @@
1881 ** scratch memory beyond what is provided by this configuration option, then
1882 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1883 **
1884 ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
1885 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1886 ** the database page cache with the default page cache implemenation.
1887 ** This configuration should not be used if an application-define page
1888 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1889 ** There are three arguments to this option: A pointer to 8-byte aligned
1890 ** memory, the size of each page buffer (sz), and the number of pages (N).
1891 ** The sz argument should be the size of the largest database page
@@ -2979,16 +3011,16 @@
2979 ** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
2980 **
2981 ** ^If [URI filename] interpretation is enabled, and the filename argument
2982 ** begins with "file:", then the filename is interpreted as a URI. ^URI
2983 ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2984 ** is set in the fourth argument to sqlite3_open_v2(), or if it has
2985 ** been enabled globally using the [SQLITE_CONFIG_URI] option with the
2986 ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
2987 ** As of SQLite version 3.7.7, URI filename interpretation is turned off
2988 ** by default, but future releases of SQLite might enable URI filename
2989 ** intepretation by default. See "[URI filenames]" for additional
2990 ** information.
2991 **
2992 ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
2993 ** authority, then it must be either an empty string or the string
2994 ** "localhost". ^If the authority is not an empty string or "localhost", an
@@ -3803,11 +3835,11 @@
3803 ** [extended result codes] might be returned as well.
3804 **
3805 ** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
3806 ** database locks it needs to do its job. ^If the statement is a [COMMIT]
3807 ** or occurs outside of an explicit transaction, then you can retry the
3808 ** statement. If the statement is not a [COMMIT] and occurs within a
3809 ** explicit transaction then you should rollback the transaction before
3810 ** continuing.
3811 **
3812 ** ^[SQLITE_DONE] means that the statement has finished executing
3813 ** successfully. sqlite3_step() should not be called again on this virtual
@@ -4082,11 +4114,11 @@
4082
4083 /*
4084 ** CAPI3REF: Destroy A Prepared Statement Object
4085 **
4086 ** ^The sqlite3_finalize() function is called to delete a [prepared statement].
4087 ** ^If the most recent evaluation of the statement encountered no errors or
4088 ** or if the statement is never been evaluated, then sqlite3_finalize() returns
4089 ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
4090 ** sqlite3_finalize(S) returns the appropriate [error code] or
4091 ** [extended error code].
4092 **
@@ -5996,11 +6028,11 @@
5996 ** versions of these routines, it should at least provide stubs that always
5997 ** return true so that one does not get spurious assertion failures.
5998 **
5999 ** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
6000 ** the routine should return 1. This seems counter-intuitive since
6001 ** clearly the mutex cannot be held if it does not exist. But the
6002 ** the reason the mutex does not exist is because the build is not
6003 ** using mutexes. And we do not want the assert() containing the
6004 ** call to sqlite3_mutex_held() to fail, so a non-zero return is
6005 ** the appropriate thing to do. ^The sqlite3_mutex_notheld()
6006 ** interface should also return 1 when given a NULL pointer.
@@ -6119,11 +6151,12 @@
6119 #define SQLITE_TESTCTRL_RESERVE 14
6120 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15
6121 #define SQLITE_TESTCTRL_ISKEYWORD 16
6122 #define SQLITE_TESTCTRL_PGHDRSZ 17
6123 #define SQLITE_TESTCTRL_SCRATCHMALLOC 18
6124 #define SQLITE_TESTCTRL_LAST 18
 
6125
6126 /*
6127 ** CAPI3REF: SQLite Runtime Status
6128 **
6129 ** ^This interface is used to retrieve runtime status information
@@ -6505,11 +6538,11 @@
6505 ** [[the xFetch() page cache methods]]
6506 ** The xFetch() method locates a page in the cache and returns a pointer to
6507 ** the page, or a NULL pointer.
6508 ** A "page", in this context, means a buffer of szPage bytes aligned at an
6509 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
6510 ** mimimum key value is 1. After it has been retrieved using xFetch, the page
6511 ** is considered to be "pinned".
6512 **
6513 ** If the requested page is already in the page cache, then the page cache
6514 ** implementation must return a pointer to the page buffer with its content
6515 ** intact. If the requested page is not already in the cache, then the
@@ -7599,10 +7632,18 @@
7599 */
7600 #ifndef SQLITE_TEMP_STORE
7601 # define SQLITE_TEMP_STORE 1
7602 #endif
7603
 
 
 
 
 
 
 
 
7604 /*
7605 ** GCC does not define the offsetof() macro so we'll have to do it
7606 ** ourselves.
7607 */
7608 #ifndef offsetof
@@ -7941,10 +7982,11 @@
7941 #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
7942 #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
7943 #define BTREE_MEMORY 4 /* This is an in-memory DB */
7944 #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
7945 #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
 
7946
7947 SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
7948 SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
7949 SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
7950 SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
@@ -8143,10 +8185,11 @@
8143 ** or VDBE. The VDBE implements an abstract machine that runs a
8144 ** simple program to access and modify the underlying database.
8145 */
8146 #ifndef _SQLITE_VDBE_H_
8147 #define _SQLITE_VDBE_H_
 
8148
8149 /*
8150 ** A single VDBE is an opaque structure named "Vdbe". Only routines
8151 ** in the source file sqliteVdbe.c are allowed to see the insides
8152 ** of this structure.
@@ -8186,10 +8229,11 @@
8186 Mem *pMem; /* Used when p4type is P4_MEM */
8187 VTable *pVtab; /* Used when p4type is P4_VTAB */
8188 KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
8189 int *ai; /* Used when p4type is P4_INTARRAY */
8190 SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
 
8191 } p4;
8192 #ifdef SQLITE_DEBUG
8193 char *zComment; /* Comment to improve readability */
8194 #endif
8195 #ifdef VDBE_PROFILE
@@ -8241,10 +8285,11 @@
8241 #define P4_REAL (-12) /* P4 is a 64-bit floating point value */
8242 #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
8243 #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
8244 #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
8245 #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
 
8246
8247 /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
8248 ** is made. That copy is freed when the Vdbe is finalized. But if the
8249 ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still
8250 ** gets freed when the Vdbe is finalized so it still should be obtained
@@ -8354,89 +8399,89 @@
8354 #define OP_ReadCookie 35
8355 #define OP_SetCookie 36
8356 #define OP_VerifyCookie 37
8357 #define OP_OpenRead 38
8358 #define OP_OpenWrite 39
8359 #define OP_OpenAutoindex 40
8360 #define OP_OpenEphemeral 41
8361 #define OP_OpenPseudo 42
8362 #define OP_Close 43
8363 #define OP_SeekLt 44
8364 #define OP_SeekLe 45
8365 #define OP_SeekGe 46
8366 #define OP_SeekGt 47
8367 #define OP_Seek 48
8368 #define OP_NotFound 49
8369 #define OP_Found 50
8370 #define OP_IsUnique 51
8371 #define OP_NotExists 52
8372 #define OP_Sequence 53
8373 #define OP_NewRowid 54
8374 #define OP_Insert 55
8375 #define OP_InsertInt 56
8376 #define OP_Delete 57
8377 #define OP_ResetCount 58
8378 #define OP_RowKey 59
8379 #define OP_RowData 60
8380 #define OP_Rowid 61
8381 #define OP_NullRow 62
8382 #define OP_Last 63
8383 #define OP_Sort 64
8384 #define OP_Rewind 65
8385 #define OP_Prev 66
8386 #define OP_Next 67
8387 #define OP_IdxInsert 70
8388 #define OP_IdxDelete 71
8389 #define OP_IdxRowid 72
8390 #define OP_IdxLT 81
8391 #define OP_IdxGE 92
8392 #define OP_Destroy 95
8393 #define OP_Clear 96
8394 #define OP_CreateIndex 97
8395 #define OP_CreateTable 98
8396 #define OP_ParseSchema 99
8397 #define OP_LoadAnalysis 100
8398 #define OP_DropTable 101
8399 #define OP_DropIndex 102
8400 #define OP_DropTrigger 103
8401 #define OP_IntegrityCk 104
8402 #define OP_RowSetAdd 105
8403 #define OP_RowSetRead 106
8404 #define OP_RowSetTest 107
8405 #define OP_Program 108
8406 #define OP_Param 109
8407 #define OP_FkCounter 110
8408 #define OP_FkIfZero 111
8409 #define OP_MemMax 112
8410 #define OP_IfPos 113
8411 #define OP_IfNeg 114
8412 #define OP_IfZero 115
8413 #define OP_AggStep 116
8414 #define OP_AggFinal 117
8415 #define OP_Checkpoint 118
8416 #define OP_JournalMode 119
8417 #define OP_Vacuum 120
8418 #define OP_IncrVacuum 121
8419 #define OP_Expire 122
8420 #define OP_TableLock 123
8421 #define OP_VBegin 124
8422 #define OP_VCreate 125
8423 #define OP_VDestroy 126
8424 #define OP_VOpen 127
8425 #define OP_VFilter 128
8426 #define OP_VColumn 129
8427 #define OP_VNext 131
8428 #define OP_VRename 132
8429 #define OP_VUpdate 133
8430 #define OP_Pagecount 134
8431 #define OP_MaxPgcnt 135
8432 #define OP_Trace 136
8433 #define OP_Noop 137
8434 #define OP_Explain 138
8435
8436 /* The following opcode values are never used */
8437 #define OP_NotUsed_139 139
8438 #define OP_NotUsed_140 140
8439
8440
8441 /* Properties such as "out2" or "jump" that are specified in
8442 ** comments following the "case" for each opcode in the vdbe.c
@@ -8453,23 +8498,23 @@
8453 /* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
8454 /* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
8455 /* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
8456 /* 24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
8457 /* 32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
8458 /* 40 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
8459 /* 48 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00,\
8460 /* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
8461 /* 64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x08, 0x00,\
8462 /* 72 */ 0x02, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8463 /* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
8464 /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x02,\
8465 /* 96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
8466 /* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\
8467 /* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
8468 /* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
8469 /* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x02,\
8470 /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
8471 /* 144 */ 0x04, 0x04,}
8472
8473 /************** End of opcodes.h *********************************************/
8474 /************** Continuing where we left off in vdbe.h ***********************/
8475
@@ -8484,13 +8529,13 @@
8484 SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
8485 SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
8486 SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
8487 SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
8488 SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
8489 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
8490 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
8491 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
8492 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
8493 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
8494 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
8495 SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
8496 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
@@ -8608,10 +8653,11 @@
8608 ** NOTE: These values must match the corresponding BTREE_ values in btree.h.
8609 */
8610 #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
8611 #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
8612 #define PAGER_MEMORY 0x0004 /* In-memory database */
 
8613
8614 /*
8615 ** Valid values for the second argument to sqlite3PagerLockingMode().
8616 */
8617 #define PAGER_LOCKINGMODE_QUERY -1
@@ -8703,10 +8749,13 @@
8703 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
8704 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
8705 SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
8706 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
8707 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
 
 
 
8708
8709 /* Functions used to truncate the database file. */
8710 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
8711
8712 #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
@@ -9556,10 +9605,12 @@
9556 #define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */
9557 #define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
9558 #define SQLITE_IndexCover 0x10 /* Disable index covering table */
9559 #define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
9560 #define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
 
 
9561 #define SQLITE_OptMask 0xff /* Mask of all disablable opts */
9562
9563 /*
9564 ** Possible values for the sqlite.magic field.
9565 ** The numbers are obtained at random and have no special meaning, other
@@ -10447,10 +10498,11 @@
10447 Table *pTab; /* An SQL table corresponding to zName */
10448 Select *pSelect; /* A SELECT statement used in place of a table name */
10449 u8 isPopulated; /* Temporary table associated with SELECT is populated */
10450 u8 jointype; /* Type of join between this able and the previous */
10451 u8 notIndexed; /* True if there is a NOT INDEXED clause */
 
10452 #ifndef SQLITE_OMIT_EXPLAIN
10453 u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
10454 #endif
10455 int iCursor; /* The VDBE cursor number used to access this table */
10456 Expr *pOn; /* The ON clause of a join */
@@ -10566,10 +10618,11 @@
10566 struct WhereInfo {
10567 Parse *pParse; /* Parsing and code generating context */
10568 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
10569 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
10570 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
 
10571 SrcList *pTabList; /* List of tables in the join */
10572 int iTop; /* The very beginning of the WHERE loop */
10573 int iContinue; /* Jump here to continue with next record */
10574 int iBreak; /* Jump here to break out of the loop */
10575 int nLevel; /* Number of nested loop */
@@ -10577,10 +10630,13 @@
10577 double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
10578 double nRowOut; /* Estimated number of output rows */
10579 WhereLevel a[1]; /* Information about each nest loop in WHERE */
10580 };
10581
 
 
 
10582 /*
10583 ** A NameContext defines a context in which to resolve table and column
10584 ** names. The context consists of a list of tables (the pSrcList) field and
10585 ** a list of named expression (pEList). The named expression list may
10586 ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
@@ -11053,10 +11109,11 @@
11053 int isPCacheInit; /* True after malloc is initialized */
11054 sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
11055 int nRefInitMutex; /* Number of users of pInitMutex */
11056 void (*xLog)(void*,int,const char*); /* Function for logging */
11057 void *pLogArg; /* First argument to xLog() */
 
11058 };
11059
11060 /*
11061 ** Context pointer passed down through the tree-walk.
11062 */
@@ -11337,11 +11394,11 @@
11337 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
11338 SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
11339 #endif
11340 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
11341 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11342 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
11343 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
11344 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
11345 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
11346 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
11347 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
@@ -12013,10 +12070,11 @@
12013 0, /* isPCacheInit */
12014 0, /* pInitMutex */
12015 0, /* nRefInitMutex */
12016 0, /* xLog */
12017 0, /* pLogArg */
 
12018 };
12019
12020
12021 /*
12022 ** Hash table for global functions - functions common to all
@@ -12321,10 +12379,13 @@
12321 #ifdef SQLITE_OMIT_LOOKASIDE
12322 "OMIT_LOOKASIDE",
12323 #endif
12324 #ifdef SQLITE_OMIT_MEMORYDB
12325 "OMIT_MEMORYDB",
 
 
 
12326 #endif
12327 #ifdef SQLITE_OMIT_OR_OPTIMIZATION
12328 "OMIT_OR_OPTIMIZATION",
12329 #endif
12330 #ifdef SQLITE_OMIT_PAGER_PRAGMAS
@@ -12387,10 +12448,13 @@
12387 #ifdef SQLITE_OMIT_WSD
12388 "OMIT_WSD",
12389 #endif
12390 #ifdef SQLITE_OMIT_XFER_OPT
12391 "OMIT_XFER_OPT",
 
 
 
12392 #endif
12393 #ifdef SQLITE_PERFORMANCE_TRACE
12394 "PERFORMANCE_TRACE",
12395 #endif
12396 #ifdef SQLITE_PROXY_DEBUG
@@ -12508,10 +12572,13 @@
12508 /*
12509 ** Boolean values
12510 */
12511 typedef unsigned char Bool;
12512
 
 
 
12513 /*
12514 ** A cursor is a pointer into a single BTree within a database file.
12515 ** The cursor can seek to a BTree entry with a particular key, or
12516 ** loop over all entries of the Btree. You can also insert new BTree
12517 ** entries or retrieve the key or data from the entry that the cursor
@@ -12539,10 +12606,11 @@
12539 sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
12540 const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
12541 i64 seqCount; /* Sequence counter */
12542 i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
12543 i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
 
12544
12545 /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
12546 ** OP_IsUnique opcode on this cursor. */
12547 int seekResult;
12548
@@ -12858,17 +12926,36 @@
12858 SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
12859 SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
12860 SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
12861 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
12862 SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
 
 
 
12863 SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
12864 SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
12865 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
12866 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
12867 SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
12868 SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
12869 SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12870
12871 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
12872 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
12873 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
12874 #else
@@ -13159,30 +13246,16 @@
13159 ** Astronomical Algorithms, 2nd Edition, 1998
13160 ** ISBM 0-943396-61-1
13161 ** Willmann-Bell, Inc
13162 ** Richmond, Virginia (USA)
13163 */
 
 
13164 #include <time.h>
13165
13166 #ifndef SQLITE_OMIT_DATETIME_FUNCS
13167
13168 /*
13169 ** On recent Windows platforms, the localtime_s() function is available
13170 ** as part of the "Secure CRT". It is essentially equivalent to
13171 ** localtime_r() available under most POSIX platforms, except that the
13172 ** order of the parameters is reversed.
13173 **
13174 ** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
13175 **
13176 ** If the user has not indicated to use localtime_r() or localtime_s()
13177 ** already, check for an MSVC build environment that provides
13178 ** localtime_s().
13179 */
13180 #if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
13181 defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
13182 #define HAVE_LOCALTIME_S 1
13183 #endif
13184
13185 /*
13186 ** A structure for holding a single date and time.
13187 */
13188 typedef struct DateTime DateTime;
@@ -13523,20 +13596,90 @@
13523 static void clearYMD_HMS_TZ(DateTime *p){
13524 p->validYMD = 0;
13525 p->validHMS = 0;
13526 p->validTZ = 0;
13527 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13528
13529 #ifndef SQLITE_OMIT_LOCALTIME
13530 /*
13531 ** Compute the difference (in milliseconds)
13532 ** between localtime and UTC (a.k.a. GMT)
13533 ** for the time value p where p is in UTC.
 
 
 
13534 */
13535 static sqlite3_int64 localtimeOffset(DateTime *p){
 
 
 
 
13536 DateTime x, y;
13537 time_t t;
 
 
 
 
 
13538 x = *p;
13539 computeYMD_HMS(&x);
13540 if( x.Y<1971 || x.Y>=2038 ){
13541 x.Y = 2000;
13542 x.M = 1;
@@ -13550,51 +13693,27 @@
13550 }
13551 x.tz = 0;
13552 x.validJD = 0;
13553 computeJD(&x);
13554 t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
13555 #ifdef HAVE_LOCALTIME_R
13556 {
13557 struct tm sLocal;
13558 localtime_r(&t, &sLocal);
13559 y.Y = sLocal.tm_year + 1900;
13560 y.M = sLocal.tm_mon + 1;
13561 y.D = sLocal.tm_mday;
13562 y.h = sLocal.tm_hour;
13563 y.m = sLocal.tm_min;
13564 y.s = sLocal.tm_sec;
13565 }
13566 #elif defined(HAVE_LOCALTIME_S) && HAVE_LOCALTIME_S
13567 {
13568 struct tm sLocal;
13569 localtime_s(&sLocal, &t);
13570 y.Y = sLocal.tm_year + 1900;
13571 y.M = sLocal.tm_mon + 1;
13572 y.D = sLocal.tm_mday;
13573 y.h = sLocal.tm_hour;
13574 y.m = sLocal.tm_min;
13575 y.s = sLocal.tm_sec;
13576 }
13577 #else
13578 {
13579 struct tm *pTm;
13580 sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
13581 pTm = localtime(&t);
13582 y.Y = pTm->tm_year + 1900;
13583 y.M = pTm->tm_mon + 1;
13584 y.D = pTm->tm_mday;
13585 y.h = pTm->tm_hour;
13586 y.m = pTm->tm_min;
13587 y.s = pTm->tm_sec;
13588 sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
13589 }
13590 #endif
13591 y.validYMD = 1;
13592 y.validHMS = 1;
13593 y.validJD = 0;
13594 y.validTZ = 0;
13595 computeJD(&y);
 
13596 return y.iJD - x.iJD;
13597 }
13598 #endif /* SQLITE_OMIT_LOCALTIME */
13599
13600 /*
@@ -13614,13 +13733,16 @@
13614 ** weekday N
13615 ** unixepoch
13616 ** localtime
13617 ** utc
13618 **
13619 ** Return 0 on success and 1 if there is any kind of error.
 
 
 
13620 */
13621 static int parseModifier(const char *zMod, DateTime *p){
13622 int rc = 1;
13623 int n;
13624 double r;
13625 char *z, zBuf[30];
13626 z = zBuf;
@@ -13636,13 +13758,12 @@
13636 ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
13637 ** show local time.
13638 */
13639 if( strcmp(z, "localtime")==0 ){
13640 computeJD(p);
13641 p->iJD += localtimeOffset(p);
13642 clearYMD_HMS_TZ(p);
13643 rc = 0;
13644 }
13645 break;
13646 }
13647 #endif
13648 case 'u': {
@@ -13659,15 +13780,16 @@
13659 }
13660 #ifndef SQLITE_OMIT_LOCALTIME
13661 else if( strcmp(z, "utc")==0 ){
13662 sqlite3_int64 c1;
13663 computeJD(p);
13664 c1 = localtimeOffset(p);
13665 p->iJD -= c1;
13666 clearYMD_HMS_TZ(p);
13667 p->iJD += c1 - localtimeOffset(p);
13668 rc = 0;
 
13669 }
13670 #endif
13671 break;
13672 }
13673 case 'w': {
@@ -13844,13 +13966,12 @@
13844 if( !z || parseDateOrTime(context, (char*)z, p) ){
13845 return 1;
13846 }
13847 }
13848 for(i=1; i<argc; i++){
13849 if( (z = sqlite3_value_text(argv[i]))==0 || parseModifier((char*)z, p) ){
13850 return 1;
13851 }
13852 }
13853 return 0;
13854 }
13855
13856
@@ -14344,11 +14465,11 @@
14344 DO_OS_MALLOC_TEST(0);
14345 /* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
14346 ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
14347 ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
14348 ** reaching the VFS. */
14349 rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f3f, pFlagsOut);
14350 assert( rc==SQLITE_OK || pFile->pMethods==0 );
14351 return rc;
14352 }
14353 SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
14354 return pVfs->xDelete(pVfs, zPath, dirSync);
@@ -14880,10 +15001,11 @@
14880 extern void backtrace_symbols_fd(void*const*,int,int);
14881 #else
14882 # define backtrace(A,B) 1
14883 # define backtrace_symbols_fd(A,B,C)
14884 #endif
 
14885
14886 /*
14887 ** Each memory allocation looks like this:
14888 **
14889 ** ------------------------------------------------------------------------
@@ -15805,11 +15927,11 @@
15805 ** Free an outstanding memory allocation.
15806 **
15807 ** This function assumes that the necessary mutexes, if any, are
15808 ** already held by the caller. Hence "Unsafe".
15809 */
15810 void memsys3FreeUnsafe(void *pOld){
15811 Mem3Block *p = (Mem3Block*)pOld;
15812 int i;
15813 u32 size, x;
15814 assert( sqlite3_mutex_held(mem3.mutex) );
15815 assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
@@ -15880,21 +16002,21 @@
15880 }
15881
15882 /*
15883 ** Free memory.
15884 */
15885 void memsys3Free(void *pPrior){
15886 assert( pPrior );
15887 memsys3Enter();
15888 memsys3FreeUnsafe(pPrior);
15889 memsys3Leave();
15890 }
15891
15892 /*
15893 ** Change the size of an existing memory allocation
15894 */
15895 void *memsys3Realloc(void *pPrior, int nBytes){
15896 int nOld;
15897 void *p;
15898 if( pPrior==0 ){
15899 return sqlite3_malloc(nBytes);
15900 }
@@ -17983,10 +18105,11 @@
17983 **
17984 *************************************************************************
17985 **
17986 ** Memory allocation functions used throughout sqlite.
17987 */
 
17988
17989 /*
17990 ** Attempt to release up to n bytes of non-essential memory currently
17991 ** held by SQLite. An example of non-essential memory is memory used to
17992 ** cache database pages that are not currently in use.
@@ -19960,10 +20083,11 @@
19960 ** BOM or Byte Order Mark:
19961 ** 0xff 0xfe little-endian utf-16 follows
19962 ** 0xfe 0xff big-endian utf-16 follows
19963 **
19964 */
 
19965
19966 #ifndef SQLITE_AMALGAMATION
19967 /*
19968 ** The following constant value is used by the SQLITE_BIGENDIAN and
19969 ** SQLITE_LITTLEENDIAN macros.
@@ -20502,10 +20626,11 @@
20502 **
20503 ** This file contains functions for allocating memory, comparing
20504 ** strings, and stuff like that.
20505 **
20506 */
 
20507 #ifdef SQLITE_HAVE_ISNAN
20508 # include <math.h>
20509 #endif
20510
20511 /*
@@ -21634,26 +21759,32 @@
21634 return -x;
21635 }
21636
21637 #ifdef SQLITE_ENABLE_8_3_NAMES
21638 /*
21639 ** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
21640 ** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
21641 ** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
21642 ** three characters, then shorten the suffix on z[] to be the last three
21643 ** characters of the original suffix.
 
 
 
21644 **
21645 ** Examples:
21646 **
21647 ** test.db-journal => test.nal
21648 ** test.db-wal => test.wal
21649 ** test.db-shm => test.shm
21650 */
21651 SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
 
21652 const char *zOk;
21653 zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
21654 if( zOk && sqlite3GetBoolean(zOk) ){
 
 
21655 int i, sz;
21656 sz = sqlite3Strlen30(z);
21657 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
21658 if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
21659 }
@@ -21674,10 +21805,11 @@
21674 **
21675 *************************************************************************
21676 ** This is the implementation of generic hash-tables
21677 ** used in SQLite.
21678 */
 
21679
21680 /* Turn bulk memory into a hash table object by initializing the
21681 ** fields of the Hash structure.
21682 **
21683 ** "pNew" is a pointer to the hash table that is to be initialized.
@@ -21982,52 +22114,52 @@
21982 /* 35 */ "ReadCookie",
21983 /* 36 */ "SetCookie",
21984 /* 37 */ "VerifyCookie",
21985 /* 38 */ "OpenRead",
21986 /* 39 */ "OpenWrite",
21987 /* 40 */ "OpenAutoindex",
21988 /* 41 */ "OpenEphemeral",
21989 /* 42 */ "OpenPseudo",
21990 /* 43 */ "Close",
21991 /* 44 */ "SeekLt",
21992 /* 45 */ "SeekLe",
21993 /* 46 */ "SeekGe",
21994 /* 47 */ "SeekGt",
21995 /* 48 */ "Seek",
21996 /* 49 */ "NotFound",
21997 /* 50 */ "Found",
21998 /* 51 */ "IsUnique",
21999 /* 52 */ "NotExists",
22000 /* 53 */ "Sequence",
22001 /* 54 */ "NewRowid",
22002 /* 55 */ "Insert",
22003 /* 56 */ "InsertInt",
22004 /* 57 */ "Delete",
22005 /* 58 */ "ResetCount",
22006 /* 59 */ "RowKey",
22007 /* 60 */ "RowData",
22008 /* 61 */ "Rowid",
22009 /* 62 */ "NullRow",
22010 /* 63 */ "Last",
22011 /* 64 */ "Sort",
22012 /* 65 */ "Rewind",
22013 /* 66 */ "Prev",
22014 /* 67 */ "Next",
22015 /* 68 */ "Or",
22016 /* 69 */ "And",
22017 /* 70 */ "IdxInsert",
22018 /* 71 */ "IdxDelete",
22019 /* 72 */ "IdxRowid",
22020 /* 73 */ "IsNull",
22021 /* 74 */ "NotNull",
22022 /* 75 */ "Ne",
22023 /* 76 */ "Eq",
22024 /* 77 */ "Gt",
22025 /* 78 */ "Le",
22026 /* 79 */ "Lt",
22027 /* 80 */ "Ge",
22028 /* 81 */ "IdxLT",
22029 /* 82 */ "BitAnd",
22030 /* 83 */ "BitOr",
22031 /* 84 */ "ShiftLeft",
22032 /* 85 */ "ShiftRight",
22033 /* 86 */ "Add",
@@ -22034,58 +22166,58 @@
22034 /* 87 */ "Subtract",
22035 /* 88 */ "Multiply",
22036 /* 89 */ "Divide",
22037 /* 90 */ "Remainder",
22038 /* 91 */ "Concat",
22039 /* 92 */ "IdxGE",
22040 /* 93 */ "BitNot",
22041 /* 94 */ "String8",
22042 /* 95 */ "Destroy",
22043 /* 96 */ "Clear",
22044 /* 97 */ "CreateIndex",
22045 /* 98 */ "CreateTable",
22046 /* 99 */ "ParseSchema",
22047 /* 100 */ "LoadAnalysis",
22048 /* 101 */ "DropTable",
22049 /* 102 */ "DropIndex",
22050 /* 103 */ "DropTrigger",
22051 /* 104 */ "IntegrityCk",
22052 /* 105 */ "RowSetAdd",
22053 /* 106 */ "RowSetRead",
22054 /* 107 */ "RowSetTest",
22055 /* 108 */ "Program",
22056 /* 109 */ "Param",
22057 /* 110 */ "FkCounter",
22058 /* 111 */ "FkIfZero",
22059 /* 112 */ "MemMax",
22060 /* 113 */ "IfPos",
22061 /* 114 */ "IfNeg",
22062 /* 115 */ "IfZero",
22063 /* 116 */ "AggStep",
22064 /* 117 */ "AggFinal",
22065 /* 118 */ "Checkpoint",
22066 /* 119 */ "JournalMode",
22067 /* 120 */ "Vacuum",
22068 /* 121 */ "IncrVacuum",
22069 /* 122 */ "Expire",
22070 /* 123 */ "TableLock",
22071 /* 124 */ "VBegin",
22072 /* 125 */ "VCreate",
22073 /* 126 */ "VDestroy",
22074 /* 127 */ "VOpen",
22075 /* 128 */ "VFilter",
22076 /* 129 */ "VColumn",
22077 /* 130 */ "Real",
22078 /* 131 */ "VNext",
22079 /* 132 */ "VRename",
22080 /* 133 */ "VUpdate",
22081 /* 134 */ "Pagecount",
22082 /* 135 */ "MaxPgcnt",
22083 /* 136 */ "Trace",
22084 /* 137 */ "Noop",
22085 /* 138 */ "Explain",
22086 /* 139 */ "NotUsed_139",
22087 /* 140 */ "NotUsed_140",
22088 /* 141 */ "ToText",
22089 /* 142 */ "ToBlob",
22090 /* 143 */ "ToNumeric",
22091 /* 144 */ "ToInt",
@@ -22183,14 +22315,17 @@
22183 #ifdef MEMORY_DEBUG
22184 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
22185 #endif
22186
22187 #ifdef SQLITE_DEBUG
22188 SQLITE_PRIVATE int sqlite3OSTrace = 0;
22189 #define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
 
 
 
22190 #else
22191 #define OSTRACE(X)
22192 #endif
22193
22194 /*
22195 ** Macros for performance tracing. Normally turned off. Only works
22196 ** on i486 hardware.
@@ -24343,10 +24478,11 @@
24343 */
24344 #include <sys/types.h>
24345 #include <sys/stat.h>
24346 #include <fcntl.h>
24347 #include <unistd.h>
 
24348 #include <sys/time.h>
24349 #include <errno.h>
24350 #ifndef SQLITE_OMIT_WAL
24351 #include <sys/mman.h>
24352 #endif
@@ -24364,10 +24500,14 @@
24364
24365 #if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
24366 # include <sys/mount.h>
24367 #endif
24368
 
 
 
 
24369 /*
24370 ** Allowed values of unixFile.fsFlags
24371 */
24372 #define SQLITE_FSFLAGS_IS_MSDOS 0x1
24373
@@ -24374,10 +24514,11 @@
24374 /*
24375 ** If we are to be thread-safe, include the pthreads header and define
24376 ** the SQLITE_UNIX_THREADS macro.
24377 */
24378 #if SQLITE_THREADSAFE
 
24379 # define SQLITE_UNIX_THREADS 1
24380 #endif
24381
24382 /*
24383 ** Default permissions when creating a new file
@@ -24429,11 +24570,10 @@
24429 typedef struct unixFile unixFile;
24430 struct unixFile {
24431 sqlite3_io_methods const *pMethod; /* Always the first entry */
24432 unixInodeInfo *pInode; /* Info about locks on this inode */
24433 int h; /* The file descriptor */
24434 int dirfd; /* File descriptor for the directory */
24435 unsigned char eFileLock; /* The type of lock held on this fd */
24436 unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
24437 int lastErrno; /* The unix errno from last I/O error */
24438 void *lockingContext; /* Locking style specific state */
24439 UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
@@ -24471,12 +24611,18 @@
24471 };
24472
24473 /*
24474 ** Allowed values for the unixFile.ctrlFlags bitmask:
24475 */
24476 #define UNIXFILE_EXCL 0x01 /* Connections from one process only */
24477 #define UNIXFILE_RDONLY 0x02 /* Connection is read only */
 
 
 
 
 
 
24478
24479 /*
24480 ** Include code that is common to all os_*.c files
24481 */
24482 /************** Include os_common.h in the middle of os_unix.c ***************/
@@ -24511,14 +24657,17 @@
24511 #ifdef MEMORY_DEBUG
24512 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
24513 #endif
24514
24515 #ifdef SQLITE_DEBUG
24516 SQLITE_PRIVATE int sqlite3OSTrace = 0;
24517 #define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
 
 
 
24518 #else
24519 #define OSTRACE(X)
24520 #endif
24521
24522 /*
24523 ** Macros for performance tracing. Normally turned off. Only works
24524 ** on i486 hardware.
@@ -24723,10 +24872,13 @@
24723 */
24724 static int posixOpen(const char *zFile, int flags, int mode){
24725 return open(zFile, flags, mode);
24726 }
24727
 
 
 
24728 /*
24729 ** Many system calls are accessed through pointer-to-functions so that
24730 ** they may be overridden at runtime to facilitate fault injection during
24731 ** testing and sandboxing. The following array holds the names and pointers
24732 ** to all overrideable system calls.
@@ -24819,10 +24971,16 @@
24819 #else
24820 { "fallocate", (sqlite3_syscall_ptr)0, 0 },
24821 #endif
24822 #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
24823
 
 
 
 
 
 
24824 }; /* End of the overrideable system calls */
24825
24826 /*
24827 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
24828 ** "unix" VFSes. Return SQLITE_OK opon successfully updating the
@@ -25103,11 +25261,13 @@
25103 case EINVAL:
25104 case ENOTCONN:
25105 case ENODEV:
25106 case ENXIO:
25107 case ENOENT:
 
25108 case ESTALE:
 
25109 case ENOSYS:
25110 /* these should force the client to close the file and reconnect */
25111
25112 default:
25113 return sqliteIOErr;
@@ -26173,22 +26333,18 @@
26173 ** even on VxWorks. A mutex will be acquired on VxWorks by the
26174 ** vxworksReleaseFileId() routine.
26175 */
26176 static int closeUnixFile(sqlite3_file *id){
26177 unixFile *pFile = (unixFile*)id;
26178 if( pFile->dirfd>=0 ){
26179 robust_close(pFile, pFile->dirfd, __LINE__);
26180 pFile->dirfd=-1;
26181 }
26182 if( pFile->h>=0 ){
26183 robust_close(pFile, pFile->h, __LINE__);
26184 pFile->h = -1;
26185 }
26186 #if OS_VXWORKS
26187 if( pFile->pId ){
26188 if( pFile->isDelete ){
26189 unlink(pFile->pId->zCanonicalName);
26190 }
26191 vxworksReleaseFileId(pFile->pId);
26192 pFile->pId = 0;
26193 }
26194 #endif
@@ -26369,12 +26525,14 @@
26369 /* If we have any lock, then the lock file already exists. All we have
26370 ** to do is adjust our internal record of the lock level.
26371 */
26372 if( pFile->eFileLock > NO_LOCK ){
26373 pFile->eFileLock = eFileLock;
26374 #if !OS_VXWORKS
26375 /* Always update the timestamp on the old file */
 
 
 
26376 utimes(zLockFile, NULL);
26377 #endif
26378 return SQLITE_OK;
26379 }
26380
@@ -26431,11 +26589,11 @@
26431 return SQLITE_OK;
26432 }
26433
26434 /* To fully unlock the database, delete the lock file */
26435 assert( eFileLock==NO_LOCK );
26436 if( unlink(zLockFile) ){
26437 int rc = 0;
26438 int tErrno = errno;
26439 if( ENOENT != tErrno ){
26440 rc = SQLITE_IOERR_UNLOCK;
26441 }
@@ -26937,15 +27095,16 @@
26937 */
26938 static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
26939 int rc = SQLITE_OK;
26940 int reserved = 0;
26941 unixFile *pFile = (unixFile*)id;
 
26942
26943 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
26944
26945 assert( pFile );
26946 afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
26947 if( context->reserved ){
26948 *pResOut = 1;
26949 return SQLITE_OK;
26950 }
26951 unixEnterMutex(); /* Because pFile->pInode is shared across threads */
@@ -27081,11 +27240,11 @@
27081
27082 /* If control gets to this point, then actually go ahead and make
27083 ** operating system calls for the specified lock.
27084 */
27085 if( eFileLock==SHARED_LOCK ){
27086 int lrc1, lrc2, lrc1Errno;
27087 long lk, mask;
27088
27089 assert( pInode->nShared==0 );
27090 assert( pInode->eFileLock==0 );
27091
@@ -27455,21 +27614,23 @@
27455 #if defined(USE_PREAD)
27456 do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
27457 #elif defined(USE_PREAD64)
27458 do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
27459 #else
27460 newOffset = lseek(id->h, offset, SEEK_SET);
27461 SimulateIOError( newOffset-- );
27462 if( newOffset!=offset ){
27463 if( newOffset == -1 ){
27464 ((unixFile*)id)->lastErrno = errno;
27465 }else{
27466 ((unixFile*)id)->lastErrno = 0;
27467 }
27468 return -1;
27469 }
27470 do{ got = osWrite(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
 
 
27471 #endif
27472 TIMER_END;
27473 if( got<0 ){
27474 ((unixFile*)id)->lastErrno = errno;
27475 }
@@ -27666,10 +27827,54 @@
27666 if( OS_VXWORKS && rc!= -1 ){
27667 rc = 0;
27668 }
27669 return rc;
27670 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27671
27672 /*
27673 ** Make sure all writes to a particular file are committed to disk.
27674 **
27675 ** If dataOnly==0 then both the file itself and its metadata (file
@@ -27707,32 +27912,27 @@
27707 SimulateIOError( rc=1 );
27708 if( rc ){
27709 pFile->lastErrno = errno;
27710 return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
27711 }
27712 if( pFile->dirfd>=0 ){
27713 OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
 
 
 
 
 
 
27714 HAVE_FULLFSYNC, isFullsync));
27715 #ifndef SQLITE_DISABLE_DIRSYNC
27716 /* The directory sync is only attempted if full_fsync is
27717 ** turned off or unavailable. If a full_fsync occurred above,
27718 ** then the directory sync is superfluous.
27719 */
27720 if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
27721 /*
27722 ** We have received multiple reports of fsync() returning
27723 ** errors when applied to directories on certain file systems.
27724 ** A failed directory sync is not a big deal. So it seems
27725 ** better to ignore the error. Ticket #1657
27726 */
27727 /* pFile->lastErrno = errno; */
27728 /* return SQLITE_IOERR; */
27729 }
27730 #endif
27731 /* Only need to sync once, so close the directory when we are done */
27732 robust_close(pFile, pFile->dirfd, __LINE__);
27733 pFile->dirfd = -1;
27734 }
27735 return rc;
27736 }
27737
27738 /*
@@ -27810,15 +28010,13 @@
27810 static int proxyFileControl(sqlite3_file*,int,void*);
27811 #endif
27812
27813 /*
27814 ** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
27815 ** file-control operation.
27816 **
27817 ** If the user has configured a chunk-size for this file, it could be
27818 ** that the file needs to be extended at this point. Otherwise, the
27819 ** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
27820 */
27821 static int fcntlSizeHint(unixFile *pFile, i64 nByte){
27822 if( pFile->szChunk ){
27823 i64 nSize; /* Required file size */
27824 struct stat buf; /* Used to hold return values of fstat() */
@@ -27866,25 +28064,41 @@
27866
27867 /*
27868 ** Information and control of an open file handle.
27869 */
27870 static int unixFileControl(sqlite3_file *id, int op, void *pArg){
 
27871 switch( op ){
27872 case SQLITE_FCNTL_LOCKSTATE: {
27873 *(int*)pArg = ((unixFile*)id)->eFileLock;
27874 return SQLITE_OK;
27875 }
27876 case SQLITE_LAST_ERRNO: {
27877 *(int*)pArg = ((unixFile*)id)->lastErrno;
27878 return SQLITE_OK;
27879 }
27880 case SQLITE_FCNTL_CHUNK_SIZE: {
27881 ((unixFile*)id)->szChunk = *(int *)pArg;
27882 return SQLITE_OK;
27883 }
27884 case SQLITE_FCNTL_SIZE_HINT: {
27885 return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27886 }
27887 #ifndef NDEBUG
27888 /* The pager calls this method to signal that it has done
27889 ** a rollback and that the database is therefore unchanged and
27890 ** it hence it is OK for the transaction change counter to be
@@ -28096,11 +28310,11 @@
28096 unixShmNode *p = pFd->pInode->pShmNode;
28097 assert( unixMutexHeld() );
28098 if( p && p->nRef==0 ){
28099 int i;
28100 assert( p->pInode==pFd->pInode );
28101 if( p->mutex ) sqlite3_mutex_free(p->mutex);
28102 for(i=0; i<p->nRegion; i++){
28103 if( p->h>=0 ){
28104 munmap(p->apRegion[i], p->szRegion);
28105 }else{
28106 sqlite3_free(p->apRegion[i]);
@@ -28565,11 +28779,11 @@
28565 ** shared-memory file, too */
28566 unixEnterMutex();
28567 assert( pShmNode->nRef>0 );
28568 pShmNode->nRef--;
28569 if( pShmNode->nRef==0 ){
28570 if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename);
28571 unixShmPurge(pDbFd);
28572 }
28573 unixLeaveMutex();
28574
28575 return SQLITE_OK;
@@ -28878,11 +29092,11 @@
28878 ** Initialize the contents of the unixFile structure pointed to by pId.
28879 */
28880 static int fillInUnixFile(
28881 sqlite3_vfs *pVfs, /* Pointer to vfs object */
28882 int h, /* Open file descriptor of file being opened */
28883 int dirfd, /* Directory file descriptor */
28884 sqlite3_file *pId, /* Write to the unixFile structure here */
28885 const char *zFilename, /* Name of the file being opened */
28886 int noLock, /* Omit locking if true */
28887 int isDelete, /* Delete on close if true */
28888 int isReadOnly /* True if the file is opened read-only */
@@ -28909,20 +29123,22 @@
28909 assert( zFilename==0 || zFilename[0]=='/' );
28910 #endif
28911
28912 OSTRACE(("OPEN %-3d %s\n", h, zFilename));
28913 pNew->h = h;
28914 pNew->dirfd = dirfd;
28915 pNew->zPath = zFilename;
28916 if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
28917 pNew->ctrlFlags = UNIXFILE_EXCL;
28918 }else{
28919 pNew->ctrlFlags = 0;
28920 }
28921 if( isReadOnly ){
28922 pNew->ctrlFlags |= UNIXFILE_RDONLY;
28923 }
 
 
 
28924
28925 #if OS_VXWORKS
28926 pNew->pId = vxworksFindFileId(zFilename);
28927 if( pNew->pId==0 ){
28928 noLock = 1;
@@ -29045,56 +29261,24 @@
29045 pNew->lastErrno = 0;
29046 #if OS_VXWORKS
29047 if( rc!=SQLITE_OK ){
29048 if( h>=0 ) robust_close(pNew, h, __LINE__);
29049 h = -1;
29050 unlink(zFilename);
29051 isDelete = 0;
29052 }
29053 pNew->isDelete = isDelete;
29054 #endif
29055 if( rc!=SQLITE_OK ){
29056 if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__);
29057 if( h>=0 ) robust_close(pNew, h, __LINE__);
29058 }else{
29059 pNew->pMethod = pLockingStyle;
29060 OpenCounter(+1);
29061 }
29062 return rc;
29063 }
29064
29065 /*
29066 ** Open a file descriptor to the directory containing file zFilename.
29067 ** If successful, *pFd is set to the opened file descriptor and
29068 ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
29069 ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
29070 ** value.
29071 **
29072 ** If SQLITE_OK is returned, the caller is responsible for closing
29073 ** the file descriptor *pFd using close().
29074 */
29075 static int openDirectory(const char *zFilename, int *pFd){
29076 int ii;
29077 int fd = -1;
29078 char zDirname[MAX_PATHNAME+1];
29079
29080 sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
29081 for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
29082 if( ii>0 ){
29083 zDirname[ii] = '\0';
29084 fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
29085 if( fd>=0 ){
29086 #ifdef FD_CLOEXEC
29087 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
29088 #endif
29089 OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
29090 }
29091 }
29092 *pFd = fd;
29093 return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
29094 }
29095
29096 /*
29097 ** Return the name of a directory in which to put temporary files.
29098 ** If no suitable temporary file directory can be found, return NULL.
29099 */
29100 static const char *unixTempFileDir(void){
@@ -29205,11 +29389,11 @@
29205 ** ignored and -1 is returned. The caller will try to open a new file
29206 ** descriptor on the same path, fail, and return an error to SQLite.
29207 **
29208 ** Even if a subsequent open() call does succeed, the consequences of
29209 ** not searching for a resusable file descriptor are not dire. */
29210 if( 0==stat(zPath, &sStat) ){
29211 unixInodeInfo *pInode;
29212
29213 unixEnterMutex();
29214 pInode = inodeList;
29215 while( pInode && (pInode->fileId.dev!=sStat.st_dev
@@ -29281,11 +29465,11 @@
29281 while( nDb>0 && zPath[nDb]!='-' ) nDb--;
29282 if( nDb==0 ) return SQLITE_OK;
29283 memcpy(zDb, zPath, nDb);
29284 zDb[nDb] = '\0';
29285
29286 if( 0==stat(zDb, &sStat) ){
29287 *pMode = sStat.st_mode & 0777;
29288 }else{
29289 rc = SQLITE_IOERR_FSTAT;
29290 }
29291 }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
@@ -29323,11 +29507,10 @@
29323 int flags, /* Input flags to control the opening */
29324 int *pOutFlags /* Output flags returned to SQLite core */
29325 ){
29326 unixFile *p = (unixFile *)pFile;
29327 int fd = -1; /* File descriptor returned by open() */
29328 int dirfd = -1; /* Directory file descriptor */
29329 int openFlags = 0; /* Flags to pass to open() */
29330 int eType = flags&0xFFFFFF00; /* Type of file to open */
29331 int noLock; /* True to omit locking primitives */
29332 int rc = SQLITE_OK; /* Function Return Code */
29333
@@ -29337,16 +29520,19 @@
29337 int isReadonly = (flags & SQLITE_OPEN_READONLY);
29338 int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
29339 #if SQLITE_ENABLE_LOCKING_STYLE
29340 int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
29341 #endif
 
 
 
29342
29343 /* If creating a master or main-file journal, this function will open
29344 ** a file-descriptor on the directory too. The first time unixSync()
29345 ** is called the directory file descriptor will be fsync()ed and close()d.
29346 */
29347 int isOpenDirectory = (isCreate && (
29348 eType==SQLITE_OPEN_MASTER_JOURNAL
29349 || eType==SQLITE_OPEN_MAIN_JOURNAL
29350 || eType==SQLITE_OPEN_WAL
29351 ));
29352
@@ -29396,11 +29582,11 @@
29396 }
29397 }
29398 p->pUnused = pUnused;
29399 }else if( !zName ){
29400 /* If zName is NULL, the upper layer is requesting a temp file. */
29401 assert(isDelete && !isOpenDirectory);
29402 rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
29403 if( rc!=SQLITE_OK ){
29404 return rc;
29405 }
29406 zName = zTmpname;
@@ -29452,44 +29638,29 @@
29452
29453 if( isDelete ){
29454 #if OS_VXWORKS
29455 zPath = zName;
29456 #else
29457 unlink(zName);
29458 #endif
29459 }
29460 #if SQLITE_ENABLE_LOCKING_STYLE
29461 else{
29462 p->openFlags = openFlags;
29463 }
29464 #endif
29465
29466 if( isOpenDirectory ){
29467 rc = openDirectory(zPath, &dirfd);
29468 if( rc!=SQLITE_OK ){
29469 /* It is safe to close fd at this point, because it is guaranteed not
29470 ** to be open on a database file. If it were open on a database file,
29471 ** it would not be safe to close as this would release any locks held
29472 ** on the file by this process. */
29473 assert( eType!=SQLITE_OPEN_MAIN_DB );
29474 robust_close(p, fd, __LINE__);
29475 goto open_finished;
29476 }
29477 }
29478
29479 #ifdef FD_CLOEXEC
29480 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
29481 #endif
29482
29483 noLock = eType!=SQLITE_OPEN_MAIN_DB;
29484
29485
29486 #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
29487 struct statfs fsInfo;
29488 if( fstatfs(fd, &fsInfo) == -1 ){
29489 ((unixFile*)pFile)->lastErrno = errno;
29490 if( dirfd>=0 ) robust_close(p, dirfd, __LINE__);
29491 robust_close(p, fd, __LINE__);
29492 return SQLITE_IOERR_ACCESS;
29493 }
29494 if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
29495 ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
@@ -29507,31 +29678,27 @@
29507 /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
29508 ** never use proxy, NULL means use proxy for non-local files only. */
29509 if( envforce!=NULL ){
29510 useProxy = atoi(envforce)>0;
29511 }else{
29512 struct statfs fsInfo;
29513 if( statfs(zPath, &fsInfo) == -1 ){
29514 /* In theory, the close(fd) call is sub-optimal. If the file opened
29515 ** with fd is a database file, and there are other connections open
29516 ** on that file that are currently holding advisory locks on it,
29517 ** then the call to close() will cancel those locks. In practice,
29518 ** we're assuming that statfs() doesn't fail very often. At least
29519 ** not while other file descriptors opened by the same process on
29520 ** the same file are working. */
29521 p->lastErrno = errno;
29522 if( dirfd>=0 ){
29523 robust_close(p, dirfd, __LINE__);
29524 }
29525 robust_close(p, fd, __LINE__);
29526 rc = SQLITE_IOERR_ACCESS;
29527 goto open_finished;
29528 }
29529 useProxy = !(fsInfo.f_flags&MNT_LOCAL);
29530 }
29531 if( useProxy ){
29532 rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
29533 isDelete, isReadonly);
29534 if( rc==SQLITE_OK ){
29535 rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
29536 if( rc!=SQLITE_OK ){
29537 /* Use unixClose to clean up the resources added in fillInUnixFile
@@ -29545,11 +29712,11 @@
29545 goto open_finished;
29546 }
29547 }
29548 #endif
29549
29550 rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
29551 isDelete, isReadonly);
29552 open_finished:
29553 if( rc!=SQLITE_OK ){
29554 sqlite3_free(p->pUnused);
29555 }
@@ -29567,17 +29734,17 @@
29567 int dirSync /* If true, fsync() directory after deleting file */
29568 ){
29569 int rc = SQLITE_OK;
29570 UNUSED_PARAMETER(NotUsed);
29571 SimulateIOError(return SQLITE_IOERR_DELETE);
29572 if( unlink(zPath)==(-1) && errno!=ENOENT ){
29573 return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
29574 }
29575 #ifndef SQLITE_DISABLE_DIRSYNC
29576 if( dirSync ){
29577 int fd;
29578 rc = openDirectory(zPath, &fd);
29579 if( rc==SQLITE_OK ){
29580 #if OS_VXWORKS
29581 if( fsync(fd)==-1 )
29582 #else
29583 if( fsync(fd) )
@@ -29584,10 +29751,12 @@
29584 #endif
29585 {
29586 rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
29587 }
29588 robust_close(0, fd, __LINE__);
 
 
29589 }
29590 }
29591 #endif
29592 return rc;
29593 }
@@ -29626,11 +29795,11 @@
29626 assert(!"Invalid flags argument");
29627 }
29628 *pResOut = (osAccess(zPath, amode)==0);
29629 if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
29630 struct stat buf;
29631 if( 0==stat(zPath, &buf) && buf.st_size==0 ){
29632 *pResOut = 0;
29633 }
29634 }
29635 return SQLITE_OK;
29636 }
@@ -30145,11 +30314,10 @@
30145 const char *path, /* path for the new unixFile */
30146 unixFile **ppFile, /* unixFile created and returned by ref */
30147 int islockfile /* if non zero missing dirs will be created */
30148 ) {
30149 int fd = -1;
30150 int dirfd = -1;
30151 unixFile *pNew;
30152 int rc = SQLITE_OK;
30153 int openFlags = O_RDWR | O_CREAT;
30154 sqlite3_vfs dummyVfs;
30155 int terrno = 0;
@@ -30210,11 +30378,11 @@
30210 dummyVfs.zName = "dummy";
30211 pUnused->fd = fd;
30212 pUnused->flags = openFlags;
30213 pNew->pUnused = pUnused;
30214
30215 rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0);
30216 if( rc==SQLITE_OK ){
30217 *ppFile = pNew;
30218 return SQLITE_OK;
30219 }
30220 end_create_proxy:
@@ -30250,10 +30418,12 @@
30250 *pError = err;
30251 }
30252 return SQLITE_IOERR;
30253 }
30254 }
 
 
30255 #endif
30256 #ifdef SQLITE_TEST
30257 /* simulate multiple hosts by creating unique hostid file paths */
30258 if( sqlite3_hostid_num != 0){
30259 pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
@@ -30324,11 +30494,11 @@
30324 conchFile->openFlags = O_RDWR | O_CREAT;
30325
30326 end_breaklock:
30327 if( rc ){
30328 if( fd>=0 ){
30329 unlink(tPath);
30330 robust_close(pFile, fd, __LINE__);
30331 }
30332 fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
30333 }
30334 return rc;
@@ -30342,10 +30512,11 @@
30342 unixFile *conchFile = pCtx->conchFile;
30343 int rc = SQLITE_OK;
30344 int nTries = 0;
30345 struct timespec conchModTime;
30346
 
30347 do {
30348 rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
30349 nTries ++;
30350 if( rc==SQLITE_BUSY ){
30351 /* If the lock failed (busy):
@@ -30573,15 +30744,16 @@
30573 conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
30574
30575 end_takeconch:
30576 OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
30577 if( rc==SQLITE_OK && pFile->openFlags ){
 
30578 if( pFile->h>=0 ){
30579 robust_close(pFile, pFile->h, __LINE__);
30580 }
30581 pFile->h = -1;
30582 int fd = robust_open(pCtx->dbPath, pFile->openFlags,
30583 SQLITE_DEFAULT_FILE_PERMISSIONS);
30584 OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
30585 if( fd>=0 ){
30586 pFile->h = fd;
30587 }else{
@@ -31147,11 +31319,11 @@
31147 };
31148 unsigned int i; /* Loop counter */
31149
31150 /* Double-check that the aSyscall[] array has been constructed
31151 ** correctly. See ticket [bb3a86e890c8e96ab] */
31152 assert( ArraySize(aSyscall)==16 );
31153
31154 /* Register all VFSes defined in the aVfs[] array */
31155 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
31156 sqlite3_vfs_register(&aVfs[i], i==0);
31157 }
@@ -31264,14 +31436,17 @@
31264 #ifdef MEMORY_DEBUG
31265 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
31266 #endif
31267
31268 #ifdef SQLITE_DEBUG
31269 SQLITE_PRIVATE int sqlite3OSTrace = 0;
31270 #define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
 
 
 
31271 #else
31272 #define OSTRACE(X)
31273 #endif
31274
31275 /*
31276 ** Macros for performance tracing. Normally turned off. Only works
31277 ** on i486 hardware.
@@ -31479,12 +31654,13 @@
31479 typedef struct winFile winFile;
31480 struct winFile {
31481 const sqlite3_io_methods *pMethod; /*** Must be first ***/
31482 sqlite3_vfs *pVfs; /* The VFS used to open this file */
31483 HANDLE h; /* Handle for accessing the file */
31484 unsigned char locktype; /* Type of lock currently held on this file */
31485 short sharedLockByte; /* Randomly chosen byte used as a shared lock */
 
31486 DWORD lastErrno; /* The Windows errno from the last I/O error */
31487 DWORD sectorSize; /* Sector size of the device file is on */
31488 winShm *pShm; /* Instance of shared memory on this file */
31489 const char *zPath; /* Full pathname of this file */
31490 int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
@@ -31495,10 +31671,80 @@
31495 winceLock local; /* Locks obtained by this instance of winFile */
31496 winceLock *shared; /* Global shared lock memory for the file */
31497 #endif
31498 };
31499
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31500
31501 /*
31502 ** Forward prototypes.
31503 */
31504 static int getSectorSize(
@@ -31547,10 +31793,192 @@
31547 }
31548 return sqlite3_os_type==2;
31549 }
31550 #endif /* SQLITE_OS_WINCE */
31551
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31552 /*
31553 ** Convert a UTF-8 string to microsoft unicode (UTF-16?).
31554 **
31555 ** Space to hold the returned string is obtained from malloc.
31556 */
@@ -31778,19 +32206,68 @@
31778 iLine, iErrno, zFunc, zPath, zMsg
31779 );
31780
31781 return errcode;
31782 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31783
31784 #if SQLITE_OS_WINCE
31785 /*************************************************************************
31786 ** This section contains code for WinCE only.
31787 */
31788 /*
31789 ** WindowsCE does not have a localtime() function. So create a
31790 ** substitute.
31791 */
 
31792 struct tm *__cdecl localtime(const time_t *t)
31793 {
31794 static struct tm y;
31795 FILETIME uTm, lTm;
31796 SYSTEMTIME pTm;
@@ -32196,22 +32673,25 @@
32196 int amt, /* Number of bytes to read */
32197 sqlite3_int64 offset /* Begin reading at this offset */
32198 ){
32199 winFile *pFile = (winFile*)id; /* file handle */
32200 DWORD nRead; /* Number of bytes actually read from file */
 
32201
32202 assert( id!=0 );
32203 SimulateIOError(return SQLITE_IOERR_READ);
32204 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
32205
32206 if( seekWinFile(pFile, offset) ){
32207 return SQLITE_FULL;
32208 }
32209 if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
 
32210 pFile->lastErrno = GetLastError();
32211 return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
32212 }
 
32213 if( nRead<(DWORD)amt ){
32214 /* Unread parts of the buffer must be zero-filled */
32215 memset(&((char*)pBuf)[nRead], 0, amt-nRead);
32216 return SQLITE_IOERR_SHORT_READ;
32217 }
@@ -32229,10 +32709,11 @@
32229 int amt, /* Number of bytes to write */
32230 sqlite3_int64 offset /* Offset into the file to begin writing at */
32231 ){
32232 int rc; /* True if error has occured, else false */
32233 winFile *pFile = (winFile*)id; /* File handle */
 
32234
32235 assert( amt>0 );
32236 assert( pFile );
32237 SimulateIOError(return SQLITE_IOERR_WRITE);
32238 SimulateDiskfullError(return SQLITE_FULL);
@@ -32243,11 +32724,16 @@
32243 if( rc==0 ){
32244 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
32245 int nRem = amt; /* Number of bytes yet to be written */
32246 DWORD nWrite; /* Bytes written by each WriteFile() call */
32247
32248 while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
 
 
 
 
 
32249 aRem += nWrite;
32250 nRem -= nWrite;
32251 }
32252 if( nRem>0 ){
32253 pFile->lastErrno = GetLastError();
@@ -32254,14 +32740,17 @@
32254 rc = 1;
32255 }
32256 }
32257
32258 if( rc ){
32259 if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
 
32260 return SQLITE_FULL;
32261 }
32262 return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
 
 
32263 }
32264 return SQLITE_OK;
32265 }
32266
32267 /*
@@ -32651,32 +33140,63 @@
32651
32652 /*
32653 ** Control and query of the open file handle.
32654 */
32655 static int winFileControl(sqlite3_file *id, int op, void *pArg){
 
32656 switch( op ){
32657 case SQLITE_FCNTL_LOCKSTATE: {
32658 *(int*)pArg = ((winFile*)id)->locktype;
32659 return SQLITE_OK;
32660 }
32661 case SQLITE_LAST_ERRNO: {
32662 *(int*)pArg = (int)((winFile*)id)->lastErrno;
32663 return SQLITE_OK;
32664 }
32665 case SQLITE_FCNTL_CHUNK_SIZE: {
32666 ((winFile*)id)->szChunk = *(int *)pArg;
32667 return SQLITE_OK;
32668 }
32669 case SQLITE_FCNTL_SIZE_HINT: {
32670 sqlite3_int64 sz = *(sqlite3_int64*)pArg;
32671 SimulateIOErrorBenign(1);
32672 winTruncate(id, sz);
32673 SimulateIOErrorBenign(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32674 return SQLITE_OK;
32675 }
32676 case SQLITE_FCNTL_SYNC_OMITTED: {
32677 return SQLITE_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32678 }
32679 }
32680 return SQLITE_NOTFOUND;
32681 }
32682
@@ -33482,10 +34002,11 @@
33482 int isTemp = 0;
33483 #endif
33484 winFile *pFile = (winFile*)id;
33485 void *zConverted; /* Filename in OS encoding */
33486 const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
 
33487
33488 /* If argument zPath is a NULL pointer, this function is required to open
33489 ** a temporary file. Use this buffer to store the file name in.
33490 */
33491 char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */
@@ -33601,34 +34122,34 @@
33601 #if SQLITE_OS_WINCE
33602 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
33603 #endif
33604
33605 if( isNT() ){
33606 h = CreateFileW((WCHAR*)zConverted,
33607 dwDesiredAccess,
33608 dwShareMode,
33609 NULL,
33610 dwCreationDisposition,
33611 dwFlagsAndAttributes,
33612 NULL
33613 );
33614 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
33615 ** Since the ASCII version of these Windows API do not exist for WINCE,
33616 ** it's important to not reference them for WINCE builds.
33617 */
33618 #if SQLITE_OS_WINCE==0
33619 }else{
33620 h = CreateFileA((char*)zConverted,
33621 dwDesiredAccess,
33622 dwShareMode,
33623 NULL,
33624 dwCreationDisposition,
33625 dwFlagsAndAttributes,
33626 NULL
33627 );
33628 #endif
33629 }
 
 
33630
33631 OSTRACE(("OPEN %d %s 0x%lx %s\n",
33632 h, zName, dwDesiredAccess,
33633 h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
33634
@@ -33691,19 +34212,17 @@
33691 ** file open, we will be unable to delete it. To work around this
33692 ** problem, we delay 100 milliseconds and try to delete again. Up
33693 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
33694 ** up and returning an error.
33695 */
33696 #define MX_DELETION_ATTEMPTS 5
33697 static int winDelete(
33698 sqlite3_vfs *pVfs, /* Not used on win32 */
33699 const char *zFilename, /* Name of file to delete */
33700 int syncDir /* Not used on win32 */
33701 ){
33702 int cnt = 0;
33703 DWORD rc;
33704 DWORD error = 0;
33705 void *zConverted;
33706 UNUSED_PARAMETER(pVfs);
33707 UNUSED_PARAMETER(syncDir);
33708
33709 SimulateIOError(return SQLITE_IOERR_DELETE);
@@ -33710,38 +34229,34 @@
33710 zConverted = convertUtf8Filename(zFilename);
33711 if( zConverted==0 ){
33712 return SQLITE_NOMEM;
33713 }
33714 if( isNT() ){
33715 do{
33716 DeleteFileW(zConverted);
33717 }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
33718 || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33719 && (++cnt < MX_DELETION_ATTEMPTS)
33720 && (Sleep(100), 1) );
33721 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
33722 ** Since the ASCII version of these Windows API do not exist for WINCE,
33723 ** it's important to not reference them for WINCE builds.
33724 */
33725 #if SQLITE_OS_WINCE==0
33726 }else{
33727 do{
33728 DeleteFileA(zConverted);
33729 }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
33730 || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33731 && (++cnt < MX_DELETION_ATTEMPTS)
33732 && (Sleep(100), 1) );
33733 #endif
33734 }
 
 
 
 
 
33735 free(zConverted);
33736 OSTRACE(("DELETE \"%s\" %s\n", zFilename,
33737 ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
33738 "ok" : "failed" ));
33739
33740 return ( (rc == INVALID_FILE_ATTRIBUTES)
33741 && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
33742 winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
33743 }
33744
33745 /*
33746 ** Check the existance and status of a file.
33747 */
@@ -33760,15 +34275,17 @@
33760 zConverted = convertUtf8Filename(zFilename);
33761 if( zConverted==0 ){
33762 return SQLITE_NOMEM;
33763 }
33764 if( isNT() ){
 
33765 WIN32_FILE_ATTRIBUTE_DATA sAttrData;
33766 memset(&sAttrData, 0, sizeof(sAttrData));
33767 if( GetFileAttributesExW((WCHAR*)zConverted,
33768 GetFileExInfoStandard,
33769 &sAttrData) ){
 
33770 /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
33771 ** as if it does not exist.
33772 */
33773 if( flags==SQLITE_ACCESS_EXISTS
33774 && sAttrData.nFileSizeHigh==0
@@ -33776,10 +34293,11 @@
33776 attr = INVALID_FILE_ATTRIBUTES;
33777 }else{
33778 attr = sAttrData.dwFileAttributes;
33779 }
33780 }else{
 
33781 if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
33782 winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
33783 free(zConverted);
33784 return SQLITE_IOERR_ACCESS;
33785 }else{
@@ -33800,11 +34318,12 @@
33800 case SQLITE_ACCESS_READ:
33801 case SQLITE_ACCESS_EXISTS:
33802 rc = attr!=INVALID_FILE_ATTRIBUTES;
33803 break;
33804 case SQLITE_ACCESS_READWRITE:
33805 rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
 
33806 break;
33807 default:
33808 assert(!"Invalid flags argument");
33809 }
33810 *pResOut = rc;
@@ -35256,10 +35775,13 @@
35256 typedef struct PCache1 PCache1;
35257 typedef struct PgHdr1 PgHdr1;
35258 typedef struct PgFreeslot PgFreeslot;
35259 typedef struct PGroup PGroup;
35260
 
 
 
35261 /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
35262 ** of one or more PCaches that are able to recycle each others unpinned
35263 ** pages when they are under memory pressure. A PGroup is an instance of
35264 ** the following object.
35265 **
@@ -35285,12 +35807,70 @@
35285 int nMaxPage; /* Sum of nMax for purgeable caches */
35286 int nMinPage; /* Sum of nMin for purgeable caches */
35287 int mxPinned; /* nMaxpage + 10 - nMinPage */
35288 int nCurrentPage; /* Number of purgeable pages allocated */
35289 PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
 
 
 
 
35290 };
35291
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35292 /* Each page cache is an instance of the following object. Every
35293 ** open database file (including each in-memory database and each
35294 ** temporary or transient database) has a single page cache which
35295 ** is an instance of this object.
35296 **
@@ -35389,10 +35969,21 @@
35389 **
35390 ** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
35391 */
35392 #define PGHDR1_TO_PAGE(p) (void*)(((char*)p) - p->pCache->szPage)
35393 #define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)
 
 
 
 
 
 
 
 
 
 
 
35394
35395 /*
35396 ** Macros to enter and leave the PCache LRU mutex.
35397 */
35398 #define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
@@ -35515,25 +36106,159 @@
35515 return iSize;
35516 }
35517 }
35518 #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
35519
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35520 /*
35521 ** Allocate a new page object initially associated with cache pCache.
35522 */
35523 static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
35524 int nByte = sizeof(PgHdr1) + pCache->szPage;
35525 void *pPg = pcache1Alloc(nByte);
35526 PgHdr1 *p;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35527 if( pPg ){
35528 p = PAGE_TO_PGHDR1(pCache, pPg);
35529 if( pCache->bPurgeable ){
35530 pCache->pGroup->nCurrentPage++;
35531 }
35532 }else{
35533 p = 0;
35534 }
 
35535 return p;
35536 }
35537
35538 /*
35539 ** Free a page object allocated by pcache1AllocPage().
@@ -35543,14 +36268,56 @@
35543 ** with a NULL pointer, so we mark the NULL test with ALWAYS().
35544 */
35545 static void pcache1FreePage(PgHdr1 *p){
35546 if( ALWAYS(p) ){
35547 PCache1 *pCache = p->pCache;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35548 if( pCache->bPurgeable ){
35549 pCache->pGroup->nCurrentPage--;
35550 }
35551 pcache1Free(PGHDR1_TO_PAGE(p));
35552 }
35553 }
35554
35555 /*
35556 ** Malloc function used by SQLite to obtain space from the buffer configured
@@ -35984,13 +36751,11 @@
35984 /* Step 5. If a usable page buffer has still not been found,
35985 ** attempt to allocate a new one.
35986 */
35987 if( !pPage ){
35988 if( createFlag==1 ) sqlite3BeginBenignMalloc();
35989 pcache1LeaveMutex(pGroup);
35990 pPage = pcache1AllocPage(pCache);
35991 pcache1EnterMutex(pGroup);
35992 if( createFlag==1 ) sqlite3EndBenignMalloc();
35993 }
35994
35995 if( pPage ){
35996 unsigned int h = iKey % pCache->nHash;
@@ -36156,10 +36921,13 @@
36156 ** been released, the function returns. The return value is the total number
36157 ** of bytes of memory released.
36158 */
36159 SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
36160 int nFree = 0;
 
 
 
36161 assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
36162 assert( sqlite3_mutex_notheld(pcache1.mutex) );
36163 if( pcache1.pStart==0 ){
36164 PgHdr1 *p;
36165 pcache1EnterMutex(&pcache1.grp);
@@ -37368,10 +38136,12 @@
37368 u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
37369 u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
37370 u8 tempFile; /* zFilename is a temporary file */
37371 u8 readOnly; /* True for a read-only database */
37372 u8 memDb; /* True to inhibit all file I/O */
 
 
37373
37374 /**************************************************************************
37375 ** The following block contains those class members that change during
37376 ** routine opertion. Class members not in this block are either fixed
37377 ** when the pager is first created or else only change when there is a
@@ -37590,10 +38360,19 @@
37590 || p->journalMode==PAGER_JOURNALMODE_MEMORY
37591 );
37592 assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
37593 assert( pagerUseWal(p)==0 );
37594 }
 
 
 
 
 
 
 
 
 
37595
37596 /* If changeCountDone is set, a RESERVED lock or greater must be held
37597 ** on the file.
37598 */
37599 assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
@@ -40487,10 +41266,11 @@
40487 ** to the caller.
40488 */
40489 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
40490 u8 *pTmp = (u8 *)pPager->pTmpSpace;
40491
 
40492 disable_simulated_io_errors();
40493 sqlite3BeginBenignMalloc();
40494 /* pPager->errCode = 0; */
40495 pPager->exclusiveMode = 0;
40496 #ifndef SQLITE_OMIT_WAL
@@ -40921,10 +41701,11 @@
40921 ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1
40922 ** while in the error state, hence it is impossible for this routine to
40923 ** be called in the error state. Nevertheless, we include a NEVER()
40924 ** test for the error state as a safeguard against future changes.
40925 */
 
40926 if( NEVER(pPager->errCode) ) return SQLITE_OK;
40927 if( pPager->doNotSpill ) return SQLITE_OK;
40928 if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
40929 return SQLITE_OK;
40930 }
@@ -41292,10 +42073,16 @@
41292 }
41293 /* pPager->xBusyHandler = 0; */
41294 /* pPager->pBusyHandlerArg = 0; */
41295 pPager->xReiniter = xReinit;
41296 /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
 
 
 
 
 
 
41297
41298 *ppPager = pPager;
41299 return SQLITE_OK;
41300 }
41301
@@ -42835,10 +43622,21 @@
42835 ** Return true if this is an in-memory pager.
42836 */
42837 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
42838 return MEMDB;
42839 }
 
 
 
 
 
 
 
 
 
 
 
42840
42841 /*
42842 ** Check that there are at least nSavepoint savepoints open. If there are
42843 ** currently less than nSavepoints open, then open one or more savepoints
42844 ** to make up the difference. If the number of savepoints is already
@@ -45384,17 +46182,19 @@
45384 **
45385 ** The EXCLUSIVE lock is not released before returning.
45386 */
45387 rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
45388 if( rc==SQLITE_OK ){
 
45389 if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
45390 pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
45391 }
45392 rc = sqlite3WalCheckpoint(
45393 pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
45394 );
45395 if( rc==SQLITE_OK ){
 
45396 isDelete = 1;
45397 }
45398 }
45399
45400 walIndexClose(pWal, isDelete);
@@ -49202,15 +50002,26 @@
49202 assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
49203
49204 /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
49205 assert( (flags & BTREE_SINGLE)==0 || isTempDb );
49206
 
 
 
 
 
 
 
 
 
 
49207 if( db->flags & SQLITE_NoReadlock ){
49208 flags |= BTREE_NO_READLOCK;
49209 }
49210 if( isMemdb ){
49211 flags |= BTREE_MEMORY;
 
49212 }
49213 if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
49214 vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
49215 }
49216 p = sqlite3MallocZero(sizeof(Btree));
@@ -50936,11 +51747,12 @@
50936
50937 if( NEVER(wrFlag && pBt->readOnly) ){
50938 return SQLITE_READONLY;
50939 }
50940 if( iTable==1 && btreePagecount(pBt)==0 ){
50941 return SQLITE_EMPTY;
 
50942 }
50943
50944 /* Now that no other errors can occur, finish filling in the BtCursor
50945 ** variables and link the cursor into the BtShared list. */
50946 pCur->pgnoRoot = (Pgno)iTable;
@@ -51690,10 +52502,13 @@
51690 int i;
51691 for(i=1; i<=pCur->iPage; i++){
51692 releasePage(pCur->apPage[i]);
51693 }
51694 pCur->iPage = 0;
 
 
 
51695 }else{
51696 rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
51697 if( rc!=SQLITE_OK ){
51698 pCur->eState = CURSOR_INVALID;
51699 return rc;
@@ -51799,11 +52614,11 @@
51799 assert( cursorHoldsMutex(pCur) );
51800 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
51801 rc = moveToRoot(pCur);
51802 if( rc==SQLITE_OK ){
51803 if( pCur->eState==CURSOR_INVALID ){
51804 assert( pCur->apPage[pCur->iPage]->nCell==0 );
51805 *pRes = 1;
51806 }else{
51807 assert( pCur->apPage[pCur->iPage]->nCell>0 );
51808 *pRes = 0;
51809 rc = moveToLeftmost(pCur);
@@ -51838,11 +52653,11 @@
51838 }
51839
51840 rc = moveToRoot(pCur);
51841 if( rc==SQLITE_OK ){
51842 if( CURSOR_INVALID==pCur->eState ){
51843 assert( pCur->apPage[pCur->iPage]->nCell==0 );
51844 *pRes = 1;
51845 }else{
51846 assert( pCur->eState==CURSOR_VALID );
51847 *pRes = 0;
51848 rc = moveToRightmost(pCur);
@@ -51911,16 +52726,16 @@
51911
51912 rc = moveToRoot(pCur);
51913 if( rc ){
51914 return rc;
51915 }
51916 assert( pCur->apPage[pCur->iPage] );
51917 assert( pCur->apPage[pCur->iPage]->isInit );
51918 assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
51919 if( pCur->eState==CURSOR_INVALID ){
51920 *pRes = -1;
51921 assert( pCur->apPage[pCur->iPage]->nCell==0 );
51922 return SQLITE_OK;
51923 }
51924 assert( pCur->apPage[0]->intKey || pIdxKey );
51925 for(;;){
51926 int lwr, upr, idx;
@@ -54745,13 +55560,20 @@
54745 releasePage(pPage);
54746 }
54747 return rc;
54748 }
54749 SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
 
54750 int rc;
54751 sqlite3BtreeEnter(p);
54752 rc = btreeDropTable(p, iTable, piMoved);
 
 
 
 
 
 
54753 sqlite3BtreeLeave(p);
54754 return rc;
54755 }
54756
54757
@@ -54826,10 +55648,15 @@
54826 ** corruption) an SQLite error code is returned.
54827 */
54828 SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
54829 i64 nEntry = 0; /* Value to return in *pnEntry */
54830 int rc; /* Return code */
 
 
 
 
 
54831 rc = moveToRoot(pCur);
54832
54833 /* Unless an error occurs, the following loop runs one iteration for each
54834 ** page in the B-Tree structure (not including overflow pages).
54835 */
@@ -55610,11 +56437,10 @@
55610 */
55611 SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
55612 BtShared *pBt = pBtree->pBt;
55613 int rc; /* Return code */
55614
55615 assert( pBtree->inTrans==TRANS_NONE );
55616 assert( iVersion==1 || iVersion==2 );
55617
55618 /* If setting the version fields to 1, do not automatically open the
55619 ** WAL connection, even if the version fields are currently set to 2.
55620 */
@@ -56049,106 +56875,110 @@
56049 /* Update the schema version field in the destination database. This
56050 ** is to make sure that the schema-version really does change in
56051 ** the case where the source and destination databases have the
56052 ** same schema version.
56053 */
56054 if( rc==SQLITE_DONE
56055 && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
56056 ){
56057 int nDestTruncate;
56058
56059 if( p->pDestDb ){
56060 sqlite3ResetInternalSchema(p->pDestDb, -1);
56061 }
56062
56063 /* Set nDestTruncate to the final number of pages in the destination
56064 ** database. The complication here is that the destination page
56065 ** size may be different to the source page size.
56066 **
56067 ** If the source page size is smaller than the destination page size,
56068 ** round up. In this case the call to sqlite3OsTruncate() below will
56069 ** fix the size of the file. However it is important to call
56070 ** sqlite3PagerTruncateImage() here so that any pages in the
56071 ** destination file that lie beyond the nDestTruncate page mark are
56072 ** journalled by PagerCommitPhaseOne() before they are destroyed
56073 ** by the file truncation.
56074 */
56075 assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
56076 assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
56077 if( pgszSrc<pgszDest ){
56078 int ratio = pgszDest/pgszSrc;
56079 nDestTruncate = (nSrcPage+ratio-1)/ratio;
56080 if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
56081 nDestTruncate--;
56082 }
56083 }else{
56084 nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
56085 }
56086 sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
56087
56088 if( pgszSrc<pgszDest ){
56089 /* If the source page-size is smaller than the destination page-size,
56090 ** two extra things may need to happen:
56091 **
56092 ** * The destination may need to be truncated, and
56093 **
56094 ** * Data stored on the pages immediately following the
56095 ** pending-byte page in the source database may need to be
56096 ** copied into the destination database.
56097 */
56098 const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
56099 sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
56100 i64 iOff;
56101 i64 iEnd;
56102
56103 assert( pFile );
56104 assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
56105 nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
56106 && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
56107 ));
56108
56109 /* This call ensures that all data required to recreate the original
56110 ** database has been stored in the journal for pDestPager and the
56111 ** journal synced to disk. So at this point we may safely modify
56112 ** the database file in any way, knowing that if a power failure
56113 ** occurs, the original database will be reconstructed from the
56114 ** journal file. */
56115 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
56116
56117 /* Write the extra pages and truncate the database file as required. */
56118 iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
56119 for(
56120 iOff=PENDING_BYTE+pgszSrc;
56121 rc==SQLITE_OK && iOff<iEnd;
56122 iOff+=pgszSrc
56123 ){
56124 PgHdr *pSrcPg = 0;
56125 const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
56126 rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
56127 if( rc==SQLITE_OK ){
56128 u8 *zData = sqlite3PagerGetData(pSrcPg);
56129 rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
56130 }
56131 sqlite3PagerUnref(pSrcPg);
56132 }
56133 if( rc==SQLITE_OK ){
56134 rc = backupTruncateFile(pFile, iSize);
56135 }
56136
56137 /* Sync the database file to disk. */
56138 if( rc==SQLITE_OK ){
56139 rc = sqlite3PagerSync(pDestPager);
56140 }
56141 }else{
56142 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
56143 }
56144
56145 /* Finish committing the transaction to the destination database. */
56146 if( SQLITE_OK==rc
56147 && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
56148 ){
56149 rc = SQLITE_DONE;
 
 
 
 
56150 }
56151 }
56152
56153 /* If bCloseTrans is true, then this function opened a read transaction
56154 ** on the source database. Close the read transaction here. There is
@@ -56612,38 +57442,32 @@
56612 ** invoking an external callback, free it now. Calling this function
56613 ** does not free any Mem.zMalloc buffer.
56614 */
56615 SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
56616 assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
56617 testcase( p->flags & MEM_Agg );
56618 testcase( p->flags & MEM_Dyn );
56619 testcase( p->flags & MEM_RowSet );
56620 testcase( p->flags & MEM_Frame );
56621 if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){
56622 if( p->flags&MEM_Agg ){
56623 sqlite3VdbeMemFinalize(p, p->u.pDef);
56624 assert( (p->flags & MEM_Agg)==0 );
56625 sqlite3VdbeMemRelease(p);
56626 }else if( p->flags&MEM_Dyn && p->xDel ){
56627 assert( (p->flags&MEM_RowSet)==0 );
56628 p->xDel((void *)p->z);
56629 p->xDel = 0;
56630 }else if( p->flags&MEM_RowSet ){
56631 sqlite3RowSetClear(p->u.pRowSet);
56632 }else if( p->flags&MEM_Frame ){
56633 sqlite3VdbeMemSetNull(p);
56634 }
56635 }
56636 }
56637
56638 /*
56639 ** Release any memory held by the Mem. This may leave the Mem in an
56640 ** inconsistent state, for example with (Mem.z==0) and
56641 ** (Mem.type==SQLITE_TEXT).
56642 */
56643 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
56644 sqlite3VdbeMemReleaseExternal(p);
56645 sqlite3DbFree(p->db, p->zMalloc);
56646 p->z = 0;
56647 p->zMalloc = 0;
56648 p->xDel = 0;
56649 }
@@ -56961,11 +57785,11 @@
56961 ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
56962 ** and flags gets srcType (either MEM_Ephem or MEM_Static).
56963 */
56964 SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
56965 assert( (pFrom->flags & MEM_RowSet)==0 );
56966 sqlite3VdbeMemReleaseExternal(pTo);
56967 memcpy(pTo, pFrom, MEMCELLSIZE);
56968 pTo->xDel = 0;
56969 if( (pFrom->flags&MEM_Static)==0 ){
56970 pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
56971 assert( srcType==MEM_Ephem || srcType==MEM_Static );
@@ -56979,11 +57803,11 @@
56979 */
56980 SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
56981 int rc = SQLITE_OK;
56982
56983 assert( (pFrom->flags & MEM_RowSet)==0 );
56984 sqlite3VdbeMemReleaseExternal(pTo);
56985 memcpy(pTo, pFrom, MEMCELLSIZE);
56986 pTo->flags &= ~MEM_Dyn;
56987
56988 if( pTo->flags&(MEM_Str|MEM_Blob) ){
56989 if( 0==(pFrom->flags&MEM_Static) ){
@@ -57934,10 +58758,16 @@
57934 assert( p->nOp - i >= 3 );
57935 assert( pOp[-1].opcode==OP_Integer );
57936 n = pOp[-1].p1;
57937 if( n>nMaxArgs ) nMaxArgs = n;
57938 #endif
 
 
 
 
 
 
57939 }
57940
57941 if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
57942 assert( -1-pOp->p2<p->nLabel );
57943 pOp->p2 = aLabel[-1-pOp->p2];
@@ -58025,37 +58855,34 @@
58025 ** Change the value of the P1 operand for a specific instruction.
58026 ** This routine is useful when a large program is loaded from a
58027 ** static array using sqlite3VdbeAddOpList but we want to make a
58028 ** few minor changes to the program.
58029 */
58030 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
58031 assert( p!=0 );
58032 assert( addr>=0 );
58033 if( p->nOp>addr ){
58034 p->aOp[addr].p1 = val;
58035 }
58036 }
58037
58038 /*
58039 ** Change the value of the P2 operand for a specific instruction.
58040 ** This routine is useful for setting a jump destination.
58041 */
58042 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
58043 assert( p!=0 );
58044 assert( addr>=0 );
58045 if( p->nOp>addr ){
58046 p->aOp[addr].p2 = val;
58047 }
58048 }
58049
58050 /*
58051 ** Change the value of the P3 operand for a specific instruction.
58052 */
58053 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
58054 assert( p!=0 );
58055 assert( addr>=0 );
58056 if( p->nOp>addr ){
58057 p->aOp[addr].p3 = val;
58058 }
58059 }
58060
58061 /*
@@ -58442,10 +59269,14 @@
58442 break;
58443 }
58444 case P4_SUBPROGRAM: {
58445 sqlite3_snprintf(nTemp, zTemp, "program");
58446 break;
 
 
 
 
58447 }
58448 default: {
58449 zP4 = pOp->p4.z;
58450 if( zP4==0 ){
58451 zP4 = zTemp;
@@ -59006,10 +59837,11 @@
59006 nMem = 10;
59007 }
59008 memset(zCsr, 0, zEnd-zCsr);
59009 zCsr += (zCsr - (u8*)0)&7;
59010 assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
 
59011
59012 /* Memory for registers, parameters, cursor, etc, is allocated in two
59013 ** passes. On the first pass, we try to reuse unused space at the
59014 ** end of the opcode array. If we are unable to satisfy all memory
59015 ** requirements by reusing the opcode array tail, then the second
@@ -59065,10 +59897,11 @@
59065 */
59066 SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
59067 if( pCx==0 ){
59068 return;
59069 }
 
59070 if( pCx->pBt ){
59071 sqlite3BtreeClose(pCx->pBt);
59072 /* The pCx->pCursor will be close automatically, if it exists, by
59073 ** the call above. */
59074 }else if( pCx->pCursor ){
@@ -61205,10 +62038,18 @@
61205 rc = db->errCode = p->rc;
61206 }
61207 return (rc&db->errMask);
61208 }
61209
 
 
 
 
 
 
 
 
61210 /*
61211 ** This is the top-level implementation of sqlite3_step(). Call
61212 ** sqlite3Step() to do most of the work. If a schema error occurs,
61213 ** call sqlite3Reprepare() and try again.
61214 */
@@ -61223,14 +62064,14 @@
61223 return SQLITE_MISUSE_BKPT;
61224 }
61225 db = v->db;
61226 sqlite3_mutex_enter(db->mutex);
61227 while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
61228 && cnt++ < 5
61229 && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
61230 sqlite3_reset(pStmt);
61231 v->expired = 0;
61232 }
61233 if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
61234 /* This case occurs after failing to recompile an sql statement.
61235 ** The error message from the SQL compiler has already been loaded
61236 ** into the database handle. This block copies the error message
@@ -62357,10 +63198,17 @@
62357 ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
62358 ** P if required.
62359 */
62360 #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
62361
 
 
 
 
 
 
 
62362 /*
62363 ** Argument pMem points at a register that will be passed to a
62364 ** user-defined function or returned to the user as the result of a query.
62365 ** This routine sets the pMem->type variable used by the sqlite3_value_*()
62366 ** routines.
@@ -62951,10 +63799,11 @@
62951 u8 *zEndHdr; /* Pointer to first byte after the header */
62952 u32 offset; /* Offset into the data */
62953 u32 szField; /* Number of bytes in the content of a field */
62954 int szHdr; /* Size of the header size field at start of record */
62955 int avail; /* Number of bytes of available data */
 
62956 Mem *pReg; /* PseudoTable input register */
62957 } am;
62958 struct OP_Affinity_stack_vars {
62959 const char *zAffinity; /* The affinity to be applied */
62960 char cAff; /* A single character of affinity */
@@ -63109,11 +63958,10 @@
63109 BtCursor *pCrsr;
63110 int res;
63111 } bl;
63112 struct OP_Next_stack_vars {
63113 VdbeCursor *pC;
63114 BtCursor *pCrsr;
63115 int res;
63116 } bm;
63117 struct OP_IdxInsert_stack_vars {
63118 VdbeCursor *pC;
63119 BtCursor *pCrsr;
@@ -63363,11 +64211,11 @@
63363 if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
63364 assert( pOp->p2>0 );
63365 assert( pOp->p2<=p->nMem );
63366 pOut = &aMem[pOp->p2];
63367 memAboutToChange(p, pOut);
63368 sqlite3VdbeMemReleaseExternal(pOut);
63369 pOut->flags = MEM_Int;
63370 }
63371
63372 /* Sanity checking on other operands */
63373 #ifdef SQLITE_DEBUG
@@ -63496,11 +64344,11 @@
63496 break;
63497 }
63498
63499 /* Opcode: HaltIfNull P1 P2 P3 P4 *
63500 **
63501 ** Check the value in register P3. If is is NULL then Halt using
63502 ** parameter P1, P2, and P4 as if this were a Halt instruction. If the
63503 ** value in register P3 is not NULL, then this routine is a no-op.
63504 */
63505 case OP_HaltIfNull: { /* in3 */
63506 pIn3 = &aMem[pOp->p3];
@@ -63730,10 +64578,15 @@
63730 assert( memIsValid(pIn1) );
63731 memAboutToChange(p, pOut);
63732 u.ac.zMalloc = pOut->zMalloc;
63733 pOut->zMalloc = 0;
63734 sqlite3VdbeMemMove(pOut, pIn1);
 
 
 
 
 
63735 pIn1->zMalloc = u.ac.zMalloc;
63736 REGISTER_TRACE(u.ac.p2++, pOut);
63737 pIn1++;
63738 pOut++;
63739 }
@@ -64433,11 +65286,11 @@
64433 ** additional information.
64434 **
64435 ** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
64436 ** true or false and is never NULL. If both operands are NULL then the result
64437 ** of comparison is false. If either operand is NULL then the result is true.
64438 ** If neither operand is NULL the the result is the same as it would be if
64439 ** the SQLITE_NULLEQ flag were omitted from P5.
64440 */
64441 /* Opcode: Eq P1 P2 P3 P4 P5
64442 **
64443 ** This works just like the Lt opcode except that the jump is taken if
@@ -64445,11 +65298,11 @@
64445 ** See the Lt opcode for additional information.
64446 **
64447 ** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
64448 ** true or false and is never NULL. If both operands are NULL then the result
64449 ** of comparison is true. If either operand is NULL then the result is false.
64450 ** If neither operand is NULL the the result is the same as it would be if
64451 ** the SQLITE_NULLEQ flag were omitted from P5.
64452 */
64453 /* Opcode: Le P1 P2 P3 P4 P5
64454 **
64455 ** This works just like the Lt opcode except that the jump is taken if
@@ -64730,17 +65583,17 @@
64730 break;
64731 }
64732
64733 /* Opcode: If P1 P2 P3 * *
64734 **
64735 ** Jump to P2 if the value in register P1 is true. The value is
64736 ** is considered true if it is numeric and non-zero. If the value
64737 ** in P1 is NULL then take the jump if P3 is true.
64738 */
64739 /* Opcode: IfNot P1 P2 P3 * *
64740 **
64741 ** Jump to P2 if the value in register P1 is False. The value is
64742 ** is considered true if it has a numeric value of zero. If the value
64743 ** in P1 is NULL then take the jump if P3 is true.
64744 */
64745 case OP_If: /* jump, in1 */
64746 case OP_IfNot: { /* jump, in1 */
@@ -64828,10 +65681,11 @@
64828 u8 *zEndHdr; /* Pointer to first byte after the header */
64829 u32 offset; /* Offset into the data */
64830 u32 szField; /* Number of bytes in the content of a field */
64831 int szHdr; /* Size of the header size field at start of record */
64832 int avail; /* Number of bytes of available data */
 
64833 Mem *pReg; /* PseudoTable input register */
64834 #endif /* local variables moved into u.am */
64835
64836
64837 u.am.p1 = pOp->p1;
@@ -64840,11 +65694,10 @@
64840 memset(&u.am.sMem, 0, sizeof(u.am.sMem));
64841 assert( u.am.p1<p->nCursor );
64842 assert( pOp->p3>0 && pOp->p3<=p->nMem );
64843 u.am.pDest = &aMem[pOp->p3];
64844 memAboutToChange(p, u.am.pDest);
64845 MemSetTypeFlag(u.am.pDest, MEM_Null);
64846 u.am.zRec = 0;
64847
64848 /* This block sets the variable u.am.payloadSize to be the total number of
64849 ** bytes in the record.
64850 **
@@ -64884,11 +65737,11 @@
64884 }else{
64885 assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) );
64886 rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize);
64887 assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
64888 }
64889 }else if( u.am.pC->pseudoTableReg>0 ){
64890 u.am.pReg = &aMem[u.am.pC->pseudoTableReg];
64891 assert( u.am.pReg->flags & MEM_Blob );
64892 assert( memIsValid(u.am.pReg) );
64893 u.am.payloadSize = u.am.pReg->n;
64894 u.am.zRec = u.am.pReg->z;
@@ -64897,13 +65750,14 @@
64897 }else{
64898 /* Consider the row to be NULL */
64899 u.am.payloadSize = 0;
64900 }
64901
64902 /* If u.am.payloadSize is 0, then just store a NULL */
 
64903 if( u.am.payloadSize==0 ){
64904 assert( u.am.pDest->flags&MEM_Null );
64905 goto op_column_out;
64906 }
64907 assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
64908 if( u.am.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
64909 goto too_big;
@@ -65006,12 +65860,18 @@
65006 ** of the record to the start of the data for the u.am.i-th column
65007 */
65008 for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
65009 if( u.am.zIdx<u.am.zEndHdr ){
65010 u.am.aOffset[u.am.i] = u.am.offset;
65011 u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]);
65012 u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]);
 
 
 
 
 
 
65013 u.am.offset += u.am.szField;
65014 if( u.am.offset<u.am.szField ){ /* True if u.am.offset overflows */
65015 u.am.zIdx = &u.am.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
65016 break;
65017 }
@@ -65048,11 +65908,11 @@
65048 ** a pointer to a Mem object.
65049 */
65050 if( u.am.aOffset[u.am.p2] ){
65051 assert( rc==SQLITE_OK );
65052 if( u.am.zRec ){
65053 sqlite3VdbeMemReleaseExternal(u.am.pDest);
65054 sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest);
65055 }else{
65056 u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]);
65057 sqlite3VdbeMemMove(&u.am.sMem, u.am.pDest);
65058 rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, u.am.aOffset[u.am.p2], u.am.len, u.am.pC->isIndex, &u.am.sMem);
@@ -65065,11 +65925,11 @@
65065 u.am.pDest->enc = encoding;
65066 }else{
65067 if( pOp->p4type==P4_MEM ){
65068 sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static);
65069 }else{
65070 assert( u.am.pDest->flags&MEM_Null );
65071 }
65072 }
65073
65074 /* If we dynamically allocated space to hold the data (in the
65075 ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
@@ -65267,11 +66127,11 @@
65267 i64 nEntry;
65268 BtCursor *pCrsr;
65269 #endif /* local variables moved into u.ap */
65270
65271 u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor;
65272 if( u.ap.pCrsr ){
65273 rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry);
65274 }else{
65275 u.ap.nEntry = 0;
65276 }
65277 pOut->u.i = u.ap.nEntry;
@@ -65843,19 +66703,13 @@
65843 u.aw.pCur->nullRow = 1;
65844 u.aw.pCur->isOrdered = 1;
65845 rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor);
65846 u.aw.pCur->pKeyInfo = u.aw.pKeyInfo;
65847
65848 /* Since it performs no memory allocation or IO, the only values that
65849 ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK.
65850 ** SQLITE_EMPTY is only returned when attempting to open the table
65851 ** rooted at page 1 of a zero-byte database. */
65852 assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
65853 if( rc==SQLITE_EMPTY ){
65854 u.aw.pCur->pCursor = 0;
65855 rc = SQLITE_OK;
65856 }
65857
65858 /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
65859 ** SQLite used to check if the root-page flags were sane at this point
65860 ** and report database corruption if they were not, but this check has
65861 ** since moved into the btree layer. */
@@ -65862,11 +66716,11 @@
65862 u.aw.pCur->isTable = pOp->p4type!=P4_KEYINFO;
65863 u.aw.pCur->isIndex = !u.aw.pCur->isTable;
65864 break;
65865 }
65866
65867 /* Opcode: OpenEphemeral P1 P2 * P4 *
65868 **
65869 ** Open a new cursor P1 to a transient table.
65870 ** The cursor is always opened read/write even if
65871 ** the main database is read-only. The ephemeral
65872 ** table is deleted automatically when the cursor is closed.
@@ -65879,18 +66733,30 @@
65879 ** This opcode was once called OpenTemp. But that created
65880 ** confusion because the term "temp table", might refer either
65881 ** to a TEMP table at the SQL level, or to a table opened by
65882 ** this opcode. Then this opcode was call OpenVirtual. But
65883 ** that created confusion with the whole virtual-table idea.
 
 
 
 
 
65884 */
65885 /* Opcode: OpenAutoindex P1 P2 * P4 *
65886 **
65887 ** This opcode works the same as OP_OpenEphemeral. It has a
65888 ** different name to distinguish its use. Tables created using
65889 ** by this opcode will be used for automatically created transient
65890 ** indices in joins.
65891 */
 
 
 
 
 
 
 
65892 case OP_OpenAutoindex:
65893 case OP_OpenEphemeral: {
65894 #if 0 /* local variables moved into u.ax */
65895 VdbeCursor *pCx;
65896 #endif /* local variables moved into u.ax */
@@ -65900,10 +66766,11 @@
65900 SQLITE_OPEN_EXCLUSIVE |
65901 SQLITE_OPEN_DELETEONCLOSE |
65902 SQLITE_OPEN_TRANSIENT_DB;
65903
65904 assert( pOp->p1>=0 );
 
65905 u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
65906 if( u.ax.pCx==0 ) goto no_mem;
65907 u.ax.pCx->nullRow = 1;
65908 rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
65909 BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
@@ -65917,11 +66784,11 @@
65917 ** automatically created table with root-page 1 (an BLOB_INTKEY table).
65918 */
65919 if( pOp->p4.pKeyInfo ){
65920 int pgno;
65921 assert( pOp->p4type==P4_KEYINFO );
65922 rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY);
65923 if( rc==SQLITE_OK ){
65924 assert( pgno==MASTER_ROOT+1 );
65925 rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
65926 (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
65927 u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
@@ -65933,10 +66800,15 @@
65933 u.ax.pCx->isTable = 1;
65934 }
65935 }
65936 u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
65937 u.ax.pCx->isIndex = !u.ax.pCx->isTable;
 
 
 
 
 
65938 break;
65939 }
65940
65941 /* Opcode: OpenPseudo P1 P2 P3 * *
65942 **
@@ -66052,11 +66924,11 @@
66052 assert( u.az.pC->pseudoTableReg==0 );
66053 assert( OP_SeekLe == OP_SeekLt+1 );
66054 assert( OP_SeekGe == OP_SeekLt+2 );
66055 assert( OP_SeekGt == OP_SeekLt+3 );
66056 assert( u.az.pC->isOrdered );
66057 if( u.az.pC->pCursor!=0 ){
66058 u.az.oc = pOp->opcode;
66059 u.az.pC->nullRow = 0;
66060 if( u.az.pC->isTable ){
66061 /* The input value in P3 might be of any type: integer, real, string,
66062 ** blob, or NULL. But it needs to be an integer before we can do
@@ -66390,11 +67262,11 @@
66390 break;
66391 }
66392
66393 /* Opcode: NotExists P1 P2 P3 * *
66394 **
66395 ** Use the content of register P3 as a integer key. If a record
66396 ** with that key does not exist in table of P1, then jump to P2.
66397 ** If the record does exist, then fall through. The cursor is left
66398 ** pointing to the record if it exists.
66399 **
66400 ** The difference between this operation and NotFound is that this
@@ -66418,11 +67290,11 @@
66418 u.bd.pC = p->apCsr[pOp->p1];
66419 assert( u.bd.pC!=0 );
66420 assert( u.bd.pC->isTable );
66421 assert( u.bd.pC->pseudoTableReg==0 );
66422 u.bd.pCrsr = u.bd.pC->pCursor;
66423 if( u.bd.pCrsr!=0 ){
66424 u.bd.res = 0;
66425 u.bd.iKey = pIn3->u.i;
66426 rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res);
66427 u.bd.pC->lastRowid = pIn3->u.i;
66428 u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0;
@@ -66468,11 +67340,11 @@
66468 ** written to register P2.
66469 **
66470 ** If P3>0 then P3 is a register in the root frame of this VDBE that holds
66471 ** the largest previously generated record number. No new record numbers are
66472 ** allowed to be less than this value. When this value reaches its maximum,
66473 ** a SQLITE_FULL error is generated. The P3 register is updated with the '
66474 ** generated record number. This P3 mechanism is used to help implement the
66475 ** AUTOINCREMENT feature.
66476 */
66477 case OP_NewRowid: { /* out2-prerelease */
66478 #if 0 /* local variables moved into u.be */
@@ -66842,10 +67714,17 @@
66842 assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey );
66843 assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData );
66844 assert( u.bh.pC!=0 );
66845 assert( u.bh.pC->nullRow==0 );
66846 assert( u.bh.pC->pseudoTableReg==0 );
 
 
 
 
 
 
 
66847 assert( u.bh.pC->pCursor!=0 );
66848 u.bh.pCrsr = u.bh.pC->pCursor;
66849 assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) );
66850
66851 /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
@@ -66950,10 +67829,11 @@
66950 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
66951 u.bj.pC = p->apCsr[pOp->p1];
66952 assert( u.bj.pC!=0 );
66953 u.bj.pC->nullRow = 1;
66954 u.bj.pC->rowidIsValid = 0;
 
66955 if( u.bj.pC->pCursor ){
66956 sqlite3BtreeClearCursor(u.bj.pC->pCursor);
66957 }
66958 break;
66959 }
@@ -66975,11 +67855,11 @@
66975
66976 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
66977 u.bk.pC = p->apCsr[pOp->p1];
66978 assert( u.bk.pC!=0 );
66979 u.bk.pCrsr = u.bk.pC->pCursor;
66980 if( u.bk.pCrsr==0 ){
66981 u.bk.res = 1;
66982 }else{
66983 rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res);
66984 }
66985 u.bk.pC->nullRow = (u8)u.bk.res;
@@ -67030,11 +67910,15 @@
67030
67031 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67032 u.bl.pC = p->apCsr[pOp->p1];
67033 assert( u.bl.pC!=0 );
67034 u.bl.res = 1;
67035 if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){
 
 
 
 
67036 rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
67037 u.bl.pC->atFirst = u.bl.res==0 ?1:0;
67038 u.bl.pC->deferredMoveto = 0;
67039 u.bl.pC->cacheStatus = CACHE_STALE;
67040 u.bl.pC->rowidIsValid = 0;
@@ -67045,18 +67929,21 @@
67045 pc = pOp->p2 - 1;
67046 }
67047 break;
67048 }
67049
67050 /* Opcode: Next P1 P2 * * P5
67051 **
67052 ** Advance cursor P1 so that it points to the next key/data pair in its
67053 ** table or index. If there are no more key/value pairs then fall through
67054 ** to the following instruction. But if the cursor advance was successful,
67055 ** jump immediately to P2.
67056 **
67057 ** The P1 cursor must be for a real table, not a pseudo-table.
 
 
 
67058 **
67059 ** If P5 is positive and the jump is taken, then event counter
67060 ** number P5-1 in the prepared statement is incremented.
67061 **
67062 ** See also: Prev
@@ -67067,19 +67954,21 @@
67067 ** table or index. If there is no previous key/value pairs then fall through
67068 ** to the following instruction. But if the cursor backup was successful,
67069 ** jump immediately to P2.
67070 **
67071 ** The P1 cursor must be for a real table, not a pseudo-table.
 
 
 
67072 **
67073 ** If P5 is positive and the jump is taken, then event counter
67074 ** number P5-1 in the prepared statement is incremented.
67075 */
67076 case OP_Prev: /* jump */
67077 case OP_Next: { /* jump */
67078 #if 0 /* local variables moved into u.bm */
67079 VdbeCursor *pC;
67080 BtCursor *pCrsr;
67081 int res;
67082 #endif /* local variables moved into u.bm */
67083
67084 CHECK_FOR_INTERRUPT;
67085 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -67086,19 +67975,21 @@
67086 assert( pOp->p5<=ArraySize(p->aCounter) );
67087 u.bm.pC = p->apCsr[pOp->p1];
67088 if( u.bm.pC==0 ){
67089 break; /* See ticket #2273 */
67090 }
67091 u.bm.pCrsr = u.bm.pC->pCursor;
67092 if( u.bm.pCrsr==0 ){
67093 u.bm.pC->nullRow = 1;
67094 break;
67095 }
67096 u.bm.res = 1;
67097 assert( u.bm.pC->deferredMoveto==0 );
67098 rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(u.bm.pCrsr, &u.bm.res) :
67099 sqlite3BtreePrevious(u.bm.pCrsr, &u.bm.res);
 
 
67100 u.bm.pC->nullRow = (u8)u.bm.res;
67101 u.bm.pC->cacheStatus = CACHE_STALE;
67102 if( u.bm.res==0 ){
67103 pc = pOp->p2 - 1;
67104 if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
@@ -67110,11 +68001,11 @@
67110 break;
67111 }
67112
67113 /* Opcode: IdxInsert P1 P2 P3 * P5
67114 **
67115 ** Register P2 holds a SQL index key made using the
67116 ** MakeRecord instructions. This opcode writes that key
67117 ** into the index P1. Data for the entry is nil.
67118 **
67119 ** P3 is a flag that provides a hint to the b-tree layer that this
67120 ** insert is likely to be an append.
@@ -67140,14 +68031,17 @@
67140 assert( u.bn.pC->isTable==0 );
67141 rc = ExpandBlob(pIn2);
67142 if( rc==SQLITE_OK ){
67143 u.bn.nKey = pIn2->n;
67144 u.bn.zKey = pIn2->z;
67145 rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
67146 ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
67147 );
67148 assert( u.bn.pC->deferredMoveto==0 );
 
 
 
67149 u.bn.pC->cacheStatus = CACHE_STALE;
67150 }
67151 }
67152 break;
67153 }
@@ -69323,10 +70217,722 @@
69323 }
69324
69325 #endif /* #ifndef SQLITE_OMIT_INCRBLOB */
69326
69327 /************** End of vdbeblob.c ********************************************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69328 /************** Begin file journal.c *****************************************/
69329 /*
69330 ** 2007 August 22
69331 **
69332 ** The author disclaims copyright to this source code. In place of
@@ -69839,10 +71445,12 @@
69839 **
69840 *************************************************************************
69841 ** This file contains routines used for walking the parser tree for
69842 ** an SQL statement.
69843 */
 
 
69844
69845
69846 /*
69847 ** Walk an expression tree. Invoke the callback once for each node
69848 ** of the expression, while decending. (In other words, the callback
@@ -69977,10 +71585,12 @@
69977 **
69978 ** This file contains routines used for walking the parser tree and
69979 ** resolve all identifiers by associating them with a particular
69980 ** table and column.
69981 */
 
 
69982
69983 /*
69984 ** Turn the pExpr expression into an alias for the iCol-th column of the
69985 ** result set in pEList.
69986 **
@@ -70956,15 +72566,29 @@
70956 /* Recursively resolve names in all subqueries
70957 */
70958 for(i=0; i<p->pSrc->nSrc; i++){
70959 struct SrcList_item *pItem = &p->pSrc->a[i];
70960 if( pItem->pSelect ){
 
 
70961 const char *zSavedContext = pParse->zAuthContext;
 
 
 
 
 
 
 
 
70962 if( pItem->zName ) pParse->zAuthContext = pItem->zName;
70963 sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
70964 pParse->zAuthContext = zSavedContext;
70965 if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
 
 
 
 
70966 }
70967 }
70968
70969 /* If there are no aggregate functions in the result-set, and no GROUP BY
70970 ** expression, do not allow aggregates in any of the other expressions.
@@ -72068,10 +73692,11 @@
72068 pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
72069 pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
72070 pNewItem->jointype = pOldItem->jointype;
72071 pNewItem->iCursor = pOldItem->iCursor;
72072 pNewItem->isPopulated = pOldItem->isPopulated;
 
72073 pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
72074 pNewItem->notIndexed = pOldItem->notIndexed;
72075 pNewItem->pIndex = pOldItem->pIndex;
72076 pTab = pNewItem->pTab = pOldItem->pTab;
72077 if( pTab ){
@@ -78958,11 +80583,11 @@
78958 Table *p;
78959 int n;
78960 const char *z;
78961 Token sEnd;
78962 DbFixer sFix;
78963 Token *pName;
78964 int iDb;
78965 sqlite3 *db = pParse->db;
78966
78967 if( pParse->nVar>0 ){
78968 sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
@@ -79263,10 +80888,33 @@
79263 iDestroyed = iLargest;
79264 }
79265 }
79266 #endif
79267 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79268
79269 /*
79270 ** This routine is called to do the work of a DROP TABLE statement.
79271 ** pName is the name of the table to be dropped.
79272 */
@@ -79403,18 +81051,11 @@
79403 ** database.
79404 */
79405 sqlite3NestedParse(pParse,
79406 "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
79407 pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
79408
79409 /* Drop any statistics from the sqlite_stat1 table, if it exists */
79410 if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
79411 sqlite3NestedParse(pParse,
79412 "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName
79413 );
79414 }
79415
79416 if( !isView && !IsVirtual(pTab) ){
79417 destroyTable(pParse, pTab);
79418 }
79419
79420 /* Remove the table entry from SQLite's internal schema and modify
@@ -79592,18 +81233,28 @@
79592 */
79593 static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
79594 Table *pTab = pIndex->pTable; /* The table that is indexed */
79595 int iTab = pParse->nTab++; /* Btree cursor used for pTab */
79596 int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
 
79597 int addr1; /* Address of top of loop */
79598 int tnum; /* Root page of index */
79599 Vdbe *v; /* Generate code into this virtual machine */
79600 KeyInfo *pKey; /* KeyInfo for index */
79601 int regIdxKey; /* Registers containing the index key */
79602 int regRecord; /* Register holding assemblied index record */
79603 sqlite3 *db = pParse->db; /* The database connection */
79604 int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
 
 
 
 
 
 
 
 
 
79605
79606 #ifndef SQLITE_OMIT_AUTHORIZATION
79607 if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
79608 db->aDb[iDb].zName ) ){
79609 return;
@@ -79625,14 +81276,33 @@
79625 sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
79626 (char *)pKey, P4_KEYINFO_HANDOFF);
79627 if( memRootPage>=0 ){
79628 sqlite3VdbeChangeP5(v, 1);
79629 }
 
 
 
 
 
 
 
 
 
 
79630 sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
79631 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
79632 regRecord = sqlite3GetTempReg(pParse);
79633 regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
 
 
 
 
 
 
 
 
 
79634 if( pIndex->onError!=OE_None ){
79635 const int regRowid = regIdxKey + pIndex->nColumn;
79636 const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
79637 void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
79638
@@ -79647,17 +81317,19 @@
79647 */
79648 sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
79649 sqlite3HaltConstraint(
79650 pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
79651 }
79652 sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
79653 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
79654 sqlite3ReleaseTempReg(pParse, regRecord);
79655 sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
79656 sqlite3VdbeJumpHere(v, addr1);
 
79657 sqlite3VdbeAddOp1(v, OP_Close, iTab);
79658 sqlite3VdbeAddOp1(v, OP_Close, iIdx);
 
79659 }
79660
79661 /*
79662 ** Create a new index for an SQL table. pName1.pName2 is the name of the index
79663 ** and pTblList is the name of the table that is to be indexed. Both will
@@ -80075,11 +81747,11 @@
80075 if( pStart ){
80076 assert( pEnd!=0 );
80077 /* A named index with an explicit CREATE INDEX statement */
80078 zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
80079 onError==OE_None ? "" : " UNIQUE",
80080 pEnd->z - pName->z + 1,
80081 pName->z);
80082 }else{
80083 /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
80084 /* zStmt = sqlite3MPrintf(""); */
80085 zStmt = 0;
@@ -80233,19 +81905,13 @@
80233 v = sqlite3GetVdbe(pParse);
80234 if( v ){
80235 sqlite3BeginWriteOperation(pParse, 1, iDb);
80236 sqlite3NestedParse(pParse,
80237 "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
80238 db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
80239 pIndex->zName
80240 );
80241 if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
80242 sqlite3NestedParse(pParse,
80243 "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q",
80244 db->aDb[iDb].zName, pIndex->zName
80245 );
80246 }
80247 sqlite3ChangeCookie(pParse, iDb);
80248 destroyRootPage(pParse, pIndex->tnum, iDb);
80249 sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
80250 }
80251
@@ -80613,12 +82279,13 @@
80613 ** The operator is "natural cross join". The A and B operands are stored
80614 ** in p->a[0] and p->a[1], respectively. The parser initially stores the
80615 ** operator with A. This routine shifts that operator over to B.
80616 */
80617 SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
80618 if( p && p->a ){
80619 int i;
 
80620 for(i=p->nSrc-1; i>0; i--){
80621 p->a[i].jointype = p->a[i-1].jointype;
80622 }
80623 p->a[0].jointype = 0;
80624 }
@@ -81870,11 +83537,13 @@
81870 int regRowid; /* Actual register containing rowids */
81871
81872 /* Collect rowids of every row to be deleted.
81873 */
81874 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
81875 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
 
 
81876 if( pWInfo==0 ) goto delete_from_cleanup;
81877 regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
81878 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
81879 if( db->flags & SQLITE_CountRows ){
81880 sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
@@ -82135,12 +83804,18 @@
82135 sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
82136 sqlite3ColumnDefault(v, pTab, idx, -1);
82137 }
82138 }
82139 if( doMakeRec ){
 
 
 
 
 
 
82140 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
82141 sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
82142 }
82143 sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
82144 return regBase;
82145 }
82146
@@ -82162,10 +83837,12 @@
82162 **
82163 ** There is only one exported symbol in this file - the function
82164 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
82165 ** All other code has file scope.
82166 */
 
 
82167
82168 /*
82169 ** Return the collating function associated with a function.
82170 */
82171 static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
@@ -84311,11 +85988,11 @@
84311
84312 /* Create VDBE to loop through the entries in pSrc that match the WHERE
84313 ** clause. If the constraint is not deferred, throw an exception for
84314 ** each row found. Otherwise, for deferred constraints, increment the
84315 ** deferred constraint counter by nIncr for each row selected. */
84316 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0);
84317 if( nIncr>0 && pFKey->isDeferred==0 ){
84318 sqlite3ParseToplevel(pParse)->mayAbort = 1;
84319 }
84320 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
84321 if( pWInfo ){
@@ -84485,11 +86162,28 @@
84485 pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
84486 }else{
84487 pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
84488 }
84489 if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
 
84490 if( !isIgnoreErrors || db->mallocFailed ) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84491 continue;
84492 }
84493 assert( pFKey->nCol==1 || (aiFree && pIdx) );
84494
84495 if( aiFree ){
@@ -87178,10 +88872,13 @@
87178 int (*strnicmp)(const char*,const char*,int);
87179 int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
87180 int (*wal_autocheckpoint)(sqlite3*,int);
87181 int (*wal_checkpoint)(sqlite3*,const char*);
87182 void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
 
 
 
87183 };
87184
87185 /*
87186 ** The following macros redefine the API routines so that they are
87187 ** redirected throught the global sqlite3_api structure.
@@ -87378,19 +89075,23 @@
87378 #define sqlite3_strnicmp sqlite3_api->strnicmp
87379 #define sqlite3_unlock_notify sqlite3_api->unlock_notify
87380 #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
87381 #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
87382 #define sqlite3_wal_hook sqlite3_api->wal_hook
 
 
 
87383 #endif /* SQLITE_CORE */
87384
87385 #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
87386 #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
87387
87388 #endif /* _SQLITE3EXT_H_ */
87389
87390 /************** End of sqlite3ext.h ******************************************/
87391 /************** Continuing where we left off in loadext.c ********************/
 
87392
87393 #ifndef SQLITE_OMIT_LOAD_EXTENSION
87394
87395 /*
87396 ** Some API routines are omitted when various features are
@@ -87452,10 +89153,12 @@
87452
87453 #ifdef SQLITE_OMIT_VIRTUALTABLE
87454 # define sqlite3_create_module 0
87455 # define sqlite3_create_module_v2 0
87456 # define sqlite3_declare_vtab 0
 
 
87457 #endif
87458
87459 #ifdef SQLITE_OMIT_SHARED_CACHE
87460 # define sqlite3_enable_shared_cache 0
87461 #endif
@@ -87475,10 +89178,11 @@
87475 #define sqlite3_blob_bytes 0
87476 #define sqlite3_blob_close 0
87477 #define sqlite3_blob_open 0
87478 #define sqlite3_blob_read 0
87479 #define sqlite3_blob_write 0
 
87480 #endif
87481
87482 /*
87483 ** The following structure contains pointers to all SQLite API routines.
87484 ** A pointer to this structure is passed into extensions when they are
@@ -87740,10 +89444,13 @@
87740 #else
87741 0,
87742 0,
87743 0,
87744 #endif
 
 
 
87745 };
87746
87747 /*
87748 ** Attempt to load an SQLite extension library contained in the file
87749 ** zFile. The entry point is zProc. zProc may be 0 in which case a
@@ -94129,10 +95836,11 @@
94129 Expr *pHaving; /* The HAVING clause. May be NULL */
94130 int isDistinct; /* True if the DISTINCT keyword is present */
94131 int distinct; /* Table to use for the distinct set */
94132 int rc = 1; /* Value to return from this function */
94133 int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
 
94134 AggInfo sAggInfo; /* Information used by aggregate queries */
94135 int iEnd; /* Address of the end of the query */
94136 sqlite3 *db; /* The database connection */
94137
94138 #ifndef SQLITE_OMIT_EXPLAIN
@@ -94255,20 +95963,10 @@
94255 explainSetInteger(pParse->iSelectId, iRestoreSelectId);
94256 return rc;
94257 }
94258 #endif
94259
94260 /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
94261 ** GROUP BY might use an index, DISTINCT never does.
94262 */
94263 assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
94264 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
94265 p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
94266 pGroupBy = p->pGroupBy;
94267 p->selFlags &= ~SF_Distinct;
94268 }
94269
94270 /* If there is both a GROUP BY and an ORDER BY clause and they are
94271 ** identical, then disable the ORDER BY clause since the GROUP BY
94272 ** will cause elements to come out in the correct order. This is
94273 ** an optimization - the correct answer should result regardless.
94274 ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
@@ -94276,10 +95974,34 @@
94276 */
94277 if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
94278 && (db->flags & SQLITE_GroupByOrder)==0 ){
94279 pOrderBy = 0;
94280 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94281
94282 /* If there is an ORDER BY clause, then this sorting
94283 ** index might end up being unused if the data can be
94284 ** extracted in pre-sorted order. If that is the case, then the
94285 ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
@@ -94312,26 +96034,25 @@
94312
94313 /* Open a virtual index to use for the distinct set.
94314 */
94315 if( p->selFlags & SF_Distinct ){
94316 KeyInfo *pKeyInfo;
94317 assert( isAgg || pGroupBy );
94318 distinct = pParse->nTab++;
94319 pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
94320 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
94321 (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
94322 sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
94323 }else{
94324 distinct = -1;
94325 }
94326
94327 /* Aggregate and non-aggregate queries are handled differently */
94328 if( !isAgg && pGroupBy==0 ){
94329 /* This case is for non-aggregate queries
94330 ** Begin the database scan
94331 */
94332 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
94333 if( pWInfo==0 ) goto select_end;
94334 if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
94335
94336 /* If sorting index that was created by a prior OP_OpenEphemeral
94337 ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -94340,14 +96061,56 @@
94340 if( addrSortIndex>=0 && pOrderBy==0 ){
94341 sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
94342 p->addrOpenEphm[2] = -1;
94343 }
94344
94345 /* Use the standard inner loop
94346 */
94347 assert(!isDistinct);
94348 selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94349 pWInfo->iContinue, pWInfo->iBreak);
94350
94351 /* End the database scan loop.
94352 */
94353 sqlite3WhereEnd(pWInfo);
@@ -94453,11 +96216,11 @@
94453 ** This might involve two separate loops with an OP_Sort in between, or
94454 ** it might be a single loop that uses an index to extract information
94455 ** in the right order to begin with.
94456 */
94457 sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
94458 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
94459 if( pWInfo==0 ) goto select_end;
94460 if( pGroupBy==0 ){
94461 /* The optimizer is able to deliver rows in group by order so
94462 ** we do not have to sort. The OP_OpenEphemeral table will be
94463 ** cancelled later because we still need to use the pKeyInfo
@@ -94715,11 +96478,11 @@
94715 /* This case runs if the aggregate has no GROUP BY clause. The
94716 ** processing is much simpler since there is only a single row
94717 ** of output.
94718 */
94719 resetAccumulator(pParse, &sAggInfo);
94720 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
94721 if( pWInfo==0 ){
94722 sqlite3ExprListDelete(db, pDel);
94723 goto select_end;
94724 }
94725 updateAccumulator(pParse, &sAggInfo);
@@ -94894,10 +96657,12 @@
94894 ** interface routine of sqlite3_exec().
94895 **
94896 ** These routines are in a separate files so that they will not be linked
94897 ** if they are not used.
94898 */
 
 
94899
94900 #ifndef SQLITE_OMIT_GET_TABLE
94901
94902 /*
94903 ** This structure is used to pass data from sqlite3_get_table() through
@@ -95191,19 +96956,32 @@
95191 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
95192 if( iDb<0 ){
95193 goto trigger_cleanup;
95194 }
95195 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95196
95197 /* If the trigger name was unqualified, and the table is a temp table,
95198 ** then set iDb to 1 to create the trigger in the temporary database.
95199 ** If sqlite3SrcListLookup() returns 0, indicating the table does not
95200 ** exist, the error is caught by the block below.
95201 */
95202 if( !pTableName || db->mallocFailed ){
95203 goto trigger_cleanup;
95204 }
95205 pTab = sqlite3SrcListLookup(pParse, pTableName);
95206 if( db->init.busy==0 && pName2->n==0 && pTab
95207 && pTab->pSchema==db->aDb[1].pSchema ){
95208 iDb = 1;
95209 }
@@ -96497,11 +98275,13 @@
96497 }
96498
96499 /* Begin the database scan
96500 */
96501 sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
96502 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
 
 
96503 if( pWInfo==0 ) goto update_cleanup;
96504 okOnePass = pWInfo->okOnePass;
96505
96506 /* Remember the rowid of every item to be updated.
96507 */
@@ -98523,10 +100303,11 @@
98523 #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
98524 #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
98525 #define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
98526 #define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
98527 #define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
 
98528
98529 /*
98530 ** Initialize a preallocated WhereClause structure.
98531 */
98532 static void whereClauseInit(
@@ -99667,10 +101448,166 @@
99667 }
99668 }
99669 return 0;
99670 }
99671
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99672
99673 /*
99674 ** This routine decides if pIdx can be used to satisfy the ORDER BY
99675 ** clause. If it can, it returns 1. If pIdx cannot satisfy the
99676 ** ORDER BY clause, this routine returns 0.
@@ -99703,11 +101640,14 @@
99703 int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
99704 int nTerm; /* Number of ORDER BY terms */
99705 struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
99706 sqlite3 *db = pParse->db;
99707
99708 assert( pOrderBy!=0 );
 
 
 
99709 nTerm = pOrderBy->nExpr;
99710 assert( nTerm>0 );
99711
99712 /* Argument pIdx must either point to a 'real' named index structure,
99713 ** or an index structure allocated on the stack by bestBtreeIndex() to
@@ -100016,10 +101956,14 @@
100016 double costTempIdx; /* per-query cost of the transient index */
100017 WhereTerm *pTerm; /* A single term of the WHERE clause */
100018 WhereTerm *pWCEnd; /* End of pWC->a[] */
100019 Table *pTable; /* Table tht might be indexed */
100020
 
 
 
 
100021 if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
100022 /* Automatic indices are disabled at run-time */
100023 return;
100024 }
100025 if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
@@ -100027,10 +101971,14 @@
100027 return;
100028 }
100029 if( pSrc->notIndexed ){
100030 /* The NOT INDEXED clause appears in the SQL. */
100031 return;
 
 
 
 
100032 }
100033
100034 assert( pParse->nQueryLoop >= (double)1 );
100035 pTable = pSrc->pTab;
100036 nTableRow = pTable->nRowEst;
@@ -100244,10 +102192,11 @@
100244 if( pTerm->leftCursor != pSrc->iCursor ) continue;
100245 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
100246 testcase( pTerm->eOperator==WO_IN );
100247 testcase( pTerm->eOperator==WO_ISNULL );
100248 if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
 
100249 nTerm++;
100250 }
100251
100252 /* If the ORDER BY clause contains only columns in the current
100253 ** virtual table then allocate space for the aOrderBy part of
@@ -100294,10 +102243,11 @@
100294 if( pTerm->leftCursor != pSrc->iCursor ) continue;
100295 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
100296 testcase( pTerm->eOperator==WO_IN );
100297 testcase( pTerm->eOperator==WO_ISNULL );
100298 if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
 
100299 pIdxCons[j].iColumn = pTerm->u.leftColumn;
100300 pIdxCons[j].iTermOffset = i;
100301 pIdxCons[j].op = (u8)pTerm->eOperator;
100302 /* The direct assignment in the previous line is possible only because
100303 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
@@ -100959,10 +102909,11 @@
100959 WhereClause *pWC, /* The WHERE clause */
100960 struct SrcList_item *pSrc, /* The FROM clause term to search */
100961 Bitmask notReady, /* Mask of cursors not available for indexing */
100962 Bitmask notValid, /* Cursors not available for any purpose */
100963 ExprList *pOrderBy, /* The ORDER BY clause */
 
100964 WhereCost *pCost /* Lowest cost query plan */
100965 ){
100966 int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
100967 Index *pProbe; /* An index we are evaluating */
100968 Index *pIdx; /* Copy of pProbe, or zero for IPK index */
@@ -101099,11 +103050,12 @@
101099 int nEq; /* Number of == or IN terms matching index */
101100 int bInEst = 0; /* True if "x IN (SELECT...)" seen */
101101 int nInMul = 1; /* Number of distinct equalities to lookup */
101102 int estBound = 100; /* Estimated reduction in search space */
101103 int nBound = 0; /* Number of range constraints seen */
101104 int bSort = 0; /* True if external sort required */
 
101105 int bLookup = 0; /* True if not a covering index */
101106 WhereTerm *pTerm; /* A single term of the WHERE clause */
101107 #ifdef SQLITE_ENABLE_STAT2
101108 WhereTerm *pFirstTerm = 0; /* First term matching the index */
101109 #endif
@@ -101163,21 +103115,24 @@
101163
101164 /* If there is an ORDER BY clause and the index being considered will
101165 ** naturally scan rows in the required order, set the appropriate flags
101166 ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
101167 ** will scan rows in a different order, set the bSort variable. */
101168 if( pOrderBy ){
101169 if( (wsFlags & WHERE_COLUMN_IN)==0
101170 && pProbe->bUnordered==0
101171 && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
101172 nEq, wsFlags, &rev)
101173 ){
101174 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
101175 wsFlags |= (rev ? WHERE_REVERSE : 0);
101176 }else{
101177 bSort = 1;
101178 }
 
 
 
101179 }
101180
101181 /* If currently calculating the cost of using an index (not the IPK
101182 ** index), determine if all required column data may be obtained without
101183 ** using the main table (i.e. if the index is a covering
@@ -101208,16 +103163,17 @@
101208 nRow = aiRowEst[0]/2;
101209 nInMul = (int)(nRow / aiRowEst[nEq]);
101210 }
101211
101212 #ifdef SQLITE_ENABLE_STAT2
101213 /* If the constraint is of the form x=VALUE and histogram
 
101214 ** data is available for column x, then it might be possible
101215 ** to get a better estimate on the number of rows based on
101216 ** VALUE and how common that value is according to the histogram.
101217 */
101218 if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
101219 if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
101220 testcase( pFirstTerm->eOperator==WO_EQ );
101221 testcase( pFirstTerm->eOperator==WO_ISNULL );
101222 whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
101223 }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
@@ -101290,10 +103246,13 @@
101290 ** difference and select C of 3.0.
101291 */
101292 if( bSort ){
101293 cost += nRow*estLog(nRow)*3;
101294 }
 
 
 
101295
101296 /**** Cost of using this index has now been computed ****/
101297
101298 /* If there are additional constraints on this table that cannot
101299 ** be used with the current index, but which might lower the number
@@ -101435,11 +103394,11 @@
101435 }
101436 sqlite3DbFree(pParse->db, p);
101437 }else
101438 #endif
101439 {
101440 bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
101441 }
101442 }
101443
101444 /*
101445 ** Disable a term in the WHERE clause. Except, do not disable the term
@@ -102397,11 +104356,11 @@
102397 for(ii=0; ii<pOrWc->nTerm; ii++){
102398 WhereTerm *pOrTerm = &pOrWc->a[ii];
102399 if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
102400 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
102401 /* Loop through table entries that match term pOrTerm. */
102402 pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
102403 WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
102404 WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
102405 if( pSubWInfo ){
102406 explainOneScan(
102407 pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -102638,10 +104597,11 @@
102638 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
102639 Parse *pParse, /* The parser context */
102640 SrcList *pTabList, /* A list of all tables to be scanned */
102641 Expr *pWhere, /* The WHERE clause */
102642 ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
 
102643 u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
102644 ){
102645 int i; /* Loop counter */
102646 int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
102647 int nTabList; /* Number of elements in pTabList */
@@ -102697,10 +104657,14 @@
102697 pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
102698 pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
102699 pWInfo->wctrlFlags = wctrlFlags;
102700 pWInfo->savedNQueryLoop = pParse->nQueryLoop;
102701 pMaskSet = (WhereMaskSet*)&pWC[1];
 
 
 
 
102702
102703 /* Split the WHERE clause into separate subexpressions where each
102704 ** subexpression is separated by an AND operator.
102705 */
102706 initMaskSet(pMaskSet);
@@ -102764,10 +104728,19 @@
102764 */
102765 exprAnalyzeAll(pTabList, pWC);
102766 if( db->mallocFailed ){
102767 goto whereBeginError;
102768 }
 
 
 
 
 
 
 
 
 
102769
102770 /* Chose the best index to use for each table in the FROM clause.
102771 **
102772 ** This loop fills in the following fields:
102773 **
@@ -102848,10 +104821,11 @@
102848 Bitmask mask; /* Mask of tables not yet ready */
102849 for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
102850 int doNotReorder; /* True if this table should not be reordered */
102851 WhereCost sCost; /* Cost information from best[Virtual]Index() */
102852 ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
 
102853
102854 doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
102855 if( j!=iFrom && doNotReorder ) break;
102856 m = getMask(pMaskSet, pTabItem->iCursor);
102857 if( (m & notReady)==0 ){
@@ -102858,10 +104832,11 @@
102858 if( j==iFrom ) iFrom++;
102859 continue;
102860 }
102861 mask = (isOptimal ? m : notReady);
102862 pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
 
102863 if( pTabItem->pIndex==0 ) nUnconstrained++;
102864
102865 WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
102866 j, isOptimal));
102867 assert( pTabItem->pTab );
@@ -102872,11 +104847,11 @@
102872 &sCost, pp);
102873 }else
102874 #endif
102875 {
102876 bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
102877 &sCost);
102878 }
102879 assert( isOptimal || (sCost.used&notReady)==0 );
102880
102881 /* If an INDEXED BY clause is present, then the plan must use that
102882 ** index if it uses any index at all */
@@ -102932,10 +104907,14 @@
102932 WHERETRACE(("*** Optimizer selects table %d for loop %d"
102933 " with cost=%g and nRow=%g\n",
102934 bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
102935 if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
102936 *ppOrderBy = 0;
 
 
 
 
102937 }
102938 andFlags &= bestPlan.plan.wsFlags;
102939 pLevel->plan = bestPlan.plan;
102940 testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
102941 testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
@@ -103267,10 +105246,11 @@
103267 ** LALR(1) grammar but which are always false in the
103268 ** specific grammar used by SQLite.
103269 */
103270 /* First off, code is included that follows the "include" declaration
103271 ** in the input grammar file. */
 
103272
103273
103274 /*
103275 ** Disable all error recovery processing in the parser push-down
103276 ** automaton.
@@ -104127,10 +106107,11 @@
104127 #endif
104128 };
104129 typedef struct yyParser yyParser;
104130
104131 #ifndef NDEBUG
 
104132 static FILE *yyTraceFILE = 0;
104133 static char *yyTracePrompt = 0;
104134 #endif /* NDEBUG */
104135
104136 #ifndef NDEBUG
@@ -106702,10 +108683,11 @@
106702 **
106703 ** This file contains C code that splits an SQL input string up into
106704 ** individual tokens and sends those tokens one-by-one over to the
106705 ** parser for analysis.
106706 */
 
106707
106708 /*
106709 ** The charMap() macro maps alphabetic characters into their
106710 ** lower-case ASCII equivalent. On ASCII machines, this is just
106711 ** an upper-to-lower case map. On EBCDIC machines we also need
@@ -108093,10 +110075,20 @@
108093 memcpy(&y, &x, 8);
108094 assert( sqlite3IsNaN(y) );
108095 }
108096 #endif
108097 #endif
 
 
 
 
 
 
 
 
 
 
108098
108099 return rc;
108100 }
108101
108102 /*
@@ -110763,10 +112755,21 @@
110763 if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
110764 sqlite3ScratchFree(pFree);
110765 break;
110766 }
110767
 
 
 
 
 
 
 
 
 
 
 
110768 }
110769 va_end(ap);
110770 #endif /* SQLITE_OMIT_BUILTIN_TEST */
110771 return rc;
110772 }
@@ -111420,16 +113423,10 @@
111420 ** TODO(shess) Provide a VACUUM type operation to clear out all
111421 ** deletions and duplications. This would basically be a forced merge
111422 ** into a single segment.
111423 */
111424
111425 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
111426
111427 #if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
111428 # define SQLITE_CORE 1
111429 #endif
111430
111431 /************** Include fts3Int.h in the middle of fts3.c ********************/
111432 /************** Begin file fts3Int.h *****************************************/
111433 /*
111434 ** 2009 Nov 12
111435 **
@@ -111441,18 +113438,33 @@
111441 ** May you share freely, never taking more than you give.
111442 **
111443 ******************************************************************************
111444 **
111445 */
111446
111447 #ifndef _FTSINT_H
111448 #define _FTSINT_H
111449
111450 #if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
111451 # define NDEBUG 1
111452 #endif
111453
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111454 /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
111455 /************** Begin file fts3_tokenizer.h **********************************/
111456 /*
111457 ** 2006 July 10
111458 **
@@ -111940,11 +113952,11 @@
111940 char *aDoclist; /* List of docids for full-text queries */
111941 int nDoclist; /* Size of buffer at aDoclist */
111942 u8 bDesc; /* True to sort in descending order */
111943 int eEvalmode; /* An FTS3_EVAL_XX constant */
111944 int nRowAvg; /* Average size of database rows, in pages */
111945 int nDoc; /* Documents in table */
111946
111947 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
111948 u32 *aMatchinfo; /* Information about most recent match */
111949 int nMatchinfo; /* Number of elements in aMatchinfo[] */
111950 char *zMatchinfo; /* Matchinfo specification */
@@ -111981,11 +113993,11 @@
111981
111982 sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
111983 int bFreeList; /* True if pList should be sqlite3_free()d */
111984 char *pList; /* Pointer to position list following iDocid */
111985 int nList; /* Length of position list */
111986 } doclist;
111987
111988 /*
111989 ** A "phrase" is a sequence of one or more tokens that must match in
111990 ** sequence. A single token is the base case and the most common case.
111991 ** For a sequence of tokens contained in double-quotes (i.e. "one two three")
@@ -111997,19 +114009,19 @@
111997 int isPrefix; /* True if token ends with a "*" character */
111998
111999 /* Variables above this point are populated when the expression is
112000 ** parsed (by code in fts3_expr.c). Below this point the variables are
112001 ** used when evaluating the expression. */
112002 int bFulltext; /* True if full-text index was used */
112003 Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
112004 Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */
112005 };
112006
112007 struct Fts3Phrase {
112008 /* Cache of doclist for this phrase. */
112009 Fts3Doclist doclist;
112010 int bIncr; /* True if doclist is loaded incrementally */
 
112011
112012 /* Variables below this point are populated by fts3_expr.c when parsing
112013 ** a MATCH expression. Everything above is part of the evaluation phase.
112014 */
112015 int nToken; /* Number of tokens in the phrase */
@@ -112130,10 +114142,11 @@
112130 Fts3SegFilter *pFilter; /* Pointer to filter object */
112131 char *aBuffer; /* Buffer to merge doclists in */
112132 int nBuffer; /* Allocated size of aBuffer[] in bytes */
112133
112134 int iColFilter; /* If >=0, filter for this column */
 
112135
112136 /* Used by fts3.c only. */
112137 int nCost; /* Cost of running iterator */
112138 int bLookup; /* True if a lookup of a single entry. */
112139
@@ -112180,43 +114193,49 @@
112180 #endif
112181
112182 /* fts3_aux.c */
112183 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
112184
112185 SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
112186 Fts3Cursor *pCsr, /* Virtual table cursor handle */
112187 const char *zTerm, /* Term to query for */
112188 int nTerm, /* Size of zTerm in bytes */
112189 int isPrefix, /* True for a prefix search */
112190 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
112191 );
112192
112193 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
112194
112195 SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
112196 SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
112197
112198 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
112199 Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
112200 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
112201 Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
112202 SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
112203 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
 
112204
112205 SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
112206
112207
112208 #endif /* _FTSINT_H */
112209
112210 /************** End of fts3Int.h *********************************************/
112211 /************** Continuing where we left off in fts3.c ***********************/
 
112212
 
 
 
 
 
 
 
 
 
 
112213
112214 #ifndef SQLITE_CORE
112215 SQLITE_EXTENSION_INIT1
112216 #endif
112217
 
 
 
 
 
112218 /*
112219 ** Write a 64-bit variable-length integer to memory starting at p[0].
112220 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
112221 ** The number of bytes written is returned.
112222 */
@@ -112545,10 +114564,13 @@
112545 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
112546 if( rc==SQLITE_OK ){
112547 sqlite3_step(pStmt);
112548 p->nPgsz = sqlite3_column_int(pStmt, 0);
112549 rc = sqlite3_finalize(pStmt);
 
 
 
112550 }
112551 }
112552 assert( p->nPgsz>0 || rc!=SQLITE_OK );
112553 sqlite3_free(zSql);
112554 *pRc = rc;
@@ -112718,31 +114740,60 @@
112718 }
112719 sqlite3_free(zFree);
112720 return zRet;
112721 }
112722
 
 
 
 
 
 
 
 
 
 
 
 
 
112723 static int fts3GobbleInt(const char **pp, int *pnOut){
112724 const char *p = *pp;
112725 int nInt = 0;
 
112726 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
112727 nInt = nInt * 10 + (p[0] - '0');
112728 }
112729 if( p==*pp ) return SQLITE_ERROR;
112730 *pnOut = nInt;
112731 *pp = p;
112732 return SQLITE_OK;
112733 }
112734
112735
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112736 static int fts3PrefixParameter(
112737 const char *zParam, /* ABC in prefix=ABC parameter to parse */
112738 int *pnIndex, /* OUT: size of *apIndex[] array */
112739 struct Fts3Index **apIndex, /* OUT: Array of indexes for this table */
112740 struct Fts3Index **apFree /* OUT: Free this with sqlite3_free() */
112741 ){
112742 struct Fts3Index *aIndex;
112743 int nIndex = 1;
112744
112745 if( zParam && zParam[0] ){
112746 const char *p;
112747 nIndex++;
112748 for(p=zParam; *p; p++){
@@ -112749,11 +114800,11 @@
112749 if( *p==',' ) nIndex++;
112750 }
112751 }
112752
112753 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
112754 *apIndex = *apFree = aIndex;
112755 *pnIndex = nIndex;
112756 if( !aIndex ){
112757 return SQLITE_NOMEM;
112758 }
112759
@@ -112806,12 +114857,11 @@
112806 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
112807 const char **aCol; /* Array of column names */
112808 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
112809
112810 int nIndex; /* Size of aIndex[] array */
112811 struct Fts3Index *aIndex; /* Array of indexes for this table */
112812 struct Fts3Index *aFree = 0; /* Free this before returning */
112813
112814 /* The results of parsing supported FTS4 key=value options: */
112815 int bNoDocsize = 0; /* True to omit %_docsize table */
112816 int bDescIdx = 0; /* True to store descending indexes */
112817 char *zPrefix = 0; /* Prefix parameter value (or NULL) */
@@ -112944,11 +114994,11 @@
112944 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
112945 if( rc!=SQLITE_OK ) goto fts3_init_out;
112946 }
112947 assert( pTokenizer );
112948
112949 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
112950 if( rc==SQLITE_ERROR ){
112951 assert( zPrefix );
112952 *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
112953 }
112954 if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -112995,11 +115045,11 @@
112995 zCsr += nDb;
112996
112997 /* Fill in the azColumn array */
112998 for(iCol=0; iCol<nCol; iCol++){
112999 char *z;
113000 int n;
113001 z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
113002 memcpy(zCsr, z, n);
113003 zCsr[n] = '\0';
113004 sqlite3Fts3Dequote(zCsr);
113005 p->azColumn[iCol] = zCsr;
@@ -113031,11 +115081,11 @@
113031 /* Declare the table schema to SQLite. */
113032 fts3DeclareVtab(&rc, p);
113033
113034 fts3_init_out:
113035 sqlite3_free(zPrefix);
113036 sqlite3_free(aFree);
113037 sqlite3_free(zCompress);
113038 sqlite3_free(zUncompress);
113039 sqlite3_free((void *)aCol);
113040 if( rc!=SQLITE_OK ){
113041 if( p ){
@@ -113622,12 +115672,10 @@
113622 *pp1 = p1 + 1;
113623 *pp2 = p2 + 1;
113624 }
113625
113626 /*
113627 ** nToken==1 searches for adjacent positions.
113628 **
113629 ** This function is used to merge two position lists into one. When it is
113630 ** called, *pp1 and *pp2 must both point to position lists. A position-list is
113631 ** the part of a doclist that follows each document id. For example, if a row
113632 ** contains:
113633 **
@@ -113643,10 +115691,12 @@
113643 ** If isSaveLeft is 0, an entry is added to the output position list for
113644 ** each position in *pp2 for which there exists one or more positions in
113645 ** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
113646 ** when the *pp1 token appears before the *pp2 token, but not more than nToken
113647 ** slots before it.
 
 
113648 */
113649 static int fts3PoslistPhraseMerge(
113650 char **pp, /* IN/OUT: Preallocated output buffer */
113651 int nToken, /* Maximum difference in token positions */
113652 int isSaveLeft, /* Save the left position */
@@ -113809,26 +115859,38 @@
113809
113810 return res;
113811 }
113812
113813 /*
113814 ** A pointer to an instance of this structure is used as the context
113815 ** argument to sqlite3Fts3SegReaderIterate()
 
113816 */
113817 typedef struct TermSelect TermSelect;
113818 struct TermSelect {
113819 int isReqPos;
113820 char *aaOutput[16]; /* Malloc'd output buffer */
113821 int anOutput[16]; /* Size of output in bytes */
113822 };
113823
113824
 
 
 
 
 
 
 
 
 
 
 
 
113825 static void fts3GetDeltaVarint3(
113826 char **pp,
113827 char *pEnd,
113828 int bDescIdx,
113829 sqlite3_int64 *pVal
113830 ){
113831 if( *pp>=pEnd ){
113832 *pp = 0;
113833 }else{
113834 sqlite3_int64 iVal;
@@ -113839,10 +115901,25 @@
113839 *pVal += iVal;
113840 }
113841 }
113842 }
113843
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113844 static void fts3PutDeltaVarint3(
113845 char **pp, /* IN/OUT: Output pointer */
113846 int bDescIdx, /* True for descending docids */
113847 sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
113848 int *pbFirst, /* IN/OUT: True after first int written */
@@ -113859,14 +115936,38 @@
113859 *pp += sqlite3Fts3PutVarint(*pp, iWrite);
113860 *piPrev = iVal;
113861 *pbFirst = 1;
113862 }
113863
113864 #define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))
113865
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113866 static int fts3DoclistOrMerge(
113867 int bDescIdx, /* True if arguments are desc */
113868 char *a1, int n1, /* First doclist */
113869 char *a2, int n2, /* Second doclist */
113870 char **paOut, int *pnOut /* OUT: Malloc'd doclist */
113871 ){
113872 sqlite3_int64 i1 = 0;
@@ -113887,35 +115988,47 @@
113887
113888 p = aOut;
113889 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113890 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113891 while( p1 || p2 ){
113892 sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
113893
113894 if( p2 && p1 && iDiff==0 ){
113895 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113896 fts3PoslistMerge(&p, &p1, &p2);
113897 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113898 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113899 }else if( !p2 || (p1 && iDiff<0) ){
113900 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113901 fts3PoslistCopy(&p, &p1);
113902 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113903 }else{
113904 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
113905 fts3PoslistCopy(&p, &p2);
113906 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113907 }
113908 }
113909
113910 *paOut = aOut;
113911 *pnOut = (p-aOut);
113912 return SQLITE_OK;
113913 }
113914
 
 
 
 
 
 
 
 
 
 
 
 
113915 static void fts3DoclistPhraseMerge(
113916 int bDescIdx, /* True if arguments are desc */
113917 int nDist, /* Distance from left to right (1=adjacent) */
113918 char *aLeft, int nLeft, /* Left doclist */
113919 char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
113920 ){
113921 sqlite3_int64 i1 = 0;
@@ -113934,30 +116047,30 @@
113934 p = aOut;
113935 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113936 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113937
113938 while( p1 && p2 ){
113939 sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
113940 if( iDiff==0 ){
113941 char *pSave = p;
113942 sqlite3_int64 iPrevSave = iPrev;
113943 int bFirstOutSave = bFirstOut;
113944
113945 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113946 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
113947 p = pSave;
113948 iPrev = iPrevSave;
113949 bFirstOut = bFirstOutSave;
113950 }
113951 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113952 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113953 }else if( iDiff<0 ){
113954 fts3PoslistCopy(0, &p1);
113955 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113956 }else{
113957 fts3PoslistCopy(0, &p2);
113958 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113959 }
113960 }
113961
113962 *pnRight = p - aOut;
113963 }
@@ -113970,11 +116083,11 @@
113970 **
113971 ** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
113972 ** the responsibility of the caller to free any doclists left in the
113973 ** TermSelect.aaOutput[] array.
113974 */
113975 static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
113976 char *aOut = 0;
113977 int nOut = 0;
113978 int i;
113979
113980 /* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -114011,28 +116124,29 @@
114011 pTS->anOutput[0] = nOut;
114012 return SQLITE_OK;
114013 }
114014
114015 /*
114016 ** This function is used as the sqlite3Fts3SegReaderIterate() callback when
114017 ** querying the full-text index for a doclist associated with a term or
114018 ** term-prefix.
 
 
 
 
 
 
 
 
 
114019 */
114020 static int fts3TermSelectCb(
114021 Fts3Table *p, /* Virtual table object */
114022 void *pContext, /* Pointer to TermSelect structure */
114023 char *zTerm,
114024 int nTerm,
114025 char *aDoclist,
114026 int nDoclist
114027 ){
114028 TermSelect *pTS = (TermSelect *)pContext;
114029
114030 UNUSED_PARAMETER(p);
114031 UNUSED_PARAMETER(zTerm);
114032 UNUSED_PARAMETER(nTerm);
114033
114034 if( pTS->aaOutput[0]==0 ){
114035 /* If this is the first term selected, copy the doclist to the output
114036 ** buffer using memcpy(). */
114037 pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
114038 pTS->anOutput[0] = nDoclist;
@@ -114099,23 +116213,30 @@
114099 }
114100 pCsr->apSegment[pCsr->nSegment++] = pNew;
114101 return SQLITE_OK;
114102 }
114103
 
 
 
 
 
 
 
114104 static int fts3SegReaderCursor(
114105 Fts3Table *p, /* FTS3 table handle */
114106 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114107 int iLevel, /* Level of segments to scan */
114108 const char *zTerm, /* Term to query for */
114109 int nTerm, /* Size of zTerm in bytes */
114110 int isPrefix, /* True for a prefix search */
114111 int isScan, /* True to scan from zTerm to EOF */
114112 Fts3MultiSegReader *pCsr /* Cursor object to populate */
114113 ){
114114 int rc = SQLITE_OK;
114115 int rc2;
114116 sqlite3_stmt *pStmt = 0;
114117
114118 /* If iLevel is less than 0 and this is not a scan, include a seg-reader
114119 ** for the pending-terms. If this is a scan, then this call must be being
114120 ** made by an fts4aux module, not an FTS table. In this case calling
114121 ** Fts3SegReaderPending might segfault, as the data structures used by
@@ -114200,28 +116321,46 @@
114200 return fts3SegReaderCursor(
114201 p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
114202 );
114203 }
114204
 
 
 
 
 
 
114205 static int fts3SegReaderCursorAddZero(
114206 Fts3Table *p,
114207 const char *zTerm,
114208 int nTerm,
114209 Fts3MultiSegReader *pCsr
114210 ){
114211 return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
114212 }
114213
114214
114215 SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
 
 
 
 
 
 
 
 
 
 
 
 
114216 Fts3Cursor *pCsr, /* Virtual table cursor handle */
114217 const char *zTerm, /* Term to query for */
114218 int nTerm, /* Size of zTerm in bytes */
114219 int isPrefix, /* True for a prefix search */
114220 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
114221 ){
114222 Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114223 int rc = SQLITE_NOMEM; /* Return code */
114224
114225 pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
114226 if( pSegcsr ){
114227 int i;
@@ -114261,62 +116400,53 @@
114261
114262 *ppSegcsr = pSegcsr;
114263 return rc;
114264 }
114265
 
 
 
114266 static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
114267 sqlite3Fts3SegReaderFinish(pSegcsr);
114268 sqlite3_free(pSegcsr);
114269 }
114270
114271 /*
114272 ** This function retreives the doclist for the specified term (or term
114273 ** prefix) from the database.
114274 **
114275 ** The returned doclist may be in one of two formats, depending on the
114276 ** value of parameter isReqPos. If isReqPos is zero, then the doclist is
114277 ** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
114278 ** is non-zero, then the returned list is in the same format as is stored
114279 ** in the database without the found length specifier at the start of on-disk
114280 ** doclists.
114281 */
114282 static int fts3TermSelect(
114283 Fts3Table *p, /* Virtual table handle */
114284 Fts3PhraseToken *pTok, /* Token to query for */
114285 int iColumn, /* Column to query (or -ve for all columns) */
114286 int isReqPos, /* True to include position lists in output */
114287 int *pnOut, /* OUT: Size of buffer at *ppOut */
114288 char **ppOut /* OUT: Malloced result buffer */
114289 ){
114290 int rc; /* Return code */
114291 Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114292 TermSelect tsc; /* Context object for fts3TermSelectCb() */
114293 Fts3SegFilter filter; /* Segment term filter configuration */
114294
114295 pSegcsr = pTok->pSegcsr;
114296 memset(&tsc, 0, sizeof(TermSelect));
114297 tsc.isReqPos = isReqPos;
114298
114299 filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
114300 | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
114301 | (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
114302 | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
114303 filter.iCol = iColumn;
114304 filter.zTerm = pTok->z;
114305 filter.nTerm = pTok->n;
114306
114307 rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
114308 while( SQLITE_OK==rc
114309 && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
114310 ){
114311 rc = fts3TermSelectCb(p, (void *)&tsc,
114312 pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
114313 );
114314 }
114315
114316 if( rc==SQLITE_OK ){
114317 rc = fts3TermSelectMerge(p, &tsc);
114318 }
114319 if( rc==SQLITE_OK ){
114320 *ppOut = tsc.aaOutput[0];
114321 *pnOut = tsc.anOutput[0];
114322 }else{
@@ -114338,28 +116468,19 @@
114338 ** If the isPoslist argument is true, then it is assumed that the doclist
114339 ** contains a position-list following each docid. Otherwise, it is assumed
114340 ** that the doclist is simply a list of docids stored as delta encoded
114341 ** varints.
114342 */
114343 static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
114344 int nDoc = 0; /* Return value */
114345 if( aList ){
114346 char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
114347 char *p = aList; /* Cursor */
114348 if( !isPoslist ){
114349 /* The number of docids in the list is the same as the number of
114350 ** varints. In FTS3 a varint consists of a single byte with the 0x80
114351 ** bit cleared and zero or more bytes with the 0x80 bit set. So to
114352 ** count the varints in the buffer, just count the number of bytes
114353 ** with the 0x80 bit clear. */
114354 while( p<aEnd ) nDoc += (((*p++)&0x80)==0);
114355 }else{
114356 while( p<aEnd ){
114357 nDoc++;
114358 while( (*p++)&0x80 ); /* Skip docid varint */
114359 fts3PoslistCopy(0, &p); /* Skip over position list */
114360 }
114361 }
114362 }
114363
114364 return nDoc;
114365 }
@@ -114385,11 +116506,11 @@
114385 }else{
114386 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114387 rc = SQLITE_OK;
114388 }
114389 }else{
114390 rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
114391 }
114392 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
114393 return rc;
114394 }
114395
@@ -114462,11 +116583,11 @@
114462 }
114463
114464 rc = sqlite3Fts3ReadLock(p);
114465 if( rc!=SQLITE_OK ) return rc;
114466
114467 rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
114468
114469 sqlite3Fts3SegmentsClose(p);
114470 if( rc!=SQLITE_OK ) return rc;
114471 pCsr->pNextId = pCsr->aDoclist;
114472 pCsr->iPrevId = 0;
@@ -114581,12 +116702,12 @@
114581
114582 /*
114583 ** Implementation of xBegin() method. This is a no-op.
114584 */
114585 static int fts3BeginMethod(sqlite3_vtab *pVtab){
114586 UNUSED_PARAMETER(pVtab);
114587 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
 
114588 assert( p->pSegments==0 );
114589 assert( p->nPendingData==0 );
114590 assert( p->inTransaction!=1 );
114591 TESTONLY( p->inTransaction = 1 );
114592 TESTONLY( p->mxSavepoint = -1; );
@@ -114597,12 +116718,12 @@
114597 ** Implementation of xCommit() method. This is a no-op. The contents of
114598 ** the pending-terms hash-table have already been flushed into the database
114599 ** by fts3SyncMethod().
114600 */
114601 static int fts3CommitMethod(sqlite3_vtab *pVtab){
114602 UNUSED_PARAMETER(pVtab);
114603 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
 
114604 assert( p->nPendingData==0 );
114605 assert( p->inTransaction!=0 );
114606 assert( p->pSegments==0 );
114607 TESTONLY( p->inTransaction = 0 );
114608 TESTONLY( p->mxSavepoint = -1; );
@@ -114869,26 +116990,43 @@
114869 p->zDb, p->zName, zName
114870 );
114871 return rc;
114872 }
114873
 
 
 
 
 
114874 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
114875 UNUSED_PARAMETER(iSavepoint);
114876 assert( ((Fts3Table *)pVtab)->inTransaction );
114877 assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
114878 TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
114879 return fts3SyncMethod(pVtab);
114880 }
 
 
 
 
 
 
114881 static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
114882 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114883 UNUSED_PARAMETER(iSavepoint);
114884 UNUSED_PARAMETER(pVtab);
114885 assert( p->inTransaction );
114886 assert( p->mxSavepoint >= iSavepoint );
114887 TESTONLY( p->mxSavepoint = iSavepoint-1 );
114888 return SQLITE_OK;
114889 }
 
 
 
 
 
 
114890 static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
114891 Fts3Table *p = (Fts3Table*)pVtab;
114892 UNUSED_PARAMETER(iSavepoint);
114893 assert( p->inTransaction );
114894 assert( p->mxSavepoint >= iSavepoint );
@@ -115033,22 +117171,10 @@
115033 sqlite3Fts3HashClear(pHash);
115034 sqlite3_free(pHash);
115035 }
115036 return rc;
115037 }
115038
115039 #if !SQLITE_CORE
115040 SQLITE_API int sqlite3_extension_init(
115041 sqlite3 *db,
115042 char **pzErrMsg,
115043 const sqlite3_api_routines *pApi
115044 ){
115045 SQLITE_EXTENSION_INIT2(pApi)
115046 return sqlite3Fts3Init(db);
115047 }
115048 #endif
115049
115050
115051 /*
115052 ** Allocate an Fts3MultiSegReader for each token in the expression headed
115053 ** by pExpr.
115054 **
@@ -115062,99 +117188,151 @@
115062 ** there exists prefix b-tree of the right length) then it may be traversed
115063 ** and merged incrementally. Otherwise, it has to be merged into an in-memory
115064 ** doclist and then traversed.
115065 */
115066 static void fts3EvalAllocateReaders(
115067 Fts3Cursor *pCsr,
115068 Fts3Expr *pExpr,
115069 int *pnToken, /* OUT: Total number of tokens in phrase. */
115070 int *pnOr, /* OUT: Total number of OR nodes in expr. */
115071 int *pRc
115072 ){
115073 if( pExpr && SQLITE_OK==*pRc ){
115074 if( pExpr->eType==FTSQUERY_PHRASE ){
115075 int i;
115076 int nToken = pExpr->pPhrase->nToken;
115077 *pnToken += nToken;
115078 for(i=0; i<nToken; i++){
115079 Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
115080 int rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115081 pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115082 );
115083 if( rc!=SQLITE_OK ){
115084 *pRc = rc;
115085 return;
115086 }
115087 }
 
 
115088 }else{
115089 *pnOr += (pExpr->eType==FTSQUERY_OR);
115090 fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
115091 fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
115092 }
115093 }
115094 }
115095
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115096 static int fts3EvalPhraseLoad(
115097 Fts3Cursor *pCsr,
115098 Fts3Phrase *p
115099 ){
115100 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115101 int iToken;
115102 int rc = SQLITE_OK;
115103
115104 char *aDoclist = 0;
115105 int nDoclist = 0;
115106 int iPrev = -1;
115107
115108 for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
115109 Fts3PhraseToken *pToken = &p->aToken[iToken];
115110 assert( pToken->pSegcsr || pToken->pDeferred );
115111
115112 if( pToken->pDeferred==0 ){
115113 int nThis = 0;
115114 char *pThis = 0;
115115 rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
115116 if( rc==SQLITE_OK ){
115117 if( pThis==0 ){
115118 sqlite3_free(aDoclist);
115119 aDoclist = 0;
115120 nDoclist = 0;
115121 break;
115122 }else if( aDoclist==0 ){
115123 aDoclist = pThis;
115124 nDoclist = nThis;
115125 }else{
115126 assert( iPrev>=0 );
115127 fts3DoclistPhraseMerge(pTab->bDescIdx,
115128 iToken-iPrev, aDoclist, nDoclist, pThis, &nThis
115129 );
115130 sqlite3_free(aDoclist);
115131 aDoclist = pThis;
115132 nDoclist = nThis;
115133 }
115134 iPrev = iToken;
115135 }
115136 }
115137 }
115138
115139 if( rc==SQLITE_OK ){
115140 p->doclist.aAll = aDoclist;
115141 p->doclist.nAll = nDoclist;
115142 }else{
115143 sqlite3_free(aDoclist);
115144 }
115145 return rc;
115146 }
115147
115148 static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
115149 int iToken;
115150 int rc = SQLITE_OK;
115151
115152 int nMaxUndeferred = -1;
115153 char *aPoslist = 0;
115154 int nPoslist = 0;
115155 int iPrev = -1;
115156
115157 assert( pPhrase->doclist.bFreeList==0 );
115158
115159 for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
115160 Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -115192,16 +117370,15 @@
115192 pPhrase->doclist.nList = 0;
115193 return SQLITE_OK;
115194 }
115195 }
115196 iPrev = iToken;
115197 }else{
115198 nMaxUndeferred = iToken;
115199 }
115200 }
115201
115202 if( iPrev>=0 ){
 
115203 if( nMaxUndeferred<0 ){
115204 pPhrase->doclist.pList = aPoslist;
115205 pPhrase->doclist.nList = nPoslist;
115206 pPhrase->doclist.iDocid = pCsr->iPrevId;
115207 pPhrase->doclist.bFreeList = 1;
@@ -115246,19 +117423,27 @@
115246 /*
115247 ** This function is called for each Fts3Phrase in a full-text query
115248 ** expression to initialize the mechanism for returning rows. Once this
115249 ** function has been called successfully on an Fts3Phrase, it may be
115250 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
 
 
 
 
 
 
115251 */
115252 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
115253 int rc;
115254 Fts3PhraseToken *pFirst = &p->aToken[0];
115255 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115256
115257 assert( p->doclist.aAll==0 );
115258 if( pCsr->bDesc==pTab->bDescIdx && bOptOk==1 && p->nToken==1
115259 && pFirst->pSegcsr && pFirst->pSegcsr->bLookup
 
 
115260 ){
115261 /* Use the incremental approach. */
115262 int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
115263 rc = sqlite3Fts3MsrIncrStart(
115264 pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
@@ -115274,11 +117459,17 @@
115274 return rc;
115275 }
115276
115277 /*
115278 ** This function is used to iterate backwards (from the end to start)
115279 ** through doclists.
 
 
 
 
 
 
115280 */
115281 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
115282 int bDescIdx, /* True if the doclist is desc */
115283 char *aDoclist, /* Pointer to entire doclist */
115284 int nDoclist, /* Length of aDoclist in bytes */
@@ -115339,13 +117530,13 @@
115339 ** If there is no "next" entry and no error occurs, then *pbEof is set to
115340 ** 1 before returning. Otherwise, if no error occurs and the iterator is
115341 ** successfully advanced, *pbEof is set to 0.
115342 */
115343 static int fts3EvalPhraseNext(
115344 Fts3Cursor *pCsr,
115345 Fts3Phrase *p,
115346 u8 *pbEof
115347 ){
115348 int rc = SQLITE_OK;
115349 Fts3Doclist *pDL = &p->doclist;
115350 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115351
@@ -115387,30 +117578,46 @@
115387 fts3PoslistCopy(0, &pIter);
115388 pDL->nList = (pIter - pDL->pList);
115389
115390 /* pIter now points just past the 0x00 that terminates the position-
115391 ** list for document pDL->iDocid. However, if this position-list was
115392 ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
115393 ** point to the start of the next docid value. The following line deals
115394 ** with this case by advancing pIter past the zero-padding added by
115395 ** fts3EvalNearTrim2(). */
115396 while( pIter<pEnd && *pIter==0 ) pIter++;
115397
115398 pDL->pNextDocid = pIter;
115399 assert( *pIter || pIter>=&pDL->aAll[pDL->nAll] );
115400 *pbEof = 0;
115401 }
115402 }
115403
115404 return rc;
115405 }
115406
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115407 static void fts3EvalStartReaders(
115408 Fts3Cursor *pCsr,
115409 Fts3Expr *pExpr,
115410 int bOptOk,
115411 int *pRc
115412 ){
115413 if( pExpr && SQLITE_OK==*pRc ){
115414 if( pExpr->eType==FTSQUERY_PHRASE ){
115415 int i;
115416 int nToken = pExpr->pPhrase->nToken;
@@ -115425,33 +117632,55 @@
115425 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
115426 }
115427 }
115428 }
115429
115430
 
 
 
 
 
 
 
 
 
 
 
115431 typedef struct Fts3TokenAndCost Fts3TokenAndCost;
115432 struct Fts3TokenAndCost {
115433 Fts3PhraseToken *pToken;
115434 Fts3Expr *pRoot;
115435 int nOvfl;
115436 int iCol;
 
 
115437 };
115438
 
 
 
 
 
 
 
115439 static void fts3EvalTokenCosts(
115440 Fts3Cursor *pCsr,
115441 Fts3Expr *pRoot,
115442 Fts3Expr *pExpr,
115443 Fts3TokenAndCost **ppTC,
115444 Fts3Expr ***ppOr,
115445 int *pRc
115446 ){
115447 if( *pRc==SQLITE_OK && pExpr ){
115448 if( pExpr->eType==FTSQUERY_PHRASE ){
115449 Fts3Phrase *pPhrase = pExpr->pPhrase;
115450 int i;
115451 for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
115452 Fts3TokenAndCost *pTC = (*ppTC)++;
 
 
115453 pTC->pRoot = pRoot;
115454 pTC->pToken = &pPhrase->aToken[i];
115455 pTC->iCol = pPhrase->iColumn;
115456 *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
115457 }
@@ -115470,23 +117699,34 @@
115470 fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
115471 }
115472 }
115473 }
115474
 
 
 
 
 
 
 
 
 
 
 
115475 static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
115476 if( pCsr->nRowAvg==0 ){
115477 /* The average document size, which is required to calculate the cost
115478 ** of each doclist, has not yet been determined. Read the required
115479 ** data from the %_stat table to calculate it.
115480 **
115481 ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
115482 ** varints, where nCol is the number of columns in the FTS3 table.
115483 ** The first varint is the number of documents currently stored in
115484 ** the table. The following nCol varints contain the total amount of
115485 ** data stored in all rows of each column of the table, from left
115486 ** to right.
115487 */
115488 int rc;
115489 Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
115490 sqlite3_stmt *pStmt;
115491 sqlite3_int64 nDoc = 0;
115492 sqlite3_int64 nByte = 0;
@@ -115517,113 +117757,151 @@
115517
115518 *pnPage = pCsr->nRowAvg;
115519 return SQLITE_OK;
115520 }
115521
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115522 static int fts3EvalSelectDeferred(
115523 Fts3Cursor *pCsr,
115524 Fts3Expr *pRoot,
115525 Fts3TokenAndCost *aTC,
115526 int nTC
115527 ){
115528 int nDocSize = 0;
115529 int nDocEst = 0;
115530 int rc = SQLITE_OK;
115531 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115532 int ii;
 
 
 
 
115533
115534 int nOvfl = 0;
115535 int nTerm = 0;
115536
 
 
 
115537 for(ii=0; ii<nTC; ii++){
115538 if( aTC[ii].pRoot==pRoot ){
115539 nOvfl += aTC[ii].nOvfl;
115540 nTerm++;
115541 }
115542 }
115543 if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
115544
 
115545 rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
115546
115547 for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
115548 int jj;
115549 Fts3TokenAndCost *pTC = 0;
115550
115551 for(jj=0; jj<nTC; jj++){
115552 if( aTC[jj].pToken && aTC[jj].pRoot==pRoot
115553 && (!pTC || aTC[jj].nOvfl<pTC->nOvfl)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115554 ){
115555 pTC = &aTC[jj];
115556 }
115557 }
115558 assert( pTC );
115559
115560 /* At this point pTC points to the cheapest remaining token. */
115561 if( ii==0 ){
115562 if( pTC->nOvfl ){
115563 nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
115564 }else{
115565 /* TODO: Fix this so that the doclist need not be read twice. */
 
 
 
 
 
 
 
 
 
115566 Fts3PhraseToken *pToken = pTC->pToken;
115567 int nList = 0;
115568 char *pList = 0;
115569 rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
115570 if( rc==SQLITE_OK ){
115571 nDocEst = fts3DoclistCountDocids(1, pList, nList);
115572 }
115573 sqlite3_free(pList);
115574 if( rc==SQLITE_OK ){
115575 rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115576 pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115577 );
 
115578 }
115579 }
115580 }else{
115581 if( pTC->nOvfl>=(nDocEst*nDocSize) ){
115582 Fts3PhraseToken *pToken = pTC->pToken;
115583 rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
115584 fts3SegReaderCursorFree(pToken->pSegcsr);
115585 pToken->pSegcsr = 0;
115586 }
115587 nDocEst = 1 + (nDocEst/4);
115588 }
115589 pTC->pToken = 0;
115590 }
115591
115592 return rc;
115593 }
115594
115595 SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
 
 
 
 
 
 
 
 
 
 
 
 
115596 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115597 int rc = SQLITE_OK;
115598 int nToken = 0;
115599 int nOr = 0;
115600
115601 /* Allocate a MultiSegReader for each token in the expression. */
115602 fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
115603
115604 /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
115605 ** This call will eventually also be responsible for determining which
115606 ** tokens are 'deferred' until the document text is loaded into memory.
115607 **
115608 ** Each token in each phrase is dealt with using one of the following
115609 ** three strategies:
115610 **
115611 ** 1. Entire doclist loaded into memory as part of the
115612 ** fts3EvalStartReaders() call.
115613 **
115614 ** 2. Doclist loaded into memory incrementally, as part of each
115615 ** sqlite3Fts3EvalNext() call.
115616 **
115617 ** 3. Token doclist is never loaded. Instead, documents are loaded into
115618 ** memory and scanned for the token as part of the sqlite3Fts3EvalNext()
115619 ** call. This is known as a "deferred" token.
115620 */
115621
115622 /* If bOptOk is true, check if there are any tokens that should be deferred.
115623 */
115624 if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
115625 Fts3TokenAndCost *aTC;
115626 Fts3Expr **apOr;
115627 aTC = (Fts3TokenAndCost *)sqlite3_malloc(
115628 sizeof(Fts3TokenAndCost) * nToken
115629 + sizeof(Fts3Expr *) * nOr * 2
@@ -115635,11 +117913,11 @@
115635 }else{
115636 int ii;
115637 Fts3TokenAndCost *pTC = aTC;
115638 Fts3Expr **ppOr = apOr;
115639
115640 fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
115641 nToken = pTC-aTC;
115642 nOr = ppOr-apOr;
115643
115644 if( rc==SQLITE_OK ){
115645 rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
@@ -115650,25 +117928,50 @@
115650
115651 sqlite3_free(aTC);
115652 }
115653 }
115654
115655 fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
115656 return rc;
115657 }
115658
115659 static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
 
 
 
115660 if( pPhrase->doclist.bFreeList ){
115661 sqlite3_free(pPhrase->doclist.pList);
115662 }
115663 pPhrase->doclist.pList = 0;
115664 pPhrase->doclist.nList = 0;
115665 pPhrase->doclist.bFreeList = 0;
115666 }
115667
115668 static int fts3EvalNearTrim2(
115669 int nNear,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115670 char *aTmp, /* Temporary space to use */
115671 char **paPoslist, /* IN/OUT: Position list */
115672 int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
115673 Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
115674 ){
@@ -115696,10 +117999,176 @@
115696 }
115697
115698 return res;
115699 }
115700
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115701 static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
115702 int res = 1;
115703
115704 /* The following block runs if pExpr is the root of a NEAR query.
115705 ** For example, the query:
@@ -115717,11 +118186,11 @@
115717 ** | |
115718 ** "w" "x"
115719 **
115720 ** The right-hand child of a NEAR node is always a phrase. The
115721 ** left-hand child may be either a phrase or a NEAR node. There are
115722 ** no exceptions to this.
115723 */
115724 if( *pRc==SQLITE_OK
115725 && pExpr->eType==FTSQUERY_NEAR
115726 && pExpr->bEof==0
115727 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
@@ -115744,21 +118213,21 @@
115744 int nToken = p->pPhrase->nToken;
115745
115746 for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
115747 Fts3Phrase *pPhrase = p->pRight->pPhrase;
115748 int nNear = p->nNear;
115749 res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115750 }
115751
115752 aPoslist = pExpr->pRight->pPhrase->doclist.pList;
115753 nToken = pExpr->pRight->pPhrase->nToken;
115754 for(p=pExpr->pLeft; p && res; p=p->pLeft){
115755 int nNear = p->pParent->nNear;
115756 Fts3Phrase *pPhrase = (
115757 p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
115758 );
115759 res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115760 }
115761 }
115762
115763 sqlite3_free(aTmp);
115764 }
@@ -115765,132 +118234,33 @@
115765
115766 return res;
115767 }
115768
115769 /*
115770 ** This macro is used by the fts3EvalNext() function. The two arguments are
115771 ** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
115772 ** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
115773 ** it returns (i2 - i1). This allows the same code to be used for merging
115774 ** doclists in ascending or descending order.
 
 
 
 
115775 */
115776 #define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
115777
115778 static void fts3EvalNext(
115779 Fts3Cursor *pCsr,
115780 Fts3Expr *pExpr,
115781 int *pRc
115782 ){
115783 if( *pRc==SQLITE_OK ){
115784 assert( pExpr->bEof==0 );
115785 pExpr->bStart = 1;
115786
115787 switch( pExpr->eType ){
115788 case FTSQUERY_NEAR:
115789 case FTSQUERY_AND: {
115790 Fts3Expr *pLeft = pExpr->pLeft;
115791 Fts3Expr *pRight = pExpr->pRight;
115792 assert( !pLeft->bDeferred || !pRight->bDeferred );
115793 if( pLeft->bDeferred ){
115794 fts3EvalNext(pCsr, pRight, pRc);
115795 pExpr->iDocid = pRight->iDocid;
115796 pExpr->bEof = pRight->bEof;
115797 }else if( pRight->bDeferred ){
115798 fts3EvalNext(pCsr, pLeft, pRc);
115799 pExpr->iDocid = pLeft->iDocid;
115800 pExpr->bEof = pLeft->bEof;
115801 }else{
115802 fts3EvalNext(pCsr, pLeft, pRc);
115803 fts3EvalNext(pCsr, pRight, pRc);
115804
115805 while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
115806 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115807 if( iDiff==0 ) break;
115808 if( iDiff<0 ){
115809 fts3EvalNext(pCsr, pLeft, pRc);
115810 }else{
115811 fts3EvalNext(pCsr, pRight, pRc);
115812 }
115813 }
115814
115815 pExpr->iDocid = pLeft->iDocid;
115816 pExpr->bEof = (pLeft->bEof || pRight->bEof);
115817 }
115818 break;
115819 }
115820
115821 case FTSQUERY_OR: {
115822 Fts3Expr *pLeft = pExpr->pLeft;
115823 Fts3Expr *pRight = pExpr->pRight;
115824 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115825
115826 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
115827 assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
115828
115829 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115830 fts3EvalNext(pCsr, pLeft, pRc);
115831 }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
115832 fts3EvalNext(pCsr, pRight, pRc);
115833 }else{
115834 fts3EvalNext(pCsr, pLeft, pRc);
115835 fts3EvalNext(pCsr, pRight, pRc);
115836 }
115837
115838 pExpr->bEof = (pLeft->bEof && pRight->bEof);
115839 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115840 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115841 pExpr->iDocid = pLeft->iDocid;
115842 }else{
115843 pExpr->iDocid = pRight->iDocid;
115844 }
115845
115846 break;
115847 }
115848
115849 case FTSQUERY_NOT: {
115850 Fts3Expr *pLeft = pExpr->pLeft;
115851 Fts3Expr *pRight = pExpr->pRight;
115852
115853 if( pRight->bStart==0 ){
115854 fts3EvalNext(pCsr, pRight, pRc);
115855 assert( *pRc!=SQLITE_OK || pRight->bStart );
115856 }
115857
115858 fts3EvalNext(pCsr, pLeft, pRc);
115859 if( pLeft->bEof==0 ){
115860 while( !*pRc
115861 && !pRight->bEof
115862 && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
115863 ){
115864 fts3EvalNext(pCsr, pRight, pRc);
115865 }
115866 }
115867 pExpr->iDocid = pLeft->iDocid;
115868 pExpr->bEof = pLeft->bEof;
115869 break;
115870 }
115871
115872 default: {
115873 Fts3Phrase *pPhrase = pExpr->pPhrase;
115874 fts3EvalZeroPoslist(pPhrase);
115875 *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
115876 pExpr->iDocid = pPhrase->doclist.iDocid;
115877 break;
115878 }
115879 }
115880 }
115881 }
115882
115883 static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
115884 int bHit = 1;
115885 if( *pRc==SQLITE_OK ){
115886 switch( pExpr->eType ){
115887 case FTSQUERY_NEAR:
115888 case FTSQUERY_AND:
115889 bHit = (
115890 fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115891 && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
115892 && fts3EvalNearTest(pExpr, pRc)
115893 );
115894
115895 /* If the NEAR expression does not match any rows, zero the doclist for
115896 ** all phrases involved in the NEAR. This is because the snippet(),
@@ -115912,31 +118282,31 @@
115912 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
115913 ){
115914 Fts3Expr *p;
115915 for(p=pExpr; p->pPhrase==0; p=p->pLeft){
115916 if( p->pRight->iDocid==pCsr->iPrevId ){
115917 fts3EvalZeroPoslist(p->pRight->pPhrase);
115918 }
115919 }
115920 if( p->iDocid==pCsr->iPrevId ){
115921 fts3EvalZeroPoslist(p->pPhrase);
115922 }
115923 }
115924
115925 break;
115926
115927 case FTSQUERY_OR: {
115928 int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
115929 int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
115930 bHit = bHit1 || bHit2;
115931 break;
115932 }
115933
115934 case FTSQUERY_NOT:
115935 bHit = (
115936 fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
115937 && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
115938 );
115939 break;
115940
115941 default: {
115942 if( pCsr->pDeferred
@@ -115943,11 +118313,11 @@
115943 && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
115944 ){
115945 Fts3Phrase *pPhrase = pExpr->pPhrase;
115946 assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
115947 if( pExpr->bDeferred ){
115948 fts3EvalZeroPoslist(pPhrase);
115949 }
115950 *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
115951 bHit = (pPhrase->doclist.pList!=0);
115952 pExpr->iDocid = pCsr->iPrevId;
115953 }else{
@@ -115959,31 +118329,53 @@
115959 }
115960 return bHit;
115961 }
115962
115963 /*
115964 ** Return 1 if both of the following are true:
 
 
 
 
 
 
 
 
 
 
 
 
 
115965 **
115966 ** 1. *pRc is SQLITE_OK when this function returns, and
115967 **
115968 ** 2. After scanning the current FTS table row for the deferred tokens,
115969 ** it is determined that the row does not match the query.
115970 **
115971 ** Or, if no error occurs and it seems the current row does match the FTS
115972 ** query, return 0.
115973 */
115974 static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
115975 int rc = *pRc;
115976 int bMiss = 0;
115977 if( rc==SQLITE_OK ){
 
 
 
 
 
 
 
115978 if( pCsr->pDeferred ){
115979 rc = fts3CursorSeek(0, pCsr);
115980 if( rc==SQLITE_OK ){
115981 rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
115982 }
115983 }
115984 bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
 
 
115985 sqlite3Fts3FreeDeferredDoclists(pCsr);
115986 *pRc = rc;
115987 }
115988 return (rc==SQLITE_OK && bMiss);
115989 }
@@ -115990,11 +118382,11 @@
115990
115991 /*
115992 ** Advance to the next document that matches the FTS expression in
115993 ** Fts3Cursor.pExpr.
115994 */
115995 SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
115996 int rc = SQLITE_OK; /* Return Code */
115997 Fts3Expr *pExpr = pCsr->pExpr;
115998 assert( pCsr->isEof==0 );
115999 if( pExpr==0 ){
116000 pCsr->isEof = 1;
@@ -116002,23 +118394,23 @@
116002 do {
116003 if( pCsr->isRequireSeek==0 ){
116004 sqlite3_reset(pCsr->pStmt);
116005 }
116006 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116007 fts3EvalNext(pCsr, pExpr, &rc);
116008 pCsr->isEof = pExpr->bEof;
116009 pCsr->isRequireSeek = 1;
116010 pCsr->isMatchinfoNeeded = 1;
116011 pCsr->iPrevId = pExpr->iDocid;
116012 }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
116013 }
116014 return rc;
116015 }
116016
116017 /*
116018 ** Restart interation for expression pExpr so that the next call to
116019 ** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental
116020 ** loading or merging of phrase doclists for this iteration.
116021 **
116022 ** If *pRc is other than SQLITE_OK when this function is called, it is
116023 ** a no-op. If an error occurs within this function, *pRc is set to an
116024 ** SQLite error code before returning.
@@ -116030,19 +118422,20 @@
116030 ){
116031 if( pExpr && *pRc==SQLITE_OK ){
116032 Fts3Phrase *pPhrase = pExpr->pPhrase;
116033
116034 if( pPhrase ){
116035 fts3EvalZeroPoslist(pPhrase);
116036 if( pPhrase->bIncr ){
116037 sqlite3Fts3EvalPhraseCleanup(pPhrase);
116038 memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116039 *pRc = sqlite3Fts3EvalStart(pCsr, pExpr, 0);
116040 }else{
116041 pPhrase->doclist.pNextDocid = 0;
116042 pPhrase->doclist.iDocid = 0;
116043 }
 
 
 
116044 }
116045
116046 pExpr->iDocid = 0;
116047 pExpr->bEof = 0;
116048 pExpr->bStart = 0;
@@ -116145,18 +118538,18 @@
116145 /* Ensure the %_content statement is reset. */
116146 if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
116147 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116148
116149 /* Advance to the next document */
116150 fts3EvalNext(pCsr, pRoot, &rc);
116151 pCsr->isEof = pRoot->bEof;
116152 pCsr->isRequireSeek = 1;
116153 pCsr->isMatchinfoNeeded = 1;
116154 pCsr->iPrevId = pRoot->iDocid;
116155 }while( pCsr->isEof==0
116156 && pRoot->eType==FTSQUERY_NEAR
116157 && fts3EvalLoadDeferred(pCsr, &rc)
116158 );
116159
116160 if( rc==SQLITE_OK && pCsr->isEof==0 ){
116161 fts3EvalUpdateCounts(pRoot);
116162 }
@@ -116174,14 +118567,14 @@
116174 **
116175 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
116176 */
116177 fts3EvalRestart(pCsr, pRoot, &rc);
116178 do {
116179 fts3EvalNext(pCsr, pRoot, &rc);
116180 assert( pRoot->bEof==0 );
116181 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
116182 fts3EvalLoadDeferred(pCsr, &rc);
116183 }
116184 }
116185 return rc;
116186 }
116187
@@ -116225,12 +118618,12 @@
116225 int iCol;
116226
116227 if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
116228 assert( pCsr->nDoc>0 );
116229 for(iCol=0; iCol<pTab->nColumn; iCol++){
116230 aiOut[iCol*3 + 1] = pCsr->nDoc;
116231 aiOut[iCol*3 + 2] = pCsr->nDoc;
116232 }
116233 }else{
116234 rc = fts3EvalGatherStats(pCsr, pExpr);
116235 if( rc==SQLITE_OK ){
116236 assert( pExpr->aMI );
@@ -116308,18 +118701,32 @@
116308 */
116309 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
116310 if( pPhrase ){
116311 int i;
116312 sqlite3_free(pPhrase->doclist.aAll);
116313 fts3EvalZeroPoslist(pPhrase);
116314 memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116315 for(i=0; i<pPhrase->nToken; i++){
116316 fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
116317 pPhrase->aToken[i].pSegcsr = 0;
116318 }
116319 }
116320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116321
116322 #endif
116323
116324 /************** End of fts3.c ************************************************/
116325 /************** Begin file fts3_aux.c ****************************************/
@@ -116334,13 +118741,14 @@
116334 ** May you share freely, never taking more than you give.
116335 **
116336 ******************************************************************************
116337 **
116338 */
116339
116340 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
116341
 
 
116342
116343 typedef struct Fts3auxTable Fts3auxTable;
116344 typedef struct Fts3auxCursor Fts3auxCursor;
116345
116346 struct Fts3auxTable {
@@ -116875,10 +119283,12 @@
116875 /*
116876 ** Default span for NEAR operators.
116877 */
116878 #define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
116879
 
 
116880
116881 /*
116882 ** isNot:
116883 ** This variable is used by function getNextNode(). When getNextNode() is
116884 ** called, it sets ParseContext.isNot to true if the 'next node' is a
@@ -117576,10 +119986,11 @@
117576 ** Everything after this point is just test code.
117577 */
117578
117579 #ifdef SQLITE_TEST
117580
 
117581
117582 /*
117583 ** Function to query the hash-table of tokenizers (see README.tokenizers).
117584 */
117585 static int queryTestTokenizer(
@@ -117786,10 +120197,13 @@
117786 ** * The FTS3 module is being built into the core of
117787 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
117788 */
117789 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
117790
 
 
 
117791
117792
117793 /*
117794 ** Malloc and Free functions
117795 */
@@ -118166,11 +120580,14 @@
118166 ** * The FTS3 module is being built into the core of
118167 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
118168 */
118169 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
118170
118171
 
 
 
118172
118173
118174 /*
118175 ** Class derived from sqlite3_tokenizer
118176 */
@@ -118810,14 +121227,12 @@
118810 ** * The FTS3 module is being built into the core of
118811 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
118812 */
118813 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
118814
118815 #ifndef SQLITE_CORE
118816 SQLITE_EXTENSION_INIT1
118817 #endif
118818
118819
118820 /*
118821 ** Implementation of the SQL scalar function for accessing the underlying
118822 ** hash table. This function may be called as follows:
118823 **
@@ -118937,11 +121352,11 @@
118937 sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
118938 char **pzErr /* OUT: Set to malloced error message */
118939 ){
118940 int rc;
118941 char *z = (char *)zArg;
118942 int n;
118943 char *zCopy;
118944 char *zEnd; /* Pointer to nul-term of zCopy */
118945 sqlite3_tokenizer_module *m;
118946
118947 zCopy = sqlite3_mprintf("%s", zArg);
@@ -118989,10 +121404,12 @@
118989 }
118990
118991
118992 #ifdef SQLITE_TEST
118993
 
 
118994
118995 /*
118996 ** Implementation of a special SQL scalar function for testing tokenizers
118997 ** designed to be used in concert with the Tcl testing framework. This
118998 ** function must be called with two arguments:
@@ -119300,11 +121717,14 @@
119300 ** * The FTS3 module is being built into the core of
119301 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
119302 */
119303 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
119304
119305
 
 
 
119306
119307
119308 typedef struct simple_tokenizer {
119309 sqlite3_tokenizer base;
119310 char delim[128]; /* flag ASCII delimiters */
@@ -119526,10 +121946,13 @@
119526 ** code in fts3.c.
119527 */
119528
119529 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
119530
 
 
 
119531
119532 /*
119533 ** When full-text index nodes are loaded from disk, the buffer that they
119534 ** are loaded into has the following number of bytes of padding at the end
119535 ** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
@@ -120750,10 +123173,11 @@
120750 pReader->pOffsetList = 0;
120751 }else{
120752 pReader->pOffsetList = p;
120753 }
120754 }else{
 
120755
120756 /* Pointer p currently points at the first byte of an offset list. The
120757 ** following block advances it to point one byte past the end of
120758 ** the same offset list. */
120759 while( 1 ){
@@ -120778,17 +123202,19 @@
120778 */
120779 if( ppOffsetList ){
120780 *ppOffsetList = pReader->pOffsetList;
120781 *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
120782 }
 
 
120783
120784 /* If there are no more entries in the doclist, set pOffsetList to
120785 ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
120786 ** Fts3SegReader.pOffsetList to point to the next offset list before
120787 ** returning.
120788 */
120789 if( p>=&pReader->aDoclist[pReader->nDoclist] ){
120790 pReader->pOffsetList = 0;
120791 }else{
120792 rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
120793 if( rc==SQLITE_OK ){
120794 sqlite3_int64 iDelta;
@@ -120823,11 +123249,11 @@
120823 for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
120824 Fts3SegReader *pReader = pMsr->apSegment[ii];
120825 if( !fts3SegReaderIsPending(pReader)
120826 && !fts3SegReaderIsRootOnly(pReader)
120827 ){
120828 int jj;
120829 for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
120830 int nBlob;
120831 rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
120832 if( rc!=SQLITE_OK ) break;
120833 if( (nBlob+35)>pgsz ){
@@ -121768,55 +124194,31 @@
121768
121769 *ppList = pList;
121770 *pnList = nList;
121771 }
121772
121773 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
121774 Fts3Table *p, /* Virtual table handle */
121775 Fts3MultiSegReader *pCsr, /* Cursor object */
121776 int iCol, /* Column to match on. */
121777 const char *zTerm, /* Term to iterate through a doclist for */
121778 int nTerm /* Number of bytes in zTerm */
 
 
 
 
 
121779 ){
121780 int i;
121781 int nSegment = pCsr->nSegment;
121782 int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
121783 p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
121784 );
121785
121786 assert( pCsr->pFilter==0 );
121787 assert( zTerm && nTerm>0 );
121788
121789 /* Advance each segment iterator until it points to the term zTerm/nTerm. */
121790 for(i=0; i<nSegment; i++){
121791 Fts3SegReader *pSeg = pCsr->apSegment[i];
121792 do {
121793 int rc = fts3SegReaderNext(p, pSeg, 1);
121794 if( rc!=SQLITE_OK ) return rc;
121795 }while( fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
121796 }
121797 fts3SegReaderSort(pCsr->apSegment, nSegment, nSegment, fts3SegReaderCmp);
121798
121799 /* Determine how many of the segments actually point to zTerm/nTerm. */
121800 for(i=0; i<nSegment; i++){
121801 Fts3SegReader *pSeg = pCsr->apSegment[i];
121802 if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
121803 break;
121804 }
121805 }
121806 pCsr->nAdvance = i;
121807
121808 /* Advance each of the segments to point to the first docid. */
121809 for(i=0; i<pCsr->nAdvance; i++){
121810 int rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
121811 if( rc!=SQLITE_OK ) return rc;
121812 }
121813 fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
121814
121815 assert( iCol<0 || iCol<p->nColumn );
121816 pCsr->iColFilter = iCol;
121817
121818 return SQLITE_OK;
121819 }
121820
121821 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
121822 Fts3Table *p, /* Virtual table handle */
@@ -121866,52 +124268,138 @@
121866 if( pMsr->iColFilter>=0 ){
121867 fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
121868 }
121869
121870 if( nList>0 ){
 
 
 
 
 
 
 
 
121871 *piDocid = iDocid;
121872 *paPoslist = pList;
121873 *pnPoslist = nList;
121874 break;
121875 }
121876 }
121877
121878 }
121879
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121880 return SQLITE_OK;
121881 }
121882
121883 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
121884 Fts3Table *p, /* Virtual table handle */
121885 Fts3MultiSegReader *pCsr, /* Cursor object */
121886 Fts3SegFilter *pFilter /* Restrictions on range of iteration */
121887 ){
121888 int i;
121889
121890 /* Initialize the cursor object */
121891 pCsr->pFilter = pFilter;
121892
121893 /* If the Fts3SegFilter defines a specific term (or term prefix) to search
121894 ** for, then advance each segment iterator until it points to a term of
121895 ** equal or greater value than the specified term. This prevents many
121896 ** unnecessary merge/sort operations for the case where single segment
121897 ** b-tree leaf nodes contain more than one term.
121898 */
121899 for(i=0; i<pCsr->nSegment; i++){
121900 int nTerm = pFilter->nTerm;
121901 const char *zTerm = pFilter->zTerm;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121902 Fts3SegReader *pSeg = pCsr->apSegment[i];
121903 do {
121904 int rc = fts3SegReaderNext(p, pSeg, 0);
121905 if( rc!=SQLITE_OK ) return rc;
121906 }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
121907 }
121908 fts3SegReaderSort(
121909 pCsr->apSegment, pCsr->nSegment, pCsr->nSegment, fts3SegReaderCmp);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121910
121911 return SQLITE_OK;
121912 }
 
121913
121914 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
121915 Fts3Table *p, /* Virtual table handle */
121916 Fts3MultiSegReader *pCsr /* Cursor object */
121917 ){
@@ -121981,13 +124469,18 @@
121981 assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
121982 if( nMerge==1
121983 && !isIgnoreEmpty
121984 && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
121985 ){
121986 pCsr->aDoclist = apSegment[0]->aDoclist;
121987 pCsr->nDoclist = apSegment[0]->nDoclist;
121988 rc = SQLITE_ROW;
 
 
 
 
 
 
121989 }else{
121990 int nDoclist = 0; /* Size of doclist */
121991 sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */
121992
121993 /* The current term of the first nMerge entries in the array
@@ -122717,10 +125210,12 @@
122717 ******************************************************************************
122718 */
122719
122720 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
122721
 
 
122722
122723 /*
122724 ** Characters that may appear in the second argument to matchinfo().
122725 */
122726 #define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */
@@ -123725,11 +126220,11 @@
123725 if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
123726 break;
123727
123728 case FTS3_MATCHINFO_NDOC:
123729 if( bGlobal ){
123730 sqlite3_int64 nDoc;
123731 rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
123732 pInfo->aMatchinfo[0] = (u32)nDoc;
123733 }
123734 break;
123735
@@ -124304,10 +126799,12 @@
124304 #ifndef SQLITE_CORE
124305 SQLITE_EXTENSION_INIT1
124306 #else
124307 #endif
124308
 
 
124309
124310 #ifndef SQLITE_AMALGAMATION
124311 #include "sqlite3rtree.h"
124312 typedef sqlite3_int64 i64;
124313 typedef unsigned char u8;
@@ -125620,11 +128117,11 @@
125620 */
125621 static float cellArea(Rtree *pRtree, RtreeCell *p){
125622 float area = 1.0;
125623 int ii;
125624 for(ii=0; ii<(pRtree->nDim*2); ii+=2){
125625 area = area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
125626 }
125627 return area;
125628 }
125629
125630 /*
@@ -125633,11 +128130,11 @@
125633 */
125634 static float cellMargin(Rtree *pRtree, RtreeCell *p){
125635 float margin = 0.0;
125636 int ii;
125637 for(ii=0; ii<(pRtree->nDim*2); ii+=2){
125638 margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
125639 }
125640 return margin;
125641 }
125642
125643 /*
@@ -125718,11 +128215,11 @@
125718
125719 if( x2<x1 ){
125720 o = 0.0;
125721 break;
125722 }else{
125723 o = o * (x2-x1);
125724 }
125725 }
125726 overlap += o;
125727 }
125728 }
@@ -125737,16 +128234,16 @@
125737 RtreeCell *pInsert,
125738 RtreeCell *aCell,
125739 int nCell,
125740 int iExclude
125741 ){
125742 float before;
125743 float after;
125744 before = cellOverlap(pRtree, p, aCell, nCell, iExclude);
125745 cellUnion(pRtree, p, pInsert);
125746 after = cellOverlap(pRtree, p, aCell, nCell, iExclude);
125747 return after-before;
125748 }
125749 #endif
125750
125751
125752 /*
@@ -125764,15 +128261,15 @@
125764 RtreeNode *pNode;
125765 rc = nodeAcquire(pRtree, 1, 0, &pNode);
125766
125767 for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
125768 int iCell;
125769 sqlite3_int64 iBest;
125770
125771 float fMinGrowth;
125772 float fMinArea;
125773 float fMinOverlap;
125774
125775 int nCell = NCELL(pNode);
125776 RtreeCell cell;
125777 RtreeNode *pChild;
125778
@@ -126198,13 +128695,13 @@
126198 ){
126199 int **aaSorted;
126200 int *aSpare;
126201 int ii;
126202
126203 int iBestDim;
126204 int iBestSplit;
126205 float fBestMargin;
126206
126207 int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
126208
126209 aaSorted = (int **)sqlite3_malloc(nByte);
126210 if( !aaSorted ){
@@ -126222,13 +128719,13 @@
126222 SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);
126223 }
126224
126225 for(ii=0; ii<pRtree->nDim; ii++){
126226 float margin = 0.0;
126227 float fBestOverlap;
126228 float fBestArea;
126229 int iBestLeft;
126230 int nLeft;
126231
126232 for(
126233 nLeft=RTREE_MINCELLS(pRtree);
126234 nLeft<=(nCell-RTREE_MINCELLS(pRtree));
@@ -126539,11 +129036,11 @@
126539 static int deleteCell(Rtree *, RtreeNode *, int, int);
126540
126541 static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
126542 int rc;
126543 int rc2;
126544 RtreeNode *pParent;
126545 int iCell;
126546
126547 assert( pNode->nRef==1 );
126548
126549 /* Remove the entry in the parent cell. */
@@ -126687,23 +129184,23 @@
126687 }else{
126688 nodeGetCell(pRtree, pNode, ii, &aCell[ii]);
126689 }
126690 aOrder[ii] = ii;
126691 for(iDim=0; iDim<pRtree->nDim; iDim++){
126692 aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);
126693 aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);
126694 }
126695 }
126696 for(iDim=0; iDim<pRtree->nDim; iDim++){
126697 aCenterCoord[iDim] = aCenterCoord[iDim]/((float)nCell*2.0);
126698 }
126699
126700 for(ii=0; ii<nCell; ii++){
126701 aDistance[ii] = 0.0;
126702 for(iDim=0; iDim<pRtree->nDim; iDim++){
126703 float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) -
126704 DCOORD(aCell[ii].aCoord[iDim*2]);
126705 aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
126706 }
126707 }
126708
126709 SortByDistance(aOrder, nCell, aDistance, aSpare);
@@ -126798,14 +129295,14 @@
126798 nodeGetCell(pRtree, pNode, ii, &cell);
126799
126800 /* Find a node to store this cell in. pNode->iNode currently contains
126801 ** the height of the sub-tree headed by the cell.
126802 */
126803 rc = ChooseLeaf(pRtree, &cell, pNode->iNode, &pInsert);
126804 if( rc==SQLITE_OK ){
126805 int rc2;
126806 rc = rtreeInsertCell(pRtree, pInsert, &cell, pNode->iNode);
126807 rc2 = nodeRelease(pRtree, pInsert);
126808 if( rc==SQLITE_OK ){
126809 rc = rc2;
126810 }
126811 }
@@ -127190,11 +129687,11 @@
127190 int isCreate /* True for xCreate, false for xConnect */
127191 ){
127192 int rc;
127193 char *zSql;
127194 if( isCreate ){
127195 int iPageSize;
127196 zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
127197 rc = getIntFromStmt(db, zSql, &iPageSize);
127198 if( rc==SQLITE_OK ){
127199 pRtree->iNodeSize = iPageSize-64;
127200 if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
@@ -127518,10 +130015,11 @@
127518 #include <unicode/utypes.h>
127519 #include <unicode/uregex.h>
127520 #include <unicode/ustring.h>
127521 #include <unicode/ucol.h>
127522
 
127523
127524 #ifndef SQLITE_CORE
127525 SQLITE_EXTENSION_INIT1
127526 #else
127527 #endif
@@ -127993,19 +130491,20 @@
127993 ** May you find forgiveness for yourself and forgive others.
127994 ** May you share freely, never taking more than you give.
127995 **
127996 *************************************************************************
127997 ** This file implements a tokenizer for fts3 based on the ICU library.
127998 **
127999 ** $Id: fts3_icu.c,v 1.3 2008/09/01 18:34:20 danielk1977 Exp $
128000 */
128001
128002 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
128003 #ifdef SQLITE_ENABLE_ICU
128004
 
 
128005
128006 #include <unicode/ubrk.h>
 
 
128007 #include <unicode/utf16.h>
128008
128009 typedef struct IcuTokenizer IcuTokenizer;
128010 typedef struct IcuCursor IcuCursor;
128011
128012
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.8. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -385,23 +385,29 @@
385 /*
386 ** Exactly one of the following macros must be defined in order to
387 ** specify which memory allocation subsystem to use.
388 **
389 ** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
390 ** SQLITE_WIN32_MALLOC // Use Win32 native heap API
391 ** SQLITE_MEMDEBUG // Debugging version of system malloc()
392 **
393 ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
394 ** assert() macro is enabled, each call into the Win32 native heap subsystem
395 ** will cause HeapValidate to be called. If heap validation should fail, an
396 ** assertion will be triggered.
397 **
398 ** (Historical note: There used to be several other options, but we've
399 ** pared it down to just these two.)
400 **
401 ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
402 ** the default.
403 */
404 #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
405 # error "At most one of the following compile-time configuration options\
406 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"
407 #endif
408 #if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
409 # define SQLITE_SYSTEM_MALLOC 1
410 #endif
411
412 /*
413 ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
@@ -648,13 +654,13 @@
654 **
655 ** See also: [sqlite3_libversion()],
656 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657 ** [sqlite_version()] and [sqlite_source_id()].
658 */
659 #define SQLITE_VERSION "3.7.8"
660 #define SQLITE_VERSION_NUMBER 3007008
661 #define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
662
663 /*
664 ** CAPI3REF: Run-Time Library Version Numbers
665 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
666 **
@@ -851,11 +857,11 @@
857 ** semicolon-separate SQL statements passed into its 2nd argument,
858 ** in the context of the [database connection] passed in as its 1st
859 ** argument. ^If the callback function of the 3rd argument to
860 ** sqlite3_exec() is not NULL, then it is invoked for each result row
861 ** coming out of the evaluated SQL statements. ^The 4th argument to
862 ** sqlite3_exec() is relayed through to the 1st argument of each
863 ** callback invocation. ^If the callback pointer to sqlite3_exec()
864 ** is NULL, then no callback is ever invoked and result rows are
865 ** ignored.
866 **
867 ** ^If an error occurs while evaluating the SQL statements passed into
@@ -1282,20 +1288,52 @@
1288 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
1289 ** VFSes do not need this signal and should silently ignore this opcode.
1290 ** Applications should not call [sqlite3_file_control()] with this
1291 ** opcode as doing so may disrupt the operation of the specialized VFSes
1292 ** that do require it.
1293 **
1294 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
1295 ** retry counts and intervals for certain disk I/O operations for the
1296 ** windows [VFS] in order to work to provide robustness against
1297 ** anti-virus programs. By default, the windows VFS will retry file read,
1298 ** file write, and file delete opertions up to 10 times, with a delay
1299 ** of 25 milliseconds before the first retry and with the delay increasing
1300 ** by an additional 25 milliseconds with each subsequent retry. This
1301 ** opcode allows those to values (10 retries and 25 milliseconds of delay)
1302 ** to be adjusted. The values are changed for all database connections
1303 ** within the same process. The argument is a pointer to an array of two
1304 ** integers where the first integer i the new retry count and the second
1305 ** integer is the delay. If either integer is negative, then the setting
1306 ** is not changed but instead the prior value of that setting is written
1307 ** into the array entry, allowing the current retry settings to be
1308 ** interrogated. The zDbName parameter is ignored.
1309 **
1310 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
1311 ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
1312 ** write ahead log and shared memory files used for transaction control
1313 ** are automatically deleted when the latest connection to the database
1314 ** closes. Setting persistent WAL mode causes those files to persist after
1315 ** close. Persisting the files is useful when other processes that do not
1316 ** have write permission on the directory containing the database file want
1317 ** to read the database file, as the WAL and shared memory files must exist
1318 ** in order for the database to be readable. The fourth parameter to
1319 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
1320 ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
1321 ** WAL mode. If the integer is -1, then it is overwritten with the current
1322 ** WAL persistence setting.
1323 **
1324 */
1325 #define SQLITE_FCNTL_LOCKSTATE 1
1326 #define SQLITE_GET_LOCKPROXYFILE 2
1327 #define SQLITE_SET_LOCKPROXYFILE 3
1328 #define SQLITE_LAST_ERRNO 4
1329 #define SQLITE_FCNTL_SIZE_HINT 5
1330 #define SQLITE_FCNTL_CHUNK_SIZE 6
1331 #define SQLITE_FCNTL_FILE_POINTER 7
1332 #define SQLITE_FCNTL_SYNC_OMITTED 8
1333 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
1334 #define SQLITE_FCNTL_PERSIST_WAL 10
1335
1336 /*
1337 ** CAPI3REF: Mutex Handle
1338 **
1339 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -1443,11 +1481,11 @@
1481 ** The xSleep() method causes the calling thread to sleep for at
1482 ** least the number of microseconds given. ^The xCurrentTime()
1483 ** method returns a Julian Day Number for the current date and time as
1484 ** a floating point value.
1485 ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
1486 ** Day Number multiplied by 86400000 (the number of milliseconds in
1487 ** a 24-hour day).
1488 ** ^SQLite will use the xCurrentTimeInt64() method to get the current
1489 ** date and time if that method is available (if iVersion is 2 or
1490 ** greater and the function pointer is not NULL) and will fall back
1491 ** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
@@ -1719,20 +1757,14 @@
1757 ** also used during testing of SQLite in order to specify an alternative
1758 ** memory allocator that simulates memory out-of-memory conditions in
1759 ** order to verify that SQLite recovers gracefully from such
1760 ** conditions.
1761 **
1762 ** The xMalloc, xRealloc, and xFree methods must work like the
1763 ** malloc(), realloc() and free() functions from the standard C library.
1764 ** ^SQLite guarantees that the second argument to
 
 
 
1765 ** xRealloc is always a value returned by a prior call to xRoundup.
 
 
 
1766 **
1767 ** xSize should return the allocated size of a memory allocation
1768 ** previously obtained from xMalloc or xRealloc. The allocated size
1769 ** is always at least as big as the requested size but may be larger.
1770 **
@@ -1881,11 +1913,11 @@
1913 ** scratch memory beyond what is provided by this configuration option, then
1914 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1915 **
1916 ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
1917 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1918 ** the database page cache with the default page cache implementation.
1919 ** This configuration should not be used if an application-define page
1920 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1921 ** There are three arguments to this option: A pointer to 8-byte aligned
1922 ** memory, the size of each page buffer (sz), and the number of pages (N).
1923 ** The sz argument should be the size of the largest database page
@@ -2979,16 +3011,16 @@
3011 ** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
3012 **
3013 ** ^If [URI filename] interpretation is enabled, and the filename argument
3014 ** begins with "file:", then the filename is interpreted as a URI. ^URI
3015 ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
3016 ** set in the fourth argument to sqlite3_open_v2(), or if it has
3017 ** been enabled globally using the [SQLITE_CONFIG_URI] option with the
3018 ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
3019 ** As of SQLite version 3.7.7, URI filename interpretation is turned off
3020 ** by default, but future releases of SQLite might enable URI filename
3021 ** interpretation by default. See "[URI filenames]" for additional
3022 ** information.
3023 **
3024 ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
3025 ** authority, then it must be either an empty string or the string
3026 ** "localhost". ^If the authority is not an empty string or "localhost", an
@@ -3803,11 +3835,11 @@
3835 ** [extended result codes] might be returned as well.
3836 **
3837 ** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
3838 ** database locks it needs to do its job. ^If the statement is a [COMMIT]
3839 ** or occurs outside of an explicit transaction, then you can retry the
3840 ** statement. If the statement is not a [COMMIT] and occurs within an
3841 ** explicit transaction then you should rollback the transaction before
3842 ** continuing.
3843 **
3844 ** ^[SQLITE_DONE] means that the statement has finished executing
3845 ** successfully. sqlite3_step() should not be called again on this virtual
@@ -4082,11 +4114,11 @@
4114
4115 /*
4116 ** CAPI3REF: Destroy A Prepared Statement Object
4117 **
4118 ** ^The sqlite3_finalize() function is called to delete a [prepared statement].
4119 ** ^If the most recent evaluation of the statement encountered no errors
4120 ** or if the statement is never been evaluated, then sqlite3_finalize() returns
4121 ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
4122 ** sqlite3_finalize(S) returns the appropriate [error code] or
4123 ** [extended error code].
4124 **
@@ -5996,11 +6028,11 @@
6028 ** versions of these routines, it should at least provide stubs that always
6029 ** return true so that one does not get spurious assertion failures.
6030 **
6031 ** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
6032 ** the routine should return 1. This seems counter-intuitive since
6033 ** clearly the mutex cannot be held if it does not exist. But
6034 ** the reason the mutex does not exist is because the build is not
6035 ** using mutexes. And we do not want the assert() containing the
6036 ** call to sqlite3_mutex_held() to fail, so a non-zero return is
6037 ** the appropriate thing to do. ^The sqlite3_mutex_notheld()
6038 ** interface should also return 1 when given a NULL pointer.
@@ -6119,11 +6151,12 @@
6151 #define SQLITE_TESTCTRL_RESERVE 14
6152 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15
6153 #define SQLITE_TESTCTRL_ISKEYWORD 16
6154 #define SQLITE_TESTCTRL_PGHDRSZ 17
6155 #define SQLITE_TESTCTRL_SCRATCHMALLOC 18
6156 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 19
6157 #define SQLITE_TESTCTRL_LAST 19
6158
6159 /*
6160 ** CAPI3REF: SQLite Runtime Status
6161 **
6162 ** ^This interface is used to retrieve runtime status information
@@ -6505,11 +6538,11 @@
6538 ** [[the xFetch() page cache methods]]
6539 ** The xFetch() method locates a page in the cache and returns a pointer to
6540 ** the page, or a NULL pointer.
6541 ** A "page", in this context, means a buffer of szPage bytes aligned at an
6542 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
6543 ** minimum key value is 1. After it has been retrieved using xFetch, the page
6544 ** is considered to be "pinned".
6545 **
6546 ** If the requested page is already in the page cache, then the page cache
6547 ** implementation must return a pointer to the page buffer with its content
6548 ** intact. If the requested page is not already in the cache, then the
@@ -7599,10 +7632,18 @@
7632 */
7633 #ifndef SQLITE_TEMP_STORE
7634 # define SQLITE_TEMP_STORE 1
7635 #endif
7636
7637 /*
7638 ** If all temporary storage is in-memory, then omit the external merge-sort
7639 ** logic since it is superfluous.
7640 */
7641 #if SQLITE_TEMP_STORE==3 && !defined(SQLITE_OMIT_MERGE_SORT)
7642 # define SQLITE_OMIT_MERGE_SORT
7643 #endif
7644
7645 /*
7646 ** GCC does not define the offsetof() macro so we'll have to do it
7647 ** ourselves.
7648 */
7649 #ifndef offsetof
@@ -7941,10 +7982,11 @@
7982 #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
7983 #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
7984 #define BTREE_MEMORY 4 /* This is an in-memory DB */
7985 #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
7986 #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
7987 #define BTREE_SORTER 32 /* Used as accumulator in external merge sort */
7988
7989 SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
7990 SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
7991 SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
7992 SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
@@ -8143,10 +8185,11 @@
8185 ** or VDBE. The VDBE implements an abstract machine that runs a
8186 ** simple program to access and modify the underlying database.
8187 */
8188 #ifndef _SQLITE_VDBE_H_
8189 #define _SQLITE_VDBE_H_
8190 /* #include <stdio.h> */
8191
8192 /*
8193 ** A single VDBE is an opaque structure named "Vdbe". Only routines
8194 ** in the source file sqliteVdbe.c are allowed to see the insides
8195 ** of this structure.
@@ -8186,10 +8229,11 @@
8229 Mem *pMem; /* Used when p4type is P4_MEM */
8230 VTable *pVtab; /* Used when p4type is P4_VTAB */
8231 KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
8232 int *ai; /* Used when p4type is P4_INTARRAY */
8233 SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
8234 int (*xAdvance)(BtCursor *, int *);
8235 } p4;
8236 #ifdef SQLITE_DEBUG
8237 char *zComment; /* Comment to improve readability */
8238 #endif
8239 #ifdef VDBE_PROFILE
@@ -8241,10 +8285,11 @@
8285 #define P4_REAL (-12) /* P4 is a 64-bit floating point value */
8286 #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
8287 #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
8288 #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
8289 #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
8290 #define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
8291
8292 /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
8293 ** is made. That copy is freed when the Vdbe is finalized. But if the
8294 ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still
8295 ** gets freed when the Vdbe is finalized so it still should be obtained
@@ -8354,89 +8399,89 @@
8399 #define OP_ReadCookie 35
8400 #define OP_SetCookie 36
8401 #define OP_VerifyCookie 37
8402 #define OP_OpenRead 38
8403 #define OP_OpenWrite 39
8404 #define OP_OpenSorter 40
8405 #define OP_OpenAutoindex 41
8406 #define OP_OpenEphemeral 42
8407 #define OP_OpenPseudo 43
8408 #define OP_Close 44
8409 #define OP_SeekLt 45
8410 #define OP_SeekLe 46
8411 #define OP_SeekGe 47
8412 #define OP_SeekGt 48
8413 #define OP_Seek 49
8414 #define OP_NotFound 50
8415 #define OP_Found 51
8416 #define OP_IsUnique 52
8417 #define OP_NotExists 53
8418 #define OP_Sequence 54
8419 #define OP_NewRowid 55
8420 #define OP_Insert 56
8421 #define OP_InsertInt 57
8422 #define OP_Delete 58
8423 #define OP_ResetCount 59
8424 #define OP_RowKey 60
8425 #define OP_RowData 61
8426 #define OP_Rowid 62
8427 #define OP_NullRow 63
8428 #define OP_Last 64
8429 #define OP_Sort 65
8430 #define OP_Rewind 66
8431 #define OP_Prev 67
8432 #define OP_Next 70
8433 #define OP_IdxInsert 71
8434 #define OP_IdxDelete 72
8435 #define OP_IdxRowid 81
8436 #define OP_IdxLT 92
8437 #define OP_IdxGE 95
8438 #define OP_Destroy 96
8439 #define OP_Clear 97
8440 #define OP_CreateIndex 98
8441 #define OP_CreateTable 99
8442 #define OP_ParseSchema 100
8443 #define OP_LoadAnalysis 101
8444 #define OP_DropTable 102
8445 #define OP_DropIndex 103
8446 #define OP_DropTrigger 104
8447 #define OP_IntegrityCk 105
8448 #define OP_RowSetAdd 106
8449 #define OP_RowSetRead 107
8450 #define OP_RowSetTest 108
8451 #define OP_Program 109
8452 #define OP_Param 110
8453 #define OP_FkCounter 111
8454 #define OP_FkIfZero 112
8455 #define OP_MemMax 113
8456 #define OP_IfPos 114
8457 #define OP_IfNeg 115
8458 #define OP_IfZero 116
8459 #define OP_AggStep 117
8460 #define OP_AggFinal 118
8461 #define OP_Checkpoint 119
8462 #define OP_JournalMode 120
8463 #define OP_Vacuum 121
8464 #define OP_IncrVacuum 122
8465 #define OP_Expire 123
8466 #define OP_TableLock 124
8467 #define OP_VBegin 125
8468 #define OP_VCreate 126
8469 #define OP_VDestroy 127
8470 #define OP_VOpen 128
8471 #define OP_VFilter 129
8472 #define OP_VColumn 131
8473 #define OP_VNext 132
8474 #define OP_VRename 133
8475 #define OP_VUpdate 134
8476 #define OP_Pagecount 135
8477 #define OP_MaxPgcnt 136
8478 #define OP_Trace 137
8479 #define OP_Noop 138
8480 #define OP_Explain 139
8481
8482 /* The following opcode values are never used */
8483 #define OP_NotUsed_140 140
8484
8485
8486 /* Properties such as "out2" or "jump" that are specified in
8487 ** comments following the "case" for each opcode in the vdbe.c
@@ -8453,23 +8498,23 @@
8498 /* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
8499 /* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
8500 /* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
8501 /* 24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
8502 /* 32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
8503 /* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,\
8504 /* 48 */ 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02,\
8505 /* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,\
8506 /* 64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x01, 0x08,\
8507 /* 72 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8508 /* 80 */ 0x15, 0x02, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
8509 /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
8510 /* 96 */ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\
8511 /* 104 */ 0x00, 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00,\
8512 /* 112 */ 0x01, 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
8513 /* 120 */ 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\
8514 /* 128 */ 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x02,\
8515 /* 136 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
8516 /* 144 */ 0x04, 0x04,}
8517
8518 /************** End of opcodes.h *********************************************/
8519 /************** Continuing where we left off in vdbe.h ***********************/
8520
@@ -8484,13 +8529,13 @@
8529 SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
8530 SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
8531 SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
8532 SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
8533 SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
8534 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
8535 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
8536 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
8537 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
8538 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
8539 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
8540 SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
8541 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
@@ -8608,10 +8653,11 @@
8653 ** NOTE: These values must match the corresponding BTREE_ values in btree.h.
8654 */
8655 #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
8656 #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
8657 #define PAGER_MEMORY 0x0004 /* In-memory database */
8658 #define PAGER_SORTER 0x0020 /* Accumulator in external merge sort */
8659
8660 /*
8661 ** Valid values for the second argument to sqlite3PagerLockingMode().
8662 */
8663 #define PAGER_LOCKINGMODE_QUERY -1
@@ -8703,10 +8749,13 @@
8749 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
8750 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
8751 SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
8752 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
8753 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
8754 #ifndef SQLITE_OMIT_MERGE_SORT
8755 SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager*);
8756 #endif
8757
8758 /* Functions used to truncate the database file. */
8759 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
8760
8761 #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
@@ -9556,10 +9605,12 @@
9605 #define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */
9606 #define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
9607 #define SQLITE_IndexCover 0x10 /* Disable index covering table */
9608 #define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
9609 #define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
9610 #define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */
9611 #define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */
9612 #define SQLITE_OptMask 0xff /* Mask of all disablable opts */
9613
9614 /*
9615 ** Possible values for the sqlite.magic field.
9616 ** The numbers are obtained at random and have no special meaning, other
@@ -10447,10 +10498,11 @@
10498 Table *pTab; /* An SQL table corresponding to zName */
10499 Select *pSelect; /* A SELECT statement used in place of a table name */
10500 u8 isPopulated; /* Temporary table associated with SELECT is populated */
10501 u8 jointype; /* Type of join between this able and the previous */
10502 u8 notIndexed; /* True if there is a NOT INDEXED clause */
10503 u8 isCorrelated; /* True if sub-query is correlated */
10504 #ifndef SQLITE_OMIT_EXPLAIN
10505 u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
10506 #endif
10507 int iCursor; /* The VDBE cursor number used to access this table */
10508 Expr *pOn; /* The ON clause of a join */
@@ -10566,10 +10618,11 @@
10618 struct WhereInfo {
10619 Parse *pParse; /* Parsing and code generating context */
10620 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
10621 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
10622 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
10623 u8 eDistinct;
10624 SrcList *pTabList; /* List of tables in the join */
10625 int iTop; /* The very beginning of the WHERE loop */
10626 int iContinue; /* Jump here to continue with next record */
10627 int iBreak; /* Jump here to break out of the loop */
10628 int nLevel; /* Number of nested loop */
@@ -10577,10 +10630,13 @@
10630 double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
10631 double nRowOut; /* Estimated number of output rows */
10632 WhereLevel a[1]; /* Information about each nest loop in WHERE */
10633 };
10634
10635 #define WHERE_DISTINCT_UNIQUE 1
10636 #define WHERE_DISTINCT_ORDERED 2
10637
10638 /*
10639 ** A NameContext defines a context in which to resolve table and column
10640 ** names. The context consists of a list of tables (the pSrcList) field and
10641 ** a list of named expression (pEList). The named expression list may
10642 ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
@@ -11053,10 +11109,11 @@
11109 int isPCacheInit; /* True after malloc is initialized */
11110 sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
11111 int nRefInitMutex; /* Number of users of pInitMutex */
11112 void (*xLog)(void*,int,const char*); /* Function for logging */
11113 void *pLogArg; /* First argument to xLog() */
11114 int bLocaltimeFault; /* True to fail localtime() calls */
11115 };
11116
11117 /*
11118 ** Context pointer passed down through the tree-walk.
11119 */
@@ -11337,11 +11394,11 @@
11394 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
11395 SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
11396 #endif
11397 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
11398 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11399 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
11400 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
11401 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
11402 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
11403 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
11404 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
@@ -12013,10 +12070,11 @@
12070 0, /* isPCacheInit */
12071 0, /* pInitMutex */
12072 0, /* nRefInitMutex */
12073 0, /* xLog */
12074 0, /* pLogArg */
12075 0, /* bLocaltimeFault */
12076 };
12077
12078
12079 /*
12080 ** Hash table for global functions - functions common to all
@@ -12321,10 +12379,13 @@
12379 #ifdef SQLITE_OMIT_LOOKASIDE
12380 "OMIT_LOOKASIDE",
12381 #endif
12382 #ifdef SQLITE_OMIT_MEMORYDB
12383 "OMIT_MEMORYDB",
12384 #endif
12385 #ifdef SQLITE_OMIT_MERGE_SORT
12386 "OMIT_MERGE_SORT",
12387 #endif
12388 #ifdef SQLITE_OMIT_OR_OPTIMIZATION
12389 "OMIT_OR_OPTIMIZATION",
12390 #endif
12391 #ifdef SQLITE_OMIT_PAGER_PRAGMAS
@@ -12387,10 +12448,13 @@
12448 #ifdef SQLITE_OMIT_WSD
12449 "OMIT_WSD",
12450 #endif
12451 #ifdef SQLITE_OMIT_XFER_OPT
12452 "OMIT_XFER_OPT",
12453 #endif
12454 #ifdef SQLITE_PAGECACHE_BLOCKALLOC
12455 "PAGECACHE_BLOCKALLOC",
12456 #endif
12457 #ifdef SQLITE_PERFORMANCE_TRACE
12458 "PERFORMANCE_TRACE",
12459 #endif
12460 #ifdef SQLITE_PROXY_DEBUG
@@ -12508,10 +12572,13 @@
12572 /*
12573 ** Boolean values
12574 */
12575 typedef unsigned char Bool;
12576
12577 /* Opaque type used by code in vdbesort.c */
12578 typedef struct VdbeSorter VdbeSorter;
12579
12580 /*
12581 ** A cursor is a pointer into a single BTree within a database file.
12582 ** The cursor can seek to a BTree entry with a particular key, or
12583 ** loop over all entries of the Btree. You can also insert new BTree
12584 ** entries or retrieve the key or data from the entry that the cursor
@@ -12539,10 +12606,11 @@
12606 sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
12607 const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
12608 i64 seqCount; /* Sequence counter */
12609 i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
12610 i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
12611 VdbeSorter *pSorter; /* Sorter object for OP_OpenSorter cursors */
12612
12613 /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
12614 ** OP_IsUnique opcode on this cursor. */
12615 int seekResult;
12616
@@ -12858,17 +12926,36 @@
12926 SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
12927 SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
12928 SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
12929 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
12930 SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
12931 #define MemReleaseExt(X) \
12932 if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
12933 sqlite3VdbeMemReleaseExternal(X);
12934 SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
12935 SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
12936 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
12937 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
12938 SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
12939 SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
12940 SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
12941
12942 #ifdef SQLITE_OMIT_MERGE_SORT
12943 # define sqlite3VdbeSorterInit(Y,Z) SQLITE_OK
12944 # define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
12945 # define sqlite3VdbeSorterClose(Y,Z)
12946 # define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
12947 # define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
12948 # define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
12949 #else
12950 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
12951 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, int);
12952 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
12953 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
12954 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
12955 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
12956 #endif
12957
12958 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
12959 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
12960 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
12961 #else
@@ -13159,30 +13246,16 @@
13246 ** Astronomical Algorithms, 2nd Edition, 1998
13247 ** ISBM 0-943396-61-1
13248 ** Willmann-Bell, Inc
13249 ** Richmond, Virginia (USA)
13250 */
13251 /* #include <stdlib.h> */
13252 /* #include <assert.h> */
13253 #include <time.h>
13254
13255 #ifndef SQLITE_OMIT_DATETIME_FUNCS
13256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13257
13258 /*
13259 ** A structure for holding a single date and time.
13260 */
13261 typedef struct DateTime DateTime;
@@ -13523,20 +13596,90 @@
13596 static void clearYMD_HMS_TZ(DateTime *p){
13597 p->validYMD = 0;
13598 p->validHMS = 0;
13599 p->validTZ = 0;
13600 }
13601
13602 /*
13603 ** On recent Windows platforms, the localtime_s() function is available
13604 ** as part of the "Secure CRT". It is essentially equivalent to
13605 ** localtime_r() available under most POSIX platforms, except that the
13606 ** order of the parameters is reversed.
13607 **
13608 ** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
13609 **
13610 ** If the user has not indicated to use localtime_r() or localtime_s()
13611 ** already, check for an MSVC build environment that provides
13612 ** localtime_s().
13613 */
13614 #if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
13615 defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
13616 #define HAVE_LOCALTIME_S 1
13617 #endif
13618
13619 #ifndef SQLITE_OMIT_LOCALTIME
13620 /*
13621 ** The following routine implements the rough equivalent of localtime_r()
13622 ** using whatever operating-system specific localtime facility that
13623 ** is available. This routine returns 0 on success and
13624 ** non-zero on any kind of error.
13625 **
13626 ** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
13627 ** routine will always fail.
13628 */
13629 static int osLocaltime(time_t *t, struct tm *pTm){
13630 int rc;
13631 #if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
13632 && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
13633 struct tm *pX;
13634 #if SQLITE_THREADSAFE>0
13635 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
13636 #endif
13637 sqlite3_mutex_enter(mutex);
13638 pX = localtime(t);
13639 #ifndef SQLITE_OMIT_BUILTIN_TEST
13640 if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
13641 #endif
13642 if( pX ) *pTm = *pX;
13643 sqlite3_mutex_leave(mutex);
13644 rc = pX==0;
13645 #else
13646 #ifndef SQLITE_OMIT_BUILTIN_TEST
13647 if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
13648 #endif
13649 #if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
13650 rc = localtime_r(t, pTm)==0;
13651 #else
13652 rc = localtime_s(pTm, t);
13653 #endif /* HAVE_LOCALTIME_R */
13654 #endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
13655 return rc;
13656 }
13657 #endif /* SQLITE_OMIT_LOCALTIME */
13658
13659
13660 #ifndef SQLITE_OMIT_LOCALTIME
13661 /*
13662 ** Compute the difference (in milliseconds) between localtime and UTC
13663 ** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
13664 ** return this value and set *pRc to SQLITE_OK.
13665 **
13666 ** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
13667 ** is undefined in this case.
13668 */
13669 static sqlite3_int64 localtimeOffset(
13670 DateTime *p, /* Date at which to calculate offset */
13671 sqlite3_context *pCtx, /* Write error here if one occurs */
13672 int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
13673 ){
13674 DateTime x, y;
13675 time_t t;
13676 struct tm sLocal;
13677
13678 /* Initialize the contents of sLocal to avoid a compiler warning. */
13679 memset(&sLocal, 0, sizeof(sLocal));
13680
13681 x = *p;
13682 computeYMD_HMS(&x);
13683 if( x.Y<1971 || x.Y>=2038 ){
13684 x.Y = 2000;
13685 x.M = 1;
@@ -13550,51 +13693,27 @@
13693 }
13694 x.tz = 0;
13695 x.validJD = 0;
13696 computeJD(&x);
13697 t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
13698 if( osLocaltime(&t, &sLocal) ){
13699 sqlite3_result_error(pCtx, "local time unavailable", -1);
13700 *pRc = SQLITE_ERROR;
13701 return 0;
13702 }
13703 y.Y = sLocal.tm_year + 1900;
13704 y.M = sLocal.tm_mon + 1;
13705 y.D = sLocal.tm_mday;
13706 y.h = sLocal.tm_hour;
13707 y.m = sLocal.tm_min;
13708 y.s = sLocal.tm_sec;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13709 y.validYMD = 1;
13710 y.validHMS = 1;
13711 y.validJD = 0;
13712 y.validTZ = 0;
13713 computeJD(&y);
13714 *pRc = SQLITE_OK;
13715 return y.iJD - x.iJD;
13716 }
13717 #endif /* SQLITE_OMIT_LOCALTIME */
13718
13719 /*
@@ -13614,13 +13733,16 @@
13733 ** weekday N
13734 ** unixepoch
13735 ** localtime
13736 ** utc
13737 **
13738 ** Return 0 on success and 1 if there is any kind of error. If the error
13739 ** is in a system call (i.e. localtime()), then an error message is written
13740 ** to context pCtx. If the error is an unrecognized modifier, no error is
13741 ** written to pCtx.
13742 */
13743 static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
13744 int rc = 1;
13745 int n;
13746 double r;
13747 char *z, zBuf[30];
13748 z = zBuf;
@@ -13636,13 +13758,12 @@
13758 ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
13759 ** show local time.
13760 */
13761 if( strcmp(z, "localtime")==0 ){
13762 computeJD(p);
13763 p->iJD += localtimeOffset(p, pCtx, &rc);
13764 clearYMD_HMS_TZ(p);
 
13765 }
13766 break;
13767 }
13768 #endif
13769 case 'u': {
@@ -13659,15 +13780,16 @@
13780 }
13781 #ifndef SQLITE_OMIT_LOCALTIME
13782 else if( strcmp(z, "utc")==0 ){
13783 sqlite3_int64 c1;
13784 computeJD(p);
13785 c1 = localtimeOffset(p, pCtx, &rc);
13786 if( rc==SQLITE_OK ){
13787 p->iJD -= c1;
13788 clearYMD_HMS_TZ(p);
13789 p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
13790 }
13791 }
13792 #endif
13793 break;
13794 }
13795 case 'w': {
@@ -13844,13 +13966,12 @@
13966 if( !z || parseDateOrTime(context, (char*)z, p) ){
13967 return 1;
13968 }
13969 }
13970 for(i=1; i<argc; i++){
13971 z = sqlite3_value_text(argv[i]);
13972 if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
 
13973 }
13974 return 0;
13975 }
13976
13977
@@ -14344,11 +14465,11 @@
14465 DO_OS_MALLOC_TEST(0);
14466 /* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
14467 ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
14468 ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
14469 ** reaching the VFS. */
14470 rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
14471 assert( rc==SQLITE_OK || pFile->pMethods==0 );
14472 return rc;
14473 }
14474 SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
14475 return pVfs->xDelete(pVfs, zPath, dirSync);
@@ -14880,10 +15001,11 @@
15001 extern void backtrace_symbols_fd(void*const*,int,int);
15002 #else
15003 # define backtrace(A,B) 1
15004 # define backtrace_symbols_fd(A,B,C)
15005 #endif
15006 /* #include <stdio.h> */
15007
15008 /*
15009 ** Each memory allocation looks like this:
15010 **
15011 ** ------------------------------------------------------------------------
@@ -15805,11 +15927,11 @@
15927 ** Free an outstanding memory allocation.
15928 **
15929 ** This function assumes that the necessary mutexes, if any, are
15930 ** already held by the caller. Hence "Unsafe".
15931 */
15932 static void memsys3FreeUnsafe(void *pOld){
15933 Mem3Block *p = (Mem3Block*)pOld;
15934 int i;
15935 u32 size, x;
15936 assert( sqlite3_mutex_held(mem3.mutex) );
15937 assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
@@ -15880,21 +16002,21 @@
16002 }
16003
16004 /*
16005 ** Free memory.
16006 */
16007 static void memsys3Free(void *pPrior){
16008 assert( pPrior );
16009 memsys3Enter();
16010 memsys3FreeUnsafe(pPrior);
16011 memsys3Leave();
16012 }
16013
16014 /*
16015 ** Change the size of an existing memory allocation
16016 */
16017 static void *memsys3Realloc(void *pPrior, int nBytes){
16018 int nOld;
16019 void *p;
16020 if( pPrior==0 ){
16021 return sqlite3_malloc(nBytes);
16022 }
@@ -17983,10 +18105,11 @@
18105 **
18106 *************************************************************************
18107 **
18108 ** Memory allocation functions used throughout sqlite.
18109 */
18110 /* #include <stdarg.h> */
18111
18112 /*
18113 ** Attempt to release up to n bytes of non-essential memory currently
18114 ** held by SQLite. An example of non-essential memory is memory used to
18115 ** cache database pages that are not currently in use.
@@ -19960,10 +20083,11 @@
20083 ** BOM or Byte Order Mark:
20084 ** 0xff 0xfe little-endian utf-16 follows
20085 ** 0xfe 0xff big-endian utf-16 follows
20086 **
20087 */
20088 /* #include <assert.h> */
20089
20090 #ifndef SQLITE_AMALGAMATION
20091 /*
20092 ** The following constant value is used by the SQLITE_BIGENDIAN and
20093 ** SQLITE_LITTLEENDIAN macros.
@@ -20502,10 +20626,11 @@
20626 **
20627 ** This file contains functions for allocating memory, comparing
20628 ** strings, and stuff like that.
20629 **
20630 */
20631 /* #include <stdarg.h> */
20632 #ifdef SQLITE_HAVE_ISNAN
20633 # include <math.h>
20634 #endif
20635
20636 /*
@@ -21634,26 +21759,32 @@
21759 return -x;
21760 }
21761
21762 #ifdef SQLITE_ENABLE_8_3_NAMES
21763 /*
21764 ** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
21765 ** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
21766 ** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
21767 ** three characters, then shorten the suffix on z[] to be the last three
21768 ** characters of the original suffix.
21769 **
21770 ** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
21771 ** do the suffix shortening regardless of URI parameter.
21772 **
21773 ** Examples:
21774 **
21775 ** test.db-journal => test.nal
21776 ** test.db-wal => test.wal
21777 ** test.db-shm => test.shm
21778 */
21779 SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
21780 #if SQLITE_ENABLE_8_3_NAMES<2
21781 const char *zOk;
21782 zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
21783 if( zOk && sqlite3GetBoolean(zOk) )
21784 #endif
21785 {
21786 int i, sz;
21787 sz = sqlite3Strlen30(z);
21788 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
21789 if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
21790 }
@@ -21674,10 +21805,11 @@
21805 **
21806 *************************************************************************
21807 ** This is the implementation of generic hash-tables
21808 ** used in SQLite.
21809 */
21810 /* #include <assert.h> */
21811
21812 /* Turn bulk memory into a hash table object by initializing the
21813 ** fields of the Hash structure.
21814 **
21815 ** "pNew" is a pointer to the hash table that is to be initialized.
@@ -21982,52 +22114,52 @@
22114 /* 35 */ "ReadCookie",
22115 /* 36 */ "SetCookie",
22116 /* 37 */ "VerifyCookie",
22117 /* 38 */ "OpenRead",
22118 /* 39 */ "OpenWrite",
22119 /* 40 */ "OpenSorter",
22120 /* 41 */ "OpenAutoindex",
22121 /* 42 */ "OpenEphemeral",
22122 /* 43 */ "OpenPseudo",
22123 /* 44 */ "Close",
22124 /* 45 */ "SeekLt",
22125 /* 46 */ "SeekLe",
22126 /* 47 */ "SeekGe",
22127 /* 48 */ "SeekGt",
22128 /* 49 */ "Seek",
22129 /* 50 */ "NotFound",
22130 /* 51 */ "Found",
22131 /* 52 */ "IsUnique",
22132 /* 53 */ "NotExists",
22133 /* 54 */ "Sequence",
22134 /* 55 */ "NewRowid",
22135 /* 56 */ "Insert",
22136 /* 57 */ "InsertInt",
22137 /* 58 */ "Delete",
22138 /* 59 */ "ResetCount",
22139 /* 60 */ "RowKey",
22140 /* 61 */ "RowData",
22141 /* 62 */ "Rowid",
22142 /* 63 */ "NullRow",
22143 /* 64 */ "Last",
22144 /* 65 */ "Sort",
22145 /* 66 */ "Rewind",
22146 /* 67 */ "Prev",
22147 /* 68 */ "Or",
22148 /* 69 */ "And",
22149 /* 70 */ "Next",
22150 /* 71 */ "IdxInsert",
22151 /* 72 */ "IdxDelete",
22152 /* 73 */ "IsNull",
22153 /* 74 */ "NotNull",
22154 /* 75 */ "Ne",
22155 /* 76 */ "Eq",
22156 /* 77 */ "Gt",
22157 /* 78 */ "Le",
22158 /* 79 */ "Lt",
22159 /* 80 */ "Ge",
22160 /* 81 */ "IdxRowid",
22161 /* 82 */ "BitAnd",
22162 /* 83 */ "BitOr",
22163 /* 84 */ "ShiftLeft",
22164 /* 85 */ "ShiftRight",
22165 /* 86 */ "Add",
@@ -22034,58 +22166,58 @@
22166 /* 87 */ "Subtract",
22167 /* 88 */ "Multiply",
22168 /* 89 */ "Divide",
22169 /* 90 */ "Remainder",
22170 /* 91 */ "Concat",
22171 /* 92 */ "IdxLT",
22172 /* 93 */ "BitNot",
22173 /* 94 */ "String8",
22174 /* 95 */ "IdxGE",
22175 /* 96 */ "Destroy",
22176 /* 97 */ "Clear",
22177 /* 98 */ "CreateIndex",
22178 /* 99 */ "CreateTable",
22179 /* 100 */ "ParseSchema",
22180 /* 101 */ "LoadAnalysis",
22181 /* 102 */ "DropTable",
22182 /* 103 */ "DropIndex",
22183 /* 104 */ "DropTrigger",
22184 /* 105 */ "IntegrityCk",
22185 /* 106 */ "RowSetAdd",
22186 /* 107 */ "RowSetRead",
22187 /* 108 */ "RowSetTest",
22188 /* 109 */ "Program",
22189 /* 110 */ "Param",
22190 /* 111 */ "FkCounter",
22191 /* 112 */ "FkIfZero",
22192 /* 113 */ "MemMax",
22193 /* 114 */ "IfPos",
22194 /* 115 */ "IfNeg",
22195 /* 116 */ "IfZero",
22196 /* 117 */ "AggStep",
22197 /* 118 */ "AggFinal",
22198 /* 119 */ "Checkpoint",
22199 /* 120 */ "JournalMode",
22200 /* 121 */ "Vacuum",
22201 /* 122 */ "IncrVacuum",
22202 /* 123 */ "Expire",
22203 /* 124 */ "TableLock",
22204 /* 125 */ "VBegin",
22205 /* 126 */ "VCreate",
22206 /* 127 */ "VDestroy",
22207 /* 128 */ "VOpen",
22208 /* 129 */ "VFilter",
22209 /* 130 */ "Real",
22210 /* 131 */ "VColumn",
22211 /* 132 */ "VNext",
22212 /* 133 */ "VRename",
22213 /* 134 */ "VUpdate",
22214 /* 135 */ "Pagecount",
22215 /* 136 */ "MaxPgcnt",
22216 /* 137 */ "Trace",
22217 /* 138 */ "Noop",
22218 /* 139 */ "Explain",
22219 /* 140 */ "NotUsed_140",
22220 /* 141 */ "ToText",
22221 /* 142 */ "ToBlob",
22222 /* 143 */ "ToNumeric",
22223 /* 144 */ "ToInt",
@@ -22183,14 +22315,17 @@
22315 #ifdef MEMORY_DEBUG
22316 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
22317 #endif
22318
22319 #ifdef SQLITE_DEBUG
22320 # ifndef SQLITE_DEBUG_OS_TRACE
22321 # define SQLITE_DEBUG_OS_TRACE 0
22322 # endif
22323 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
22324 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
22325 #else
22326 # define OSTRACE(X)
22327 #endif
22328
22329 /*
22330 ** Macros for performance tracing. Normally turned off. Only works
22331 ** on i486 hardware.
@@ -24343,10 +24478,11 @@
24478 */
24479 #include <sys/types.h>
24480 #include <sys/stat.h>
24481 #include <fcntl.h>
24482 #include <unistd.h>
24483 /* #include <time.h> */
24484 #include <sys/time.h>
24485 #include <errno.h>
24486 #ifndef SQLITE_OMIT_WAL
24487 #include <sys/mman.h>
24488 #endif
@@ -24364,10 +24500,14 @@
24500
24501 #if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
24502 # include <sys/mount.h>
24503 #endif
24504
24505 #ifdef HAVE_UTIME
24506 # include <utime.h>
24507 #endif
24508
24509 /*
24510 ** Allowed values of unixFile.fsFlags
24511 */
24512 #define SQLITE_FSFLAGS_IS_MSDOS 0x1
24513
@@ -24374,10 +24514,11 @@
24514 /*
24515 ** If we are to be thread-safe, include the pthreads header and define
24516 ** the SQLITE_UNIX_THREADS macro.
24517 */
24518 #if SQLITE_THREADSAFE
24519 /* # include <pthread.h> */
24520 # define SQLITE_UNIX_THREADS 1
24521 #endif
24522
24523 /*
24524 ** Default permissions when creating a new file
@@ -24429,11 +24570,10 @@
24570 typedef struct unixFile unixFile;
24571 struct unixFile {
24572 sqlite3_io_methods const *pMethod; /* Always the first entry */
24573 unixInodeInfo *pInode; /* Info about locks on this inode */
24574 int h; /* The file descriptor */
 
24575 unsigned char eFileLock; /* The type of lock held on this fd */
24576 unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
24577 int lastErrno; /* The unix errno from last I/O error */
24578 void *lockingContext; /* Locking style specific state */
24579 UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
@@ -24471,12 +24611,18 @@
24611 };
24612
24613 /*
24614 ** Allowed values for the unixFile.ctrlFlags bitmask:
24615 */
24616 #define UNIXFILE_EXCL 0x01 /* Connections from one process only */
24617 #define UNIXFILE_RDONLY 0x02 /* Connection is read only */
24618 #define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
24619 #ifndef SQLITE_DISABLE_DIRSYNC
24620 # define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
24621 #else
24622 # define UNIXFILE_DIRSYNC 0x00
24623 #endif
24624
24625 /*
24626 ** Include code that is common to all os_*.c files
24627 */
24628 /************** Include os_common.h in the middle of os_unix.c ***************/
@@ -24511,14 +24657,17 @@
24657 #ifdef MEMORY_DEBUG
24658 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
24659 #endif
24660
24661 #ifdef SQLITE_DEBUG
24662 # ifndef SQLITE_DEBUG_OS_TRACE
24663 # define SQLITE_DEBUG_OS_TRACE 0
24664 # endif
24665 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
24666 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
24667 #else
24668 # define OSTRACE(X)
24669 #endif
24670
24671 /*
24672 ** Macros for performance tracing. Normally turned off. Only works
24673 ** on i486 hardware.
@@ -24723,10 +24872,13 @@
24872 */
24873 static int posixOpen(const char *zFile, int flags, int mode){
24874 return open(zFile, flags, mode);
24875 }
24876
24877 /* Forward reference */
24878 static int openDirectory(const char*, int*);
24879
24880 /*
24881 ** Many system calls are accessed through pointer-to-functions so that
24882 ** they may be overridden at runtime to facilitate fault injection during
24883 ** testing and sandboxing. The following array holds the names and pointers
24884 ** to all overrideable system calls.
@@ -24819,10 +24971,16 @@
24971 #else
24972 { "fallocate", (sqlite3_syscall_ptr)0, 0 },
24973 #endif
24974 #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
24975
24976 { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
24977 #define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
24978
24979 { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
24980 #define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
24981
24982 }; /* End of the overrideable system calls */
24983
24984 /*
24985 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
24986 ** "unix" VFSes. Return SQLITE_OK opon successfully updating the
@@ -25103,11 +25261,13 @@
25261 case EINVAL:
25262 case ENOTCONN:
25263 case ENODEV:
25264 case ENXIO:
25265 case ENOENT:
25266 #ifdef ESTALE /* ESTALE is not defined on Interix systems */
25267 case ESTALE:
25268 #endif
25269 case ENOSYS:
25270 /* these should force the client to close the file and reconnect */
25271
25272 default:
25273 return sqliteIOErr;
@@ -26173,22 +26333,18 @@
26333 ** even on VxWorks. A mutex will be acquired on VxWorks by the
26334 ** vxworksReleaseFileId() routine.
26335 */
26336 static int closeUnixFile(sqlite3_file *id){
26337 unixFile *pFile = (unixFile*)id;
 
 
 
 
26338 if( pFile->h>=0 ){
26339 robust_close(pFile, pFile->h, __LINE__);
26340 pFile->h = -1;
26341 }
26342 #if OS_VXWORKS
26343 if( pFile->pId ){
26344 if( pFile->isDelete ){
26345 osUnlink(pFile->pId->zCanonicalName);
26346 }
26347 vxworksReleaseFileId(pFile->pId);
26348 pFile->pId = 0;
26349 }
26350 #endif
@@ -26369,12 +26525,14 @@
26525 /* If we have any lock, then the lock file already exists. All we have
26526 ** to do is adjust our internal record of the lock level.
26527 */
26528 if( pFile->eFileLock > NO_LOCK ){
26529 pFile->eFileLock = eFileLock;
 
26530 /* Always update the timestamp on the old file */
26531 #ifdef HAVE_UTIME
26532 utime(zLockFile, NULL);
26533 #else
26534 utimes(zLockFile, NULL);
26535 #endif
26536 return SQLITE_OK;
26537 }
26538
@@ -26431,11 +26589,11 @@
26589 return SQLITE_OK;
26590 }
26591
26592 /* To fully unlock the database, delete the lock file */
26593 assert( eFileLock==NO_LOCK );
26594 if( osUnlink(zLockFile) ){
26595 int rc = 0;
26596 int tErrno = errno;
26597 if( ENOENT != tErrno ){
26598 rc = SQLITE_IOERR_UNLOCK;
26599 }
@@ -26937,15 +27095,16 @@
27095 */
27096 static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
27097 int rc = SQLITE_OK;
27098 int reserved = 0;
27099 unixFile *pFile = (unixFile*)id;
27100 afpLockingContext *context;
27101
27102 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
27103
27104 assert( pFile );
27105 context = (afpLockingContext *) pFile->lockingContext;
27106 if( context->reserved ){
27107 *pResOut = 1;
27108 return SQLITE_OK;
27109 }
27110 unixEnterMutex(); /* Because pFile->pInode is shared across threads */
@@ -27081,11 +27240,11 @@
27240
27241 /* If control gets to this point, then actually go ahead and make
27242 ** operating system calls for the specified lock.
27243 */
27244 if( eFileLock==SHARED_LOCK ){
27245 int lrc1, lrc2, lrc1Errno = 0;
27246 long lk, mask;
27247
27248 assert( pInode->nShared==0 );
27249 assert( pInode->eFileLock==0 );
27250
@@ -27455,21 +27614,23 @@
27614 #if defined(USE_PREAD)
27615 do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
27616 #elif defined(USE_PREAD64)
27617 do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
27618 #else
27619 do{
27620 newOffset = lseek(id->h, offset, SEEK_SET);
27621 SimulateIOError( newOffset-- );
27622 if( newOffset!=offset ){
27623 if( newOffset == -1 ){
27624 ((unixFile*)id)->lastErrno = errno;
27625 }else{
27626 ((unixFile*)id)->lastErrno = 0;
27627 }
27628 return -1;
27629 }
27630 got = osWrite(id->h, pBuf, cnt);
27631 }while( got<0 && errno==EINTR );
27632 #endif
27633 TIMER_END;
27634 if( got<0 ){
27635 ((unixFile*)id)->lastErrno = errno;
27636 }
@@ -27666,10 +27827,54 @@
27827 if( OS_VXWORKS && rc!= -1 ){
27828 rc = 0;
27829 }
27830 return rc;
27831 }
27832
27833 /*
27834 ** Open a file descriptor to the directory containing file zFilename.
27835 ** If successful, *pFd is set to the opened file descriptor and
27836 ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
27837 ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
27838 ** value.
27839 **
27840 ** The directory file descriptor is used for only one thing - to
27841 ** fsync() a directory to make sure file creation and deletion events
27842 ** are flushed to disk. Such fsyncs are not needed on newer
27843 ** journaling filesystems, but are required on older filesystems.
27844 **
27845 ** This routine can be overridden using the xSetSysCall interface.
27846 ** The ability to override this routine was added in support of the
27847 ** chromium sandbox. Opening a directory is a security risk (we are
27848 ** told) so making it overrideable allows the chromium sandbox to
27849 ** replace this routine with a harmless no-op. To make this routine
27850 ** a no-op, replace it with a stub that returns SQLITE_OK but leaves
27851 ** *pFd set to a negative number.
27852 **
27853 ** If SQLITE_OK is returned, the caller is responsible for closing
27854 ** the file descriptor *pFd using close().
27855 */
27856 static int openDirectory(const char *zFilename, int *pFd){
27857 int ii;
27858 int fd = -1;
27859 char zDirname[MAX_PATHNAME+1];
27860
27861 sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
27862 for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
27863 if( ii>0 ){
27864 zDirname[ii] = '\0';
27865 fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
27866 if( fd>=0 ){
27867 #ifdef FD_CLOEXEC
27868 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
27869 #endif
27870 OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
27871 }
27872 }
27873 *pFd = fd;
27874 return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
27875 }
27876
27877 /*
27878 ** Make sure all writes to a particular file are committed to disk.
27879 **
27880 ** If dataOnly==0 then both the file itself and its metadata (file
@@ -27707,32 +27912,27 @@
27912 SimulateIOError( rc=1 );
27913 if( rc ){
27914 pFile->lastErrno = errno;
27915 return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
27916 }
27917
27918 /* Also fsync the directory containing the file if the DIRSYNC flag
27919 ** is set. This is a one-time occurrance. Many systems (examples: AIX)
27920 ** are unable to fsync a directory, so ignore errors on the fsync.
27921 */
27922 if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
27923 int dirfd;
27924 OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
27925 HAVE_FULLFSYNC, isFullsync));
27926 rc = osOpenDirectory(pFile->zPath, &dirfd);
27927 if( rc==SQLITE_OK && dirfd>=0 ){
27928 full_fsync(dirfd, 0, 0);
27929 robust_close(pFile, dirfd, __LINE__);
27930 }else if( rc==SQLITE_CANTOPEN ){
27931 rc = SQLITE_OK;
27932 }
27933 pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
 
 
 
 
 
 
 
 
 
 
 
27934 }
27935 return rc;
27936 }
27937
27938 /*
@@ -27810,15 +28010,13 @@
28010 static int proxyFileControl(sqlite3_file*,int,void*);
28011 #endif
28012
28013 /*
28014 ** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
28015 ** file-control operation. Enlarge the database to nBytes in size
28016 ** (rounded up to the next chunk-size). If the database is already
28017 ** nBytes or larger, this routine is a no-op.
 
 
28018 */
28019 static int fcntlSizeHint(unixFile *pFile, i64 nByte){
28020 if( pFile->szChunk ){
28021 i64 nSize; /* Required file size */
28022 struct stat buf; /* Used to hold return values of fstat() */
@@ -27866,25 +28064,41 @@
28064
28065 /*
28066 ** Information and control of an open file handle.
28067 */
28068 static int unixFileControl(sqlite3_file *id, int op, void *pArg){
28069 unixFile *pFile = (unixFile*)id;
28070 switch( op ){
28071 case SQLITE_FCNTL_LOCKSTATE: {
28072 *(int*)pArg = pFile->eFileLock;
28073 return SQLITE_OK;
28074 }
28075 case SQLITE_LAST_ERRNO: {
28076 *(int*)pArg = pFile->lastErrno;
28077 return SQLITE_OK;
28078 }
28079 case SQLITE_FCNTL_CHUNK_SIZE: {
28080 pFile->szChunk = *(int *)pArg;
28081 return SQLITE_OK;
28082 }
28083 case SQLITE_FCNTL_SIZE_HINT: {
28084 int rc;
28085 SimulateIOErrorBenign(1);
28086 rc = fcntlSizeHint(pFile, *(i64 *)pArg);
28087 SimulateIOErrorBenign(0);
28088 return rc;
28089 }
28090 case SQLITE_FCNTL_PERSIST_WAL: {
28091 int bPersist = *(int*)pArg;
28092 if( bPersist<0 ){
28093 *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
28094 }else if( bPersist==0 ){
28095 pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
28096 }else{
28097 pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
28098 }
28099 return SQLITE_OK;
28100 }
28101 #ifndef NDEBUG
28102 /* The pager calls this method to signal that it has done
28103 ** a rollback and that the database is therefore unchanged and
28104 ** it hence it is OK for the transaction change counter to be
@@ -28096,11 +28310,11 @@
28310 unixShmNode *p = pFd->pInode->pShmNode;
28311 assert( unixMutexHeld() );
28312 if( p && p->nRef==0 ){
28313 int i;
28314 assert( p->pInode==pFd->pInode );
28315 sqlite3_mutex_free(p->mutex);
28316 for(i=0; i<p->nRegion; i++){
28317 if( p->h>=0 ){
28318 munmap(p->apRegion[i], p->szRegion);
28319 }else{
28320 sqlite3_free(p->apRegion[i]);
@@ -28565,11 +28779,11 @@
28779 ** shared-memory file, too */
28780 unixEnterMutex();
28781 assert( pShmNode->nRef>0 );
28782 pShmNode->nRef--;
28783 if( pShmNode->nRef==0 ){
28784 if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
28785 unixShmPurge(pDbFd);
28786 }
28787 unixLeaveMutex();
28788
28789 return SQLITE_OK;
@@ -28878,11 +29092,11 @@
29092 ** Initialize the contents of the unixFile structure pointed to by pId.
29093 */
29094 static int fillInUnixFile(
29095 sqlite3_vfs *pVfs, /* Pointer to vfs object */
29096 int h, /* Open file descriptor of file being opened */
29097 int syncDir, /* True to sync directory on first sync */
29098 sqlite3_file *pId, /* Write to the unixFile structure here */
29099 const char *zFilename, /* Name of the file being opened */
29100 int noLock, /* Omit locking if true */
29101 int isDelete, /* Delete on close if true */
29102 int isReadOnly /* True if the file is opened read-only */
@@ -28909,20 +29123,22 @@
29123 assert( zFilename==0 || zFilename[0]=='/' );
29124 #endif
29125
29126 OSTRACE(("OPEN %-3d %s\n", h, zFilename));
29127 pNew->h = h;
 
29128 pNew->zPath = zFilename;
29129 if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
29130 pNew->ctrlFlags = UNIXFILE_EXCL;
29131 }else{
29132 pNew->ctrlFlags = 0;
29133 }
29134 if( isReadOnly ){
29135 pNew->ctrlFlags |= UNIXFILE_RDONLY;
29136 }
29137 if( syncDir ){
29138 pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
29139 }
29140
29141 #if OS_VXWORKS
29142 pNew->pId = vxworksFindFileId(zFilename);
29143 if( pNew->pId==0 ){
29144 noLock = 1;
@@ -29045,56 +29261,24 @@
29261 pNew->lastErrno = 0;
29262 #if OS_VXWORKS
29263 if( rc!=SQLITE_OK ){
29264 if( h>=0 ) robust_close(pNew, h, __LINE__);
29265 h = -1;
29266 osUnlink(zFilename);
29267 isDelete = 0;
29268 }
29269 pNew->isDelete = isDelete;
29270 #endif
29271 if( rc!=SQLITE_OK ){
 
29272 if( h>=0 ) robust_close(pNew, h, __LINE__);
29273 }else{
29274 pNew->pMethod = pLockingStyle;
29275 OpenCounter(+1);
29276 }
29277 return rc;
29278 }
29279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29280 /*
29281 ** Return the name of a directory in which to put temporary files.
29282 ** If no suitable temporary file directory can be found, return NULL.
29283 */
29284 static const char *unixTempFileDir(void){
@@ -29205,11 +29389,11 @@
29389 ** ignored and -1 is returned. The caller will try to open a new file
29390 ** descriptor on the same path, fail, and return an error to SQLite.
29391 **
29392 ** Even if a subsequent open() call does succeed, the consequences of
29393 ** not searching for a resusable file descriptor are not dire. */
29394 if( 0==osStat(zPath, &sStat) ){
29395 unixInodeInfo *pInode;
29396
29397 unixEnterMutex();
29398 pInode = inodeList;
29399 while( pInode && (pInode->fileId.dev!=sStat.st_dev
@@ -29281,11 +29465,11 @@
29465 while( nDb>0 && zPath[nDb]!='-' ) nDb--;
29466 if( nDb==0 ) return SQLITE_OK;
29467 memcpy(zDb, zPath, nDb);
29468 zDb[nDb] = '\0';
29469
29470 if( 0==osStat(zDb, &sStat) ){
29471 *pMode = sStat.st_mode & 0777;
29472 }else{
29473 rc = SQLITE_IOERR_FSTAT;
29474 }
29475 }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
@@ -29323,11 +29507,10 @@
29507 int flags, /* Input flags to control the opening */
29508 int *pOutFlags /* Output flags returned to SQLite core */
29509 ){
29510 unixFile *p = (unixFile *)pFile;
29511 int fd = -1; /* File descriptor returned by open() */
 
29512 int openFlags = 0; /* Flags to pass to open() */
29513 int eType = flags&0xFFFFFF00; /* Type of file to open */
29514 int noLock; /* True to omit locking primitives */
29515 int rc = SQLITE_OK; /* Function Return Code */
29516
@@ -29337,16 +29520,19 @@
29520 int isReadonly = (flags & SQLITE_OPEN_READONLY);
29521 int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
29522 #if SQLITE_ENABLE_LOCKING_STYLE
29523 int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
29524 #endif
29525 #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
29526 struct statfs fsInfo;
29527 #endif
29528
29529 /* If creating a master or main-file journal, this function will open
29530 ** a file-descriptor on the directory too. The first time unixSync()
29531 ** is called the directory file descriptor will be fsync()ed and close()d.
29532 */
29533 int syncDir = (isCreate && (
29534 eType==SQLITE_OPEN_MASTER_JOURNAL
29535 || eType==SQLITE_OPEN_MAIN_JOURNAL
29536 || eType==SQLITE_OPEN_WAL
29537 ));
29538
@@ -29396,11 +29582,11 @@
29582 }
29583 }
29584 p->pUnused = pUnused;
29585 }else if( !zName ){
29586 /* If zName is NULL, the upper layer is requesting a temp file. */
29587 assert(isDelete && !syncDir);
29588 rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
29589 if( rc!=SQLITE_OK ){
29590 return rc;
29591 }
29592 zName = zTmpname;
@@ -29452,44 +29638,29 @@
29638
29639 if( isDelete ){
29640 #if OS_VXWORKS
29641 zPath = zName;
29642 #else
29643 osUnlink(zName);
29644 #endif
29645 }
29646 #if SQLITE_ENABLE_LOCKING_STYLE
29647 else{
29648 p->openFlags = openFlags;
29649 }
29650 #endif
29651
 
 
 
 
 
 
 
 
 
 
 
 
 
29652 #ifdef FD_CLOEXEC
29653 osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
29654 #endif
29655
29656 noLock = eType!=SQLITE_OPEN_MAIN_DB;
29657
29658
29659 #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
 
29660 if( fstatfs(fd, &fsInfo) == -1 ){
29661 ((unixFile*)pFile)->lastErrno = errno;
 
29662 robust_close(p, fd, __LINE__);
29663 return SQLITE_IOERR_ACCESS;
29664 }
29665 if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
29666 ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
@@ -29507,31 +29678,27 @@
29678 /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
29679 ** never use proxy, NULL means use proxy for non-local files only. */
29680 if( envforce!=NULL ){
29681 useProxy = atoi(envforce)>0;
29682 }else{
 
29683 if( statfs(zPath, &fsInfo) == -1 ){
29684 /* In theory, the close(fd) call is sub-optimal. If the file opened
29685 ** with fd is a database file, and there are other connections open
29686 ** on that file that are currently holding advisory locks on it,
29687 ** then the call to close() will cancel those locks. In practice,
29688 ** we're assuming that statfs() doesn't fail very often. At least
29689 ** not while other file descriptors opened by the same process on
29690 ** the same file are working. */
29691 p->lastErrno = errno;
 
 
 
29692 robust_close(p, fd, __LINE__);
29693 rc = SQLITE_IOERR_ACCESS;
29694 goto open_finished;
29695 }
29696 useProxy = !(fsInfo.f_flags&MNT_LOCAL);
29697 }
29698 if( useProxy ){
29699 rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
29700 isDelete, isReadonly);
29701 if( rc==SQLITE_OK ){
29702 rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
29703 if( rc!=SQLITE_OK ){
29704 /* Use unixClose to clean up the resources added in fillInUnixFile
@@ -29545,11 +29712,11 @@
29712 goto open_finished;
29713 }
29714 }
29715 #endif
29716
29717 rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
29718 isDelete, isReadonly);
29719 open_finished:
29720 if( rc!=SQLITE_OK ){
29721 sqlite3_free(p->pUnused);
29722 }
@@ -29567,17 +29734,17 @@
29734 int dirSync /* If true, fsync() directory after deleting file */
29735 ){
29736 int rc = SQLITE_OK;
29737 UNUSED_PARAMETER(NotUsed);
29738 SimulateIOError(return SQLITE_IOERR_DELETE);
29739 if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
29740 return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
29741 }
29742 #ifndef SQLITE_DISABLE_DIRSYNC
29743 if( dirSync ){
29744 int fd;
29745 rc = osOpenDirectory(zPath, &fd);
29746 if( rc==SQLITE_OK ){
29747 #if OS_VXWORKS
29748 if( fsync(fd)==-1 )
29749 #else
29750 if( fsync(fd) )
@@ -29584,10 +29751,12 @@
29751 #endif
29752 {
29753 rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
29754 }
29755 robust_close(0, fd, __LINE__);
29756 }else if( rc==SQLITE_CANTOPEN ){
29757 rc = SQLITE_OK;
29758 }
29759 }
29760 #endif
29761 return rc;
29762 }
@@ -29626,11 +29795,11 @@
29795 assert(!"Invalid flags argument");
29796 }
29797 *pResOut = (osAccess(zPath, amode)==0);
29798 if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
29799 struct stat buf;
29800 if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
29801 *pResOut = 0;
29802 }
29803 }
29804 return SQLITE_OK;
29805 }
@@ -30145,11 +30314,10 @@
30314 const char *path, /* path for the new unixFile */
30315 unixFile **ppFile, /* unixFile created and returned by ref */
30316 int islockfile /* if non zero missing dirs will be created */
30317 ) {
30318 int fd = -1;
 
30319 unixFile *pNew;
30320 int rc = SQLITE_OK;
30321 int openFlags = O_RDWR | O_CREAT;
30322 sqlite3_vfs dummyVfs;
30323 int terrno = 0;
@@ -30210,11 +30378,11 @@
30378 dummyVfs.zName = "dummy";
30379 pUnused->fd = fd;
30380 pUnused->flags = openFlags;
30381 pNew->pUnused = pUnused;
30382
30383 rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
30384 if( rc==SQLITE_OK ){
30385 *ppFile = pNew;
30386 return SQLITE_OK;
30387 }
30388 end_create_proxy:
@@ -30250,10 +30418,12 @@
30418 *pError = err;
30419 }
30420 return SQLITE_IOERR;
30421 }
30422 }
30423 #else
30424 UNUSED_PARAMETER(pError);
30425 #endif
30426 #ifdef SQLITE_TEST
30427 /* simulate multiple hosts by creating unique hostid file paths */
30428 if( sqlite3_hostid_num != 0){
30429 pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
@@ -30324,11 +30494,11 @@
30494 conchFile->openFlags = O_RDWR | O_CREAT;
30495
30496 end_breaklock:
30497 if( rc ){
30498 if( fd>=0 ){
30499 osUnlink(tPath);
30500 robust_close(pFile, fd, __LINE__);
30501 }
30502 fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
30503 }
30504 return rc;
@@ -30342,10 +30512,11 @@
30512 unixFile *conchFile = pCtx->conchFile;
30513 int rc = SQLITE_OK;
30514 int nTries = 0;
30515 struct timespec conchModTime;
30516
30517 memset(&conchModTime, 0, sizeof(conchModTime));
30518 do {
30519 rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
30520 nTries ++;
30521 if( rc==SQLITE_BUSY ){
30522 /* If the lock failed (busy):
@@ -30573,15 +30744,16 @@
30744 conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
30745
30746 end_takeconch:
30747 OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
30748 if( rc==SQLITE_OK && pFile->openFlags ){
30749 int fd;
30750 if( pFile->h>=0 ){
30751 robust_close(pFile, pFile->h, __LINE__);
30752 }
30753 pFile->h = -1;
30754 fd = robust_open(pCtx->dbPath, pFile->openFlags,
30755 SQLITE_DEFAULT_FILE_PERMISSIONS);
30756 OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
30757 if( fd>=0 ){
30758 pFile->h = fd;
30759 }else{
@@ -31147,11 +31319,11 @@
31319 };
31320 unsigned int i; /* Loop counter */
31321
31322 /* Double-check that the aSyscall[] array has been constructed
31323 ** correctly. See ticket [bb3a86e890c8e96ab] */
31324 assert( ArraySize(aSyscall)==18 );
31325
31326 /* Register all VFSes defined in the aVfs[] array */
31327 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
31328 sqlite3_vfs_register(&aVfs[i], i==0);
31329 }
@@ -31264,14 +31436,17 @@
31436 #ifdef MEMORY_DEBUG
31437 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
31438 #endif
31439
31440 #ifdef SQLITE_DEBUG
31441 # ifndef SQLITE_DEBUG_OS_TRACE
31442 # define SQLITE_DEBUG_OS_TRACE 0
31443 # endif
31444 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
31445 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
31446 #else
31447 # define OSTRACE(X)
31448 #endif
31449
31450 /*
31451 ** Macros for performance tracing. Normally turned off. Only works
31452 ** on i486 hardware.
@@ -31479,12 +31654,13 @@
31654 typedef struct winFile winFile;
31655 struct winFile {
31656 const sqlite3_io_methods *pMethod; /*** Must be first ***/
31657 sqlite3_vfs *pVfs; /* The VFS used to open this file */
31658 HANDLE h; /* Handle for accessing the file */
31659 u8 locktype; /* Type of lock currently held on this file */
31660 short sharedLockByte; /* Randomly chosen byte used as a shared lock */
31661 u8 bPersistWal; /* True to persist WAL files */
31662 DWORD lastErrno; /* The Windows errno from the last I/O error */
31663 DWORD sectorSize; /* Sector size of the device file is on */
31664 winShm *pShm; /* Instance of shared memory on this file */
31665 const char *zPath; /* Full pathname of this file */
31666 int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
@@ -31495,10 +31671,80 @@
31671 winceLock local; /* Locks obtained by this instance of winFile */
31672 winceLock *shared; /* Global shared lock memory for the file */
31673 #endif
31674 };
31675
31676 /*
31677 * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
31678 * various Win32 API heap functions instead of our own.
31679 */
31680 #ifdef SQLITE_WIN32_MALLOC
31681 /*
31682 * The initial size of the Win32-specific heap. This value may be zero.
31683 */
31684 #ifndef SQLITE_WIN32_HEAP_INIT_SIZE
31685 # define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
31686 (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
31687 #endif
31688
31689 /*
31690 * The maximum size of the Win32-specific heap. This value may be zero.
31691 */
31692 #ifndef SQLITE_WIN32_HEAP_MAX_SIZE
31693 # define SQLITE_WIN32_HEAP_MAX_SIZE (0)
31694 #endif
31695
31696 /*
31697 * The extra flags to use in calls to the Win32 heap APIs. This value may be
31698 * zero for the default behavior.
31699 */
31700 #ifndef SQLITE_WIN32_HEAP_FLAGS
31701 # define SQLITE_WIN32_HEAP_FLAGS (0)
31702 #endif
31703
31704 /*
31705 ** The winMemData structure stores information required by the Win32-specific
31706 ** sqlite3_mem_methods implementation.
31707 */
31708 typedef struct winMemData winMemData;
31709 struct winMemData {
31710 #ifndef NDEBUG
31711 u32 magic; /* Magic number to detect structure corruption. */
31712 #endif
31713 HANDLE hHeap; /* The handle to our heap. */
31714 BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
31715 };
31716
31717 #ifndef NDEBUG
31718 #define WINMEM_MAGIC 0x42b2830b
31719 #endif
31720
31721 static struct winMemData win_mem_data = {
31722 #ifndef NDEBUG
31723 WINMEM_MAGIC,
31724 #endif
31725 NULL, FALSE
31726 };
31727
31728 #ifndef NDEBUG
31729 #define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
31730 #else
31731 #define winMemAssertMagic()
31732 #endif
31733
31734 #define winMemGetHeap() win_mem_data.hHeap
31735
31736 static void *winMemMalloc(int nBytes);
31737 static void winMemFree(void *pPrior);
31738 static void *winMemRealloc(void *pPrior, int nBytes);
31739 static int winMemSize(void *p);
31740 static int winMemRoundup(int n);
31741 static int winMemInit(void *pAppData);
31742 static void winMemShutdown(void *pAppData);
31743
31744 SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
31745 #endif /* SQLITE_WIN32_MALLOC */
31746
31747 /*
31748 ** Forward prototypes.
31749 */
31750 static int getSectorSize(
@@ -31547,10 +31793,192 @@
31793 }
31794 return sqlite3_os_type==2;
31795 }
31796 #endif /* SQLITE_OS_WINCE */
31797
31798 #ifdef SQLITE_WIN32_MALLOC
31799 /*
31800 ** Allocate nBytes of memory.
31801 */
31802 static void *winMemMalloc(int nBytes){
31803 HANDLE hHeap;
31804 void *p;
31805
31806 winMemAssertMagic();
31807 hHeap = winMemGetHeap();
31808 assert( hHeap!=0 );
31809 assert( hHeap!=INVALID_HANDLE_VALUE );
31810 #ifdef SQLITE_WIN32_MALLOC_VALIDATE
31811 assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31812 #endif
31813 assert( nBytes>=0 );
31814 p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
31815 if( !p ){
31816 sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
31817 nBytes, GetLastError(), (void*)hHeap);
31818 }
31819 return p;
31820 }
31821
31822 /*
31823 ** Free memory.
31824 */
31825 static void winMemFree(void *pPrior){
31826 HANDLE hHeap;
31827
31828 winMemAssertMagic();
31829 hHeap = winMemGetHeap();
31830 assert( hHeap!=0 );
31831 assert( hHeap!=INVALID_HANDLE_VALUE );
31832 #ifdef SQLITE_WIN32_MALLOC_VALIDATE
31833 assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
31834 #endif
31835 if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
31836 if( !HeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
31837 sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
31838 pPrior, GetLastError(), (void*)hHeap);
31839 }
31840 }
31841
31842 /*
31843 ** Change the size of an existing memory allocation
31844 */
31845 static void *winMemRealloc(void *pPrior, int nBytes){
31846 HANDLE hHeap;
31847 void *p;
31848
31849 winMemAssertMagic();
31850 hHeap = winMemGetHeap();
31851 assert( hHeap!=0 );
31852 assert( hHeap!=INVALID_HANDLE_VALUE );
31853 #ifdef SQLITE_WIN32_MALLOC_VALIDATE
31854 assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
31855 #endif
31856 assert( nBytes>=0 );
31857 if( !pPrior ){
31858 p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
31859 }else{
31860 p = HeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
31861 }
31862 if( !p ){
31863 sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
31864 pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(),
31865 (void*)hHeap);
31866 }
31867 return p;
31868 }
31869
31870 /*
31871 ** Return the size of an outstanding allocation, in bytes.
31872 */
31873 static int winMemSize(void *p){
31874 HANDLE hHeap;
31875 SIZE_T n;
31876
31877 winMemAssertMagic();
31878 hHeap = winMemGetHeap();
31879 assert( hHeap!=0 );
31880 assert( hHeap!=INVALID_HANDLE_VALUE );
31881 #ifdef SQLITE_WIN32_MALLOC_VALIDATE
31882 assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31883 #endif
31884 if( !p ) return 0;
31885 n = HeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
31886 if( n==(SIZE_T)-1 ){
31887 sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
31888 p, GetLastError(), (void*)hHeap);
31889 return 0;
31890 }
31891 return (int)n;
31892 }
31893
31894 /*
31895 ** Round up a request size to the next valid allocation size.
31896 */
31897 static int winMemRoundup(int n){
31898 return n;
31899 }
31900
31901 /*
31902 ** Initialize this module.
31903 */
31904 static int winMemInit(void *pAppData){
31905 winMemData *pWinMemData = (winMemData *)pAppData;
31906
31907 if( !pWinMemData ) return SQLITE_ERROR;
31908 assert( pWinMemData->magic==WINMEM_MAGIC );
31909 if( !pWinMemData->hHeap ){
31910 pWinMemData->hHeap = HeapCreate(SQLITE_WIN32_HEAP_FLAGS,
31911 SQLITE_WIN32_HEAP_INIT_SIZE,
31912 SQLITE_WIN32_HEAP_MAX_SIZE);
31913 if( !pWinMemData->hHeap ){
31914 sqlite3_log(SQLITE_NOMEM,
31915 "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
31916 GetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE,
31917 SQLITE_WIN32_HEAP_MAX_SIZE);
31918 return SQLITE_NOMEM;
31919 }
31920 pWinMemData->bOwned = TRUE;
31921 }
31922 assert( pWinMemData->hHeap!=0 );
31923 assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
31924 #ifdef SQLITE_WIN32_MALLOC_VALIDATE
31925 assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31926 #endif
31927 return SQLITE_OK;
31928 }
31929
31930 /*
31931 ** Deinitialize this module.
31932 */
31933 static void winMemShutdown(void *pAppData){
31934 winMemData *pWinMemData = (winMemData *)pAppData;
31935
31936 if( !pWinMemData ) return;
31937 if( pWinMemData->hHeap ){
31938 assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
31939 #ifdef SQLITE_WIN32_MALLOC_VALIDATE
31940 assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
31941 #endif
31942 if( pWinMemData->bOwned ){
31943 if( !HeapDestroy(pWinMemData->hHeap) ){
31944 sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
31945 GetLastError(), (void*)pWinMemData->hHeap);
31946 }
31947 pWinMemData->bOwned = FALSE;
31948 }
31949 pWinMemData->hHeap = NULL;
31950 }
31951 }
31952
31953 /*
31954 ** Populate the low-level memory allocation function pointers in
31955 ** sqlite3GlobalConfig.m with pointers to the routines in this file. The
31956 ** arguments specify the block of memory to manage.
31957 **
31958 ** This routine is only called by sqlite3_config(), and therefore
31959 ** is not required to be threadsafe (it is not).
31960 */
31961 SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
31962 static const sqlite3_mem_methods winMemMethods = {
31963 winMemMalloc,
31964 winMemFree,
31965 winMemRealloc,
31966 winMemSize,
31967 winMemRoundup,
31968 winMemInit,
31969 winMemShutdown,
31970 &win_mem_data
31971 };
31972 return &winMemMethods;
31973 }
31974
31975 SQLITE_PRIVATE void sqlite3MemSetDefault(void){
31976 sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
31977 }
31978 #endif /* SQLITE_WIN32_MALLOC */
31979
31980 /*
31981 ** Convert a UTF-8 string to microsoft unicode (UTF-16?).
31982 **
31983 ** Space to hold the returned string is obtained from malloc.
31984 */
@@ -31778,19 +32206,68 @@
32206 iLine, iErrno, zFunc, zPath, zMsg
32207 );
32208
32209 return errcode;
32210 }
32211
32212 /*
32213 ** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
32214 ** will be retried following a locking error - probably caused by
32215 ** antivirus software. Also the initial delay before the first retry.
32216 ** The delay increases linearly with each retry.
32217 */
32218 #ifndef SQLITE_WIN32_IOERR_RETRY
32219 # define SQLITE_WIN32_IOERR_RETRY 10
32220 #endif
32221 #ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
32222 # define SQLITE_WIN32_IOERR_RETRY_DELAY 25
32223 #endif
32224 static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
32225 static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
32226
32227 /*
32228 ** If a ReadFile() or WriteFile() error occurs, invoke this routine
32229 ** to see if it should be retried. Return TRUE to retry. Return FALSE
32230 ** to give up with an error.
32231 */
32232 static int retryIoerr(int *pnRetry){
32233 DWORD e;
32234 if( *pnRetry>=win32IoerrRetry ){
32235 return 0;
32236 }
32237 e = GetLastError();
32238 if( e==ERROR_ACCESS_DENIED ||
32239 e==ERROR_LOCK_VIOLATION ||
32240 e==ERROR_SHARING_VIOLATION ){
32241 Sleep(win32IoerrRetryDelay*(1+*pnRetry));
32242 ++*pnRetry;
32243 return 1;
32244 }
32245 return 0;
32246 }
32247
32248 /*
32249 ** Log a I/O error retry episode.
32250 */
32251 static void logIoerr(int nRetry){
32252 if( nRetry ){
32253 sqlite3_log(SQLITE_IOERR,
32254 "delayed %dms for lock/sharing conflict",
32255 win32IoerrRetryDelay*nRetry*(nRetry+1)/2
32256 );
32257 }
32258 }
32259
32260 #if SQLITE_OS_WINCE
32261 /*************************************************************************
32262 ** This section contains code for WinCE only.
32263 */
32264 /*
32265 ** WindowsCE does not have a localtime() function. So create a
32266 ** substitute.
32267 */
32268 /* #include <time.h> */
32269 struct tm *__cdecl localtime(const time_t *t)
32270 {
32271 static struct tm y;
32272 FILETIME uTm, lTm;
32273 SYSTEMTIME pTm;
@@ -32196,22 +32673,25 @@
32673 int amt, /* Number of bytes to read */
32674 sqlite3_int64 offset /* Begin reading at this offset */
32675 ){
32676 winFile *pFile = (winFile*)id; /* file handle */
32677 DWORD nRead; /* Number of bytes actually read from file */
32678 int nRetry = 0; /* Number of retrys */
32679
32680 assert( id!=0 );
32681 SimulateIOError(return SQLITE_IOERR_READ);
32682 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
32683
32684 if( seekWinFile(pFile, offset) ){
32685 return SQLITE_FULL;
32686 }
32687 while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
32688 if( retryIoerr(&nRetry) ) continue;
32689 pFile->lastErrno = GetLastError();
32690 return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
32691 }
32692 logIoerr(nRetry);
32693 if( nRead<(DWORD)amt ){
32694 /* Unread parts of the buffer must be zero-filled */
32695 memset(&((char*)pBuf)[nRead], 0, amt-nRead);
32696 return SQLITE_IOERR_SHORT_READ;
32697 }
@@ -32229,10 +32709,11 @@
32709 int amt, /* Number of bytes to write */
32710 sqlite3_int64 offset /* Offset into the file to begin writing at */
32711 ){
32712 int rc; /* True if error has occured, else false */
32713 winFile *pFile = (winFile*)id; /* File handle */
32714 int nRetry = 0; /* Number of retries */
32715
32716 assert( amt>0 );
32717 assert( pFile );
32718 SimulateIOError(return SQLITE_IOERR_WRITE);
32719 SimulateDiskfullError(return SQLITE_FULL);
@@ -32243,11 +32724,16 @@
32724 if( rc==0 ){
32725 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
32726 int nRem = amt; /* Number of bytes yet to be written */
32727 DWORD nWrite; /* Bytes written by each WriteFile() call */
32728
32729 while( nRem>0 ){
32730 if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
32731 if( retryIoerr(&nRetry) ) continue;
32732 break;
32733 }
32734 if( nWrite<=0 ) break;
32735 aRem += nWrite;
32736 nRem -= nWrite;
32737 }
32738 if( nRem>0 ){
32739 pFile->lastErrno = GetLastError();
@@ -32254,14 +32740,17 @@
32740 rc = 1;
32741 }
32742 }
32743
32744 if( rc ){
32745 if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
32746 || ( pFile->lastErrno==ERROR_DISK_FULL )){
32747 return SQLITE_FULL;
32748 }
32749 return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
32750 }else{
32751 logIoerr(nRetry);
32752 }
32753 return SQLITE_OK;
32754 }
32755
32756 /*
@@ -32651,32 +33140,63 @@
33140
33141 /*
33142 ** Control and query of the open file handle.
33143 */
33144 static int winFileControl(sqlite3_file *id, int op, void *pArg){
33145 winFile *pFile = (winFile*)id;
33146 switch( op ){
33147 case SQLITE_FCNTL_LOCKSTATE: {
33148 *(int*)pArg = pFile->locktype;
33149 return SQLITE_OK;
33150 }
33151 case SQLITE_LAST_ERRNO: {
33152 *(int*)pArg = (int)pFile->lastErrno;
33153 return SQLITE_OK;
33154 }
33155 case SQLITE_FCNTL_CHUNK_SIZE: {
33156 pFile->szChunk = *(int *)pArg;
33157 return SQLITE_OK;
33158 }
33159 case SQLITE_FCNTL_SIZE_HINT: {
33160 winFile *pFile = (winFile*)id;
33161 sqlite3_int64 oldSz;
33162 int rc = winFileSize(id, &oldSz);
33163 if( rc==SQLITE_OK ){
33164 sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
33165 if( newSz>oldSz ){
33166 SimulateIOErrorBenign(1);
33167 rc = winTruncate(id, newSz);
33168 SimulateIOErrorBenign(0);
33169 }
33170 }
33171 return rc;
33172 }
33173 case SQLITE_FCNTL_PERSIST_WAL: {
33174 int bPersist = *(int*)pArg;
33175 if( bPersist<0 ){
33176 *(int*)pArg = pFile->bPersistWal;
33177 }else{
33178 pFile->bPersistWal = bPersist!=0;
33179 }
33180 return SQLITE_OK;
33181 }
33182 case SQLITE_FCNTL_SYNC_OMITTED: {
33183 return SQLITE_OK;
33184 }
33185 case SQLITE_FCNTL_WIN32_AV_RETRY: {
33186 int *a = (int*)pArg;
33187 if( a[0]>0 ){
33188 win32IoerrRetry = a[0];
33189 }else{
33190 a[0] = win32IoerrRetry;
33191 }
33192 if( a[1]>0 ){
33193 win32IoerrRetryDelay = a[1];
33194 }else{
33195 a[1] = win32IoerrRetryDelay;
33196 }
33197 return SQLITE_OK;
33198 }
33199 }
33200 return SQLITE_NOTFOUND;
33201 }
33202
@@ -33482,10 +34002,11 @@
34002 int isTemp = 0;
34003 #endif
34004 winFile *pFile = (winFile*)id;
34005 void *zConverted; /* Filename in OS encoding */
34006 const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
34007 int cnt = 0;
34008
34009 /* If argument zPath is a NULL pointer, this function is required to open
34010 ** a temporary file. Use this buffer to store the file name in.
34011 */
34012 char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */
@@ -33601,34 +34122,34 @@
34122 #if SQLITE_OS_WINCE
34123 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
34124 #endif
34125
34126 if( isNT() ){
34127 while( (h = CreateFileW((WCHAR*)zConverted,
34128 dwDesiredAccess,
34129 dwShareMode, NULL,
34130 dwCreationDisposition,
34131 dwFlagsAndAttributes,
34132 NULL))==INVALID_HANDLE_VALUE &&
34133 retryIoerr(&cnt) ){}
 
34134 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
34135 ** Since the ASCII version of these Windows API do not exist for WINCE,
34136 ** it's important to not reference them for WINCE builds.
34137 */
34138 #if SQLITE_OS_WINCE==0
34139 }else{
34140 while( (h = CreateFileA((char*)zConverted,
34141 dwDesiredAccess,
34142 dwShareMode, NULL,
34143 dwCreationDisposition,
34144 dwFlagsAndAttributes,
34145 NULL))==INVALID_HANDLE_VALUE &&
34146 retryIoerr(&cnt) ){}
 
34147 #endif
34148 }
34149
34150 logIoerr(cnt);
34151
34152 OSTRACE(("OPEN %d %s 0x%lx %s\n",
34153 h, zName, dwDesiredAccess,
34154 h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
34155
@@ -33691,19 +34212,17 @@
34212 ** file open, we will be unable to delete it. To work around this
34213 ** problem, we delay 100 milliseconds and try to delete again. Up
34214 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
34215 ** up and returning an error.
34216 */
 
34217 static int winDelete(
34218 sqlite3_vfs *pVfs, /* Not used on win32 */
34219 const char *zFilename, /* Name of file to delete */
34220 int syncDir /* Not used on win32 */
34221 ){
34222 int cnt = 0;
34223 int rc;
 
34224 void *zConverted;
34225 UNUSED_PARAMETER(pVfs);
34226 UNUSED_PARAMETER(syncDir);
34227
34228 SimulateIOError(return SQLITE_IOERR_DELETE);
@@ -33710,38 +34229,34 @@
34229 zConverted = convertUtf8Filename(zFilename);
34230 if( zConverted==0 ){
34231 return SQLITE_NOMEM;
34232 }
34233 if( isNT() ){
34234 rc = 1;
34235 while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
34236 (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}
34237 rc = rc ? SQLITE_OK : SQLITE_ERROR;
 
 
34238 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
34239 ** Since the ASCII version of these Windows API do not exist for WINCE,
34240 ** it's important to not reference them for WINCE builds.
34241 */
34242 #if SQLITE_OS_WINCE==0
34243 }else{
34244 rc = 1;
34245 while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
34246 (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}
34247 rc = rc ? SQLITE_OK : SQLITE_ERROR;
 
 
34248 #endif
34249 }
34250 if( rc ){
34251 rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
34252 }else{
34253 logIoerr(cnt);
34254 }
34255 free(zConverted);
34256 OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
34257 return rc;
 
 
 
 
 
34258 }
34259
34260 /*
34261 ** Check the existance and status of a file.
34262 */
@@ -33760,15 +34275,17 @@
34275 zConverted = convertUtf8Filename(zFilename);
34276 if( zConverted==0 ){
34277 return SQLITE_NOMEM;
34278 }
34279 if( isNT() ){
34280 int cnt = 0;
34281 WIN32_FILE_ATTRIBUTE_DATA sAttrData;
34282 memset(&sAttrData, 0, sizeof(sAttrData));
34283 while( !(rc = GetFileAttributesExW((WCHAR*)zConverted,
34284 GetFileExInfoStandard,
34285 &sAttrData)) && retryIoerr(&cnt) ){}
34286 if( rc ){
34287 /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
34288 ** as if it does not exist.
34289 */
34290 if( flags==SQLITE_ACCESS_EXISTS
34291 && sAttrData.nFileSizeHigh==0
@@ -33776,10 +34293,11 @@
34293 attr = INVALID_FILE_ATTRIBUTES;
34294 }else{
34295 attr = sAttrData.dwFileAttributes;
34296 }
34297 }else{
34298 logIoerr(cnt);
34299 if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
34300 winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
34301 free(zConverted);
34302 return SQLITE_IOERR_ACCESS;
34303 }else{
@@ -33800,11 +34318,12 @@
34318 case SQLITE_ACCESS_READ:
34319 case SQLITE_ACCESS_EXISTS:
34320 rc = attr!=INVALID_FILE_ATTRIBUTES;
34321 break;
34322 case SQLITE_ACCESS_READWRITE:
34323 rc = attr!=INVALID_FILE_ATTRIBUTES &&
34324 (attr & FILE_ATTRIBUTE_READONLY)==0;
34325 break;
34326 default:
34327 assert(!"Invalid flags argument");
34328 }
34329 *pResOut = rc;
@@ -35256,10 +35775,13 @@
35775 typedef struct PCache1 PCache1;
35776 typedef struct PgHdr1 PgHdr1;
35777 typedef struct PgFreeslot PgFreeslot;
35778 typedef struct PGroup PGroup;
35779
35780 typedef struct PGroupBlock PGroupBlock;
35781 typedef struct PGroupBlockList PGroupBlockList;
35782
35783 /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
35784 ** of one or more PCaches that are able to recycle each others unpinned
35785 ** pages when they are under memory pressure. A PGroup is an instance of
35786 ** the following object.
35787 **
@@ -35285,12 +35807,70 @@
35807 int nMaxPage; /* Sum of nMax for purgeable caches */
35808 int nMinPage; /* Sum of nMin for purgeable caches */
35809 int mxPinned; /* nMaxpage + 10 - nMinPage */
35810 int nCurrentPage; /* Number of purgeable pages allocated */
35811 PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
35812 #ifdef SQLITE_PAGECACHE_BLOCKALLOC
35813 int isBusy; /* Do not run ReleaseMemory() if true */
35814 PGroupBlockList *pBlockList; /* List of block-lists for this group */
35815 #endif
35816 };
35817
35818 /*
35819 ** If SQLITE_PAGECACHE_BLOCKALLOC is defined when the library is built,
35820 ** each PGroup structure has a linked list of the the following starting
35821 ** at PGroup.pBlockList. There is one entry for each distinct page-size
35822 ** currently used by members of the PGroup (i.e. 1024 bytes, 4096 bytes
35823 ** etc.). Variable PGroupBlockList.nByte is set to the actual allocation
35824 ** size requested by each pcache, which is the database page-size plus
35825 ** the various header structures used by the pcache, pager and btree layers.
35826 ** Usually around (pgsz+200) bytes.
35827 **
35828 ** This size (pgsz+200) bytes is not allocated efficiently by some
35829 ** implementations of malloc. In particular, some implementations are only
35830 ** able to allocate blocks of memory chunks of 2^N bytes, where N is some
35831 ** integer value. Since the page-size is a power of 2, this means we
35832 ** end up wasting (pgsz-200) bytes in each allocation.
35833 **
35834 ** If SQLITE_PAGECACHE_BLOCKALLOC is defined, the (pgsz+200) byte blocks
35835 ** are not allocated directly. Instead, blocks of roughly M*(pgsz+200) bytes
35836 ** are requested from malloc allocator. After a block is returned,
35837 ** sqlite3MallocSize() is used to determine how many (pgsz+200) byte
35838 ** allocations can fit in the space returned by malloc(). This value may
35839 ** be more than M.
35840 **
35841 ** The blocks are stored in a doubly-linked list. Variable PGroupBlock.nEntry
35842 ** contains the number of allocations that will fit in the aData[] space.
35843 ** nEntry is limited to the number of bits in bitmask mUsed. If a slot
35844 ** within aData is in use, the corresponding bit in mUsed is set. Thus
35845 ** when (mUsed+1==(1 << nEntry)) the block is completely full.
35846 **
35847 ** Each time a slot within a block is freed, the block is moved to the start
35848 ** of the linked-list. And if a block becomes completely full, then it is
35849 ** moved to the end of the list. As a result, when searching for a free
35850 ** slot, only the first block in the list need be examined. If it is full,
35851 ** then it is guaranteed that all blocks are full.
35852 */
35853 struct PGroupBlockList {
35854 int nByte; /* Size of each allocation in bytes */
35855 PGroupBlock *pFirst; /* First PGroupBlock in list */
35856 PGroupBlock *pLast; /* Last PGroupBlock in list */
35857 PGroupBlockList *pNext; /* Next block-list attached to group */
35858 };
35859
35860 struct PGroupBlock {
35861 Bitmask mUsed; /* Mask of used slots */
35862 int nEntry; /* Maximum number of allocations in aData[] */
35863 u8 *aData; /* Pointer to data block */
35864 PGroupBlock *pNext; /* Next PGroupBlock in list */
35865 PGroupBlock *pPrev; /* Previous PGroupBlock in list */
35866 PGroupBlockList *pList; /* Owner list */
35867 };
35868
35869 /* Minimum value for PGroupBlock.nEntry */
35870 #define PAGECACHE_BLOCKALLOC_MINENTRY 15
35871
35872 /* Each page cache is an instance of the following object. Every
35873 ** open database file (including each in-memory database and each
35874 ** temporary or transient database) has a single page cache which
35875 ** is an instance of this object.
35876 **
@@ -35389,10 +35969,21 @@
35969 **
35970 ** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
35971 */
35972 #define PGHDR1_TO_PAGE(p) (void*)(((char*)p) - p->pCache->szPage)
35973 #define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)
35974
35975 /*
35976 ** Blocks used by the SQLITE_PAGECACHE_BLOCKALLOC blocks to store/retrieve
35977 ** a PGroupBlock pointer based on a pointer to a page buffer.
35978 */
35979 #define PAGE_SET_BLOCKPTR(pCache, pPg, pBlock) \
35980 ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) = pBlock )
35981
35982 #define PAGE_GET_BLOCKPTR(pCache, pPg) \
35983 ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) )
35984
35985
35986 /*
35987 ** Macros to enter and leave the PCache LRU mutex.
35988 */
35989 #define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
@@ -35515,25 +36106,159 @@
36106 return iSize;
36107 }
36108 }
36109 #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
36110
36111 #ifdef SQLITE_PAGECACHE_BLOCKALLOC
36112 /*
36113 ** The block pBlock belongs to list pList but is not currently linked in.
36114 ** Insert it into the start of the list.
36115 */
36116 static void addBlockToList(PGroupBlockList *pList, PGroupBlock *pBlock){
36117 pBlock->pPrev = 0;
36118 pBlock->pNext = pList->pFirst;
36119 pList->pFirst = pBlock;
36120 if( pBlock->pNext ){
36121 pBlock->pNext->pPrev = pBlock;
36122 }else{
36123 assert( pList->pLast==0 );
36124 pList->pLast = pBlock;
36125 }
36126 }
36127
36128 /*
36129 ** If there are no blocks in the list headed by pList, remove pList
36130 ** from the pGroup->pBlockList list and free it with sqlite3_free().
36131 */
36132 static void freeListIfEmpty(PGroup *pGroup, PGroupBlockList *pList){
36133 assert( sqlite3_mutex_held(pGroup->mutex) );
36134 if( pList->pFirst==0 ){
36135 PGroupBlockList **pp;
36136 for(pp=&pGroup->pBlockList; *pp!=pList; pp=&(*pp)->pNext);
36137 *pp = (*pp)->pNext;
36138 sqlite3_free(pList);
36139 }
36140 }
36141 #endif /* SQLITE_PAGECACHE_BLOCKALLOC */
36142
36143 /*
36144 ** Allocate a new page object initially associated with cache pCache.
36145 */
36146 static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
36147 int nByte = sizeof(PgHdr1) + pCache->szPage;
36148 void *pPg = 0;
36149 PgHdr1 *p;
36150
36151 #ifdef SQLITE_PAGECACHE_BLOCKALLOC
36152 PGroup *pGroup = pCache->pGroup;
36153 PGroupBlockList *pList;
36154 PGroupBlock *pBlock;
36155 int i;
36156
36157 nByte += sizeof(PGroupBlockList *);
36158 nByte = ROUND8(nByte);
36159
36160 for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
36161 if( pList->nByte==nByte ) break;
36162 }
36163 if( pList==0 ){
36164 PGroupBlockList *pNew;
36165 assert( pGroup->isBusy==0 );
36166 assert( sqlite3_mutex_held(pGroup->mutex) );
36167 pGroup->isBusy = 1; /* Disable sqlite3PcacheReleaseMemory() */
36168 pNew = (PGroupBlockList *)sqlite3MallocZero(sizeof(PGroupBlockList));
36169 pGroup->isBusy = 0; /* Reenable sqlite3PcacheReleaseMemory() */
36170 if( pNew==0 ){
36171 /* malloc() failure. Return early. */
36172 return 0;
36173 }
36174 #ifdef SQLITE_DEBUG
36175 for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
36176 assert( pList->nByte!=nByte );
36177 }
36178 #endif
36179 pNew->nByte = nByte;
36180 pNew->pNext = pGroup->pBlockList;
36181 pGroup->pBlockList = pNew;
36182 pList = pNew;
36183 }
36184
36185 pBlock = pList->pFirst;
36186 if( pBlock==0 || pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) ){
36187 int sz;
36188
36189 /* Allocate a new block. Try to allocate enough space for the PGroupBlock
36190 ** structure and MINENTRY allocations of nByte bytes each. If the
36191 ** allocator returns more memory than requested, then more than MINENTRY
36192 ** allocations may fit in it. */
36193 assert( sqlite3_mutex_held(pGroup->mutex) );
36194 pcache1LeaveMutex(pCache->pGroup);
36195 sz = sizeof(PGroupBlock) + PAGECACHE_BLOCKALLOC_MINENTRY * nByte;
36196 pBlock = (PGroupBlock *)sqlite3Malloc(sz);
36197 pcache1EnterMutex(pCache->pGroup);
36198
36199 if( !pBlock ){
36200 freeListIfEmpty(pGroup, pList);
36201 return 0;
36202 }
36203 pBlock->nEntry = (sqlite3MallocSize(pBlock) - sizeof(PGroupBlock)) / nByte;
36204 if( pBlock->nEntry>=BMS ){
36205 pBlock->nEntry = BMS-1;
36206 }
36207 pBlock->pList = pList;
36208 pBlock->mUsed = 0;
36209 pBlock->aData = (u8 *)&pBlock[1];
36210 addBlockToList(pList, pBlock);
36211
36212 sz = sqlite3MallocSize(pBlock);
36213 sqlite3_mutex_enter(pcache1.mutex);
36214 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
36215 sqlite3_mutex_leave(pcache1.mutex);
36216 }
36217
36218 for(i=0; pPg==0 && ALWAYS(i<pBlock->nEntry); i++){
36219 if( 0==(pBlock->mUsed & ((Bitmask)1<<i)) ){
36220 pBlock->mUsed |= ((Bitmask)1<<i);
36221 pPg = (void *)&pBlock->aData[pList->nByte * i];
36222 }
36223 }
36224 assert( pPg );
36225 PAGE_SET_BLOCKPTR(pCache, pPg, pBlock);
36226
36227 /* If the block is now full, shift it to the end of the list */
36228 if( pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) && pList->pLast!=pBlock ){
36229 assert( pList->pFirst==pBlock );
36230 assert( pBlock->pPrev==0 );
36231 assert( pList->pLast->pNext==0 );
36232 pList->pFirst = pBlock->pNext;
36233 pList->pFirst->pPrev = 0;
36234 pBlock->pPrev = pList->pLast;
36235 pBlock->pNext = 0;
36236 pList->pLast->pNext = pBlock;
36237 pList->pLast = pBlock;
36238 }
36239 p = PAGE_TO_PGHDR1(pCache, pPg);
36240 if( pCache->bPurgeable ){
36241 pCache->pGroup->nCurrentPage++;
36242 }
36243 #else
36244 /* The group mutex must be released before pcache1Alloc() is called. This
36245 ** is because it may call sqlite3_release_memory(), which assumes that
36246 ** this mutex is not held. */
36247 assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
36248 pcache1LeaveMutex(pCache->pGroup);
36249 pPg = pcache1Alloc(nByte);
36250 pcache1EnterMutex(pCache->pGroup);
36251 if( pPg ){
36252 p = PAGE_TO_PGHDR1(pCache, pPg);
36253 if( pCache->bPurgeable ){
36254 pCache->pGroup->nCurrentPage++;
36255 }
36256 }else{
36257 p = 0;
36258 }
36259 #endif
36260 return p;
36261 }
36262
36263 /*
36264 ** Free a page object allocated by pcache1AllocPage().
@@ -35543,14 +36268,56 @@
36268 ** with a NULL pointer, so we mark the NULL test with ALWAYS().
36269 */
36270 static void pcache1FreePage(PgHdr1 *p){
36271 if( ALWAYS(p) ){
36272 PCache1 *pCache = p->pCache;
36273 void *pPg = PGHDR1_TO_PAGE(p);
36274
36275 #ifdef SQLITE_PAGECACHE_BLOCKALLOC
36276 PGroupBlock *pBlock = PAGE_GET_BLOCKPTR(pCache, pPg);
36277 PGroupBlockList *pList = pBlock->pList;
36278 int i = ((u8 *)pPg - pBlock->aData) / pList->nByte;
36279
36280 assert( pPg==(void *)&pBlock->aData[i*pList->nByte] );
36281 assert( pBlock->mUsed & ((Bitmask)1<<i) );
36282 pBlock->mUsed &= ~((Bitmask)1<<i);
36283
36284 /* Remove the block from the list. If it is completely empty, free it.
36285 ** Or if it is not completely empty, re-insert it at the start of the
36286 ** list. */
36287 if( pList->pFirst==pBlock ){
36288 pList->pFirst = pBlock->pNext;
36289 if( pList->pFirst ) pList->pFirst->pPrev = 0;
36290 }else{
36291 pBlock->pPrev->pNext = pBlock->pNext;
36292 }
36293 if( pList->pLast==pBlock ){
36294 pList->pLast = pBlock->pPrev;
36295 if( pList->pLast ) pList->pLast->pNext = 0;
36296 }else{
36297 pBlock->pNext->pPrev = pBlock->pPrev;
36298 }
36299
36300 if( pBlock->mUsed==0 ){
36301 PGroup *pGroup = p->pCache->pGroup;
36302
36303 int sz = sqlite3MallocSize(pBlock);
36304 sqlite3_mutex_enter(pcache1.mutex);
36305 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -sz);
36306 sqlite3_mutex_leave(pcache1.mutex);
36307 freeListIfEmpty(pGroup, pList);
36308 sqlite3_free(pBlock);
36309 }else{
36310 addBlockToList(pList, pBlock);
36311 }
36312 #else
36313 assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
36314 pcache1Free(pPg);
36315 #endif
36316 if( pCache->bPurgeable ){
36317 pCache->pGroup->nCurrentPage--;
36318 }
 
36319 }
36320 }
36321
36322 /*
36323 ** Malloc function used by SQLite to obtain space from the buffer configured
@@ -35984,13 +36751,11 @@
36751 /* Step 5. If a usable page buffer has still not been found,
36752 ** attempt to allocate a new one.
36753 */
36754 if( !pPage ){
36755 if( createFlag==1 ) sqlite3BeginBenignMalloc();
 
36756 pPage = pcache1AllocPage(pCache);
 
36757 if( createFlag==1 ) sqlite3EndBenignMalloc();
36758 }
36759
36760 if( pPage ){
36761 unsigned int h = iKey % pCache->nHash;
@@ -36156,10 +36921,13 @@
36921 ** been released, the function returns. The return value is the total number
36922 ** of bytes of memory released.
36923 */
36924 SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
36925 int nFree = 0;
36926 #ifdef SQLITE_PAGECACHE_BLOCKALLOC
36927 if( pcache1.grp.isBusy ) return 0;
36928 #endif
36929 assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
36930 assert( sqlite3_mutex_notheld(pcache1.mutex) );
36931 if( pcache1.pStart==0 ){
36932 PgHdr1 *p;
36933 pcache1EnterMutex(&pcache1.grp);
@@ -37368,10 +38136,12 @@
38136 u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
38137 u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
38138 u8 tempFile; /* zFilename is a temporary file */
38139 u8 readOnly; /* True for a read-only database */
38140 u8 memDb; /* True to inhibit all file I/O */
38141 u8 hasSeenStress; /* pagerStress() called one or more times */
38142 u8 isSorter; /* True for a PAGER_SORTER */
38143
38144 /**************************************************************************
38145 ** The following block contains those class members that change during
38146 ** routine opertion. Class members not in this block are either fixed
38147 ** when the pager is first created or else only change when there is a
@@ -37590,10 +38360,19 @@
38360 || p->journalMode==PAGER_JOURNALMODE_MEMORY
38361 );
38362 assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
38363 assert( pagerUseWal(p)==0 );
38364 }
38365
38366 /* A sorter is a temp file that never spills to disk and always has
38367 ** the doNotSpill flag set
38368 */
38369 if( p->isSorter ){
38370 assert( p->tempFile );
38371 assert( p->doNotSpill );
38372 assert( p->fd->pMethods==0 );
38373 }
38374
38375 /* If changeCountDone is set, a RESERVED lock or greater must be held
38376 ** on the file.
38377 */
38378 assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
@@ -40487,10 +41266,11 @@
41266 ** to the caller.
41267 */
41268 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
41269 u8 *pTmp = (u8 *)pPager->pTmpSpace;
41270
41271 assert( assert_pager_state(pPager) );
41272 disable_simulated_io_errors();
41273 sqlite3BeginBenignMalloc();
41274 /* pPager->errCode = 0; */
41275 pPager->exclusiveMode = 0;
41276 #ifndef SQLITE_OMIT_WAL
@@ -40921,10 +41701,11 @@
41701 ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1
41702 ** while in the error state, hence it is impossible for this routine to
41703 ** be called in the error state. Nevertheless, we include a NEVER()
41704 ** test for the error state as a safeguard against future changes.
41705 */
41706 pPager->hasSeenStress = 1;
41707 if( NEVER(pPager->errCode) ) return SQLITE_OK;
41708 if( pPager->doNotSpill ) return SQLITE_OK;
41709 if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
41710 return SQLITE_OK;
41711 }
@@ -41292,10 +42073,16 @@
42073 }
42074 /* pPager->xBusyHandler = 0; */
42075 /* pPager->pBusyHandlerArg = 0; */
42076 pPager->xReiniter = xReinit;
42077 /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
42078 #ifndef SQLITE_OMIT_MERGE_SORT
42079 if( flags & PAGER_SORTER ){
42080 pPager->doNotSpill = 1;
42081 pPager->isSorter = 1;
42082 }
42083 #endif
42084
42085 *ppPager = pPager;
42086 return SQLITE_OK;
42087 }
42088
@@ -42835,10 +43622,21 @@
43622 ** Return true if this is an in-memory pager.
43623 */
43624 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
43625 return MEMDB;
43626 }
43627
43628 #ifndef SQLITE_OMIT_MERGE_SORT
43629 /*
43630 ** Return true if the pager has seen a pagerStress callback.
43631 */
43632 SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager *pPager){
43633 assert( pPager->isSorter );
43634 assert( pPager->doNotSpill );
43635 return pPager->hasSeenStress;
43636 }
43637 #endif
43638
43639 /*
43640 ** Check that there are at least nSavepoint savepoints open. If there are
43641 ** currently less than nSavepoints open, then open one or more savepoints
43642 ** to make up the difference. If the number of savepoints is already
@@ -45384,17 +46182,19 @@
46182 **
46183 ** The EXCLUSIVE lock is not released before returning.
46184 */
46185 rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
46186 if( rc==SQLITE_OK ){
46187 int bPersistWal = -1;
46188 if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
46189 pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
46190 }
46191 rc = sqlite3WalCheckpoint(
46192 pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
46193 );
46194 sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
46195 if( rc==SQLITE_OK && bPersistWal!=1 ){
46196 isDelete = 1;
46197 }
46198 }
46199
46200 walIndexClose(pWal, isDelete);
@@ -49202,15 +50002,26 @@
50002 assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
50003
50004 /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
50005 assert( (flags & BTREE_SINGLE)==0 || isTempDb );
50006
50007 /* The BTREE_SORTER flag is only used if SQLITE_OMIT_MERGE_SORT is undef */
50008 #ifdef SQLITE_OMIT_MERGE_SORT
50009 assert( (flags & BTREE_SORTER)==0 );
50010 #endif
50011
50012 /* BTREE_SORTER is always on a BTREE_SINGLE, BTREE_OMIT_JOURNAL */
50013 assert( (flags & BTREE_SORTER)==0 ||
50014 (flags & (BTREE_SINGLE|BTREE_OMIT_JOURNAL))
50015 ==(BTREE_SINGLE|BTREE_OMIT_JOURNAL) );
50016
50017 if( db->flags & SQLITE_NoReadlock ){
50018 flags |= BTREE_NO_READLOCK;
50019 }
50020 if( isMemdb ){
50021 flags |= BTREE_MEMORY;
50022 flags &= ~BTREE_SORTER;
50023 }
50024 if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
50025 vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
50026 }
50027 p = sqlite3MallocZero(sizeof(Btree));
@@ -50936,11 +51747,12 @@
51747
51748 if( NEVER(wrFlag && pBt->readOnly) ){
51749 return SQLITE_READONLY;
51750 }
51751 if( iTable==1 && btreePagecount(pBt)==0 ){
51752 assert( wrFlag==0 );
51753 iTable = 0;
51754 }
51755
51756 /* Now that no other errors can occur, finish filling in the BtCursor
51757 ** variables and link the cursor into the BtShared list. */
51758 pCur->pgnoRoot = (Pgno)iTable;
@@ -51690,10 +52502,13 @@
52502 int i;
52503 for(i=1; i<=pCur->iPage; i++){
52504 releasePage(pCur->apPage[i]);
52505 }
52506 pCur->iPage = 0;
52507 }else if( pCur->pgnoRoot==0 ){
52508 pCur->eState = CURSOR_INVALID;
52509 return SQLITE_OK;
52510 }else{
52511 rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
52512 if( rc!=SQLITE_OK ){
52513 pCur->eState = CURSOR_INVALID;
52514 return rc;
@@ -51799,11 +52614,11 @@
52614 assert( cursorHoldsMutex(pCur) );
52615 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
52616 rc = moveToRoot(pCur);
52617 if( rc==SQLITE_OK ){
52618 if( pCur->eState==CURSOR_INVALID ){
52619 assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
52620 *pRes = 1;
52621 }else{
52622 assert( pCur->apPage[pCur->iPage]->nCell>0 );
52623 *pRes = 0;
52624 rc = moveToLeftmost(pCur);
@@ -51838,11 +52653,11 @@
52653 }
52654
52655 rc = moveToRoot(pCur);
52656 if( rc==SQLITE_OK ){
52657 if( CURSOR_INVALID==pCur->eState ){
52658 assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
52659 *pRes = 1;
52660 }else{
52661 assert( pCur->eState==CURSOR_VALID );
52662 *pRes = 0;
52663 rc = moveToRightmost(pCur);
@@ -51911,16 +52726,16 @@
52726
52727 rc = moveToRoot(pCur);
52728 if( rc ){
52729 return rc;
52730 }
52731 assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
52732 assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
52733 assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
52734 if( pCur->eState==CURSOR_INVALID ){
52735 *pRes = -1;
52736 assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
52737 return SQLITE_OK;
52738 }
52739 assert( pCur->apPage[0]->intKey || pIdxKey );
52740 for(;;){
52741 int lwr, upr, idx;
@@ -54745,13 +55560,20 @@
55560 releasePage(pPage);
55561 }
55562 return rc;
55563 }
55564 SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
55565 BtShared *pBt = p->pBt;
55566 int rc;
55567 sqlite3BtreeEnter(p);
55568 if( (pBt->openFlags&BTREE_SINGLE) ){
55569 pBt->nPage = 0;
55570 sqlite3PagerTruncateImage(pBt->pPager, 1);
55571 rc = newDatabase(pBt);
55572 }else{
55573 rc = btreeDropTable(p, iTable, piMoved);
55574 }
55575 sqlite3BtreeLeave(p);
55576 return rc;
55577 }
55578
55579
@@ -54826,10 +55648,15 @@
55648 ** corruption) an SQLite error code is returned.
55649 */
55650 SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
55651 i64 nEntry = 0; /* Value to return in *pnEntry */
55652 int rc; /* Return code */
55653
55654 if( pCur->pgnoRoot==0 ){
55655 *pnEntry = 0;
55656 return SQLITE_OK;
55657 }
55658 rc = moveToRoot(pCur);
55659
55660 /* Unless an error occurs, the following loop runs one iteration for each
55661 ** page in the B-Tree structure (not including overflow pages).
55662 */
@@ -55610,11 +56437,10 @@
56437 */
56438 SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
56439 BtShared *pBt = pBtree->pBt;
56440 int rc; /* Return code */
56441
 
56442 assert( iVersion==1 || iVersion==2 );
56443
56444 /* If setting the version fields to 1, do not automatically open the
56445 ** WAL connection, even if the version fields are currently set to 2.
56446 */
@@ -56049,106 +56875,110 @@
56875 /* Update the schema version field in the destination database. This
56876 ** is to make sure that the schema-version really does change in
56877 ** the case where the source and destination databases have the
56878 ** same schema version.
56879 */
56880 if( rc==SQLITE_DONE ){
56881 rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
56882 if( rc==SQLITE_OK ){
56883 if( p->pDestDb ){
56884 sqlite3ResetInternalSchema(p->pDestDb, -1);
56885 }
56886 if( destMode==PAGER_JOURNALMODE_WAL ){
56887 rc = sqlite3BtreeSetVersion(p->pDest, 2);
56888 }
56889 }
56890 if( rc==SQLITE_OK ){
56891 int nDestTruncate;
56892 /* Set nDestTruncate to the final number of pages in the destination
56893 ** database. The complication here is that the destination page
56894 ** size may be different to the source page size.
56895 **
56896 ** If the source page size is smaller than the destination page size,
56897 ** round up. In this case the call to sqlite3OsTruncate() below will
56898 ** fix the size of the file. However it is important to call
56899 ** sqlite3PagerTruncateImage() here so that any pages in the
56900 ** destination file that lie beyond the nDestTruncate page mark are
56901 ** journalled by PagerCommitPhaseOne() before they are destroyed
56902 ** by the file truncation.
56903 */
56904 assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
56905 assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
56906 if( pgszSrc<pgszDest ){
56907 int ratio = pgszDest/pgszSrc;
56908 nDestTruncate = (nSrcPage+ratio-1)/ratio;
56909 if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
56910 nDestTruncate--;
56911 }
56912 }else{
56913 nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
56914 }
56915 sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
56916
56917 if( pgszSrc<pgszDest ){
56918 /* If the source page-size is smaller than the destination page-size,
56919 ** two extra things may need to happen:
56920 **
56921 ** * The destination may need to be truncated, and
56922 **
56923 ** * Data stored on the pages immediately following the
56924 ** pending-byte page in the source database may need to be
56925 ** copied into the destination database.
56926 */
56927 const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
56928 sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
56929 i64 iOff;
56930 i64 iEnd;
56931
56932 assert( pFile );
56933 assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
56934 nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
56935 && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
56936 ));
56937
56938 /* This call ensures that all data required to recreate the original
56939 ** database has been stored in the journal for pDestPager and the
56940 ** journal synced to disk. So at this point we may safely modify
56941 ** the database file in any way, knowing that if a power failure
56942 ** occurs, the original database will be reconstructed from the
56943 ** journal file. */
56944 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
56945
56946 /* Write the extra pages and truncate the database file as required */
56947 iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
56948 for(
56949 iOff=PENDING_BYTE+pgszSrc;
56950 rc==SQLITE_OK && iOff<iEnd;
56951 iOff+=pgszSrc
56952 ){
56953 PgHdr *pSrcPg = 0;
56954 const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
56955 rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
56956 if( rc==SQLITE_OK ){
56957 u8 *zData = sqlite3PagerGetData(pSrcPg);
56958 rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
56959 }
56960 sqlite3PagerUnref(pSrcPg);
56961 }
56962 if( rc==SQLITE_OK ){
56963 rc = backupTruncateFile(pFile, iSize);
56964 }
56965
56966 /* Sync the database file to disk. */
56967 if( rc==SQLITE_OK ){
56968 rc = sqlite3PagerSync(pDestPager);
56969 }
56970 }else{
56971 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
56972 }
56973
56974 /* Finish committing the transaction to the destination database. */
56975 if( SQLITE_OK==rc
56976 && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
56977 ){
56978 rc = SQLITE_DONE;
56979 }
56980 }
56981 }
56982
56983 /* If bCloseTrans is true, then this function opened a read transaction
56984 ** on the source database. Close the read transaction here. There is
@@ -56612,38 +57442,32 @@
57442 ** invoking an external callback, free it now. Calling this function
57443 ** does not free any Mem.zMalloc buffer.
57444 */
57445 SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
57446 assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
57447 if( p->flags&MEM_Agg ){
57448 sqlite3VdbeMemFinalize(p, p->u.pDef);
57449 assert( (p->flags & MEM_Agg)==0 );
57450 sqlite3VdbeMemRelease(p);
57451 }else if( p->flags&MEM_Dyn && p->xDel ){
57452 assert( (p->flags&MEM_RowSet)==0 );
57453 p->xDel((void *)p->z);
57454 p->xDel = 0;
57455 }else if( p->flags&MEM_RowSet ){
57456 sqlite3RowSetClear(p->u.pRowSet);
57457 }else if( p->flags&MEM_Frame ){
57458 sqlite3VdbeMemSetNull(p);
 
 
 
 
 
 
57459 }
57460 }
57461
57462 /*
57463 ** Release any memory held by the Mem. This may leave the Mem in an
57464 ** inconsistent state, for example with (Mem.z==0) and
57465 ** (Mem.type==SQLITE_TEXT).
57466 */
57467 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
57468 MemReleaseExt(p);
57469 sqlite3DbFree(p->db, p->zMalloc);
57470 p->z = 0;
57471 p->zMalloc = 0;
57472 p->xDel = 0;
57473 }
@@ -56961,11 +57785,11 @@
57785 ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
57786 ** and flags gets srcType (either MEM_Ephem or MEM_Static).
57787 */
57788 SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
57789 assert( (pFrom->flags & MEM_RowSet)==0 );
57790 MemReleaseExt(pTo);
57791 memcpy(pTo, pFrom, MEMCELLSIZE);
57792 pTo->xDel = 0;
57793 if( (pFrom->flags&MEM_Static)==0 ){
57794 pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
57795 assert( srcType==MEM_Ephem || srcType==MEM_Static );
@@ -56979,11 +57803,11 @@
57803 */
57804 SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
57805 int rc = SQLITE_OK;
57806
57807 assert( (pFrom->flags & MEM_RowSet)==0 );
57808 MemReleaseExt(pTo);
57809 memcpy(pTo, pFrom, MEMCELLSIZE);
57810 pTo->flags &= ~MEM_Dyn;
57811
57812 if( pTo->flags&(MEM_Str|MEM_Blob) ){
57813 if( 0==(pFrom->flags&MEM_Static) ){
@@ -57934,10 +58758,16 @@
58758 assert( p->nOp - i >= 3 );
58759 assert( pOp[-1].opcode==OP_Integer );
58760 n = pOp[-1].p1;
58761 if( n>nMaxArgs ) nMaxArgs = n;
58762 #endif
58763 }else if( opcode==OP_Next ){
58764 pOp->p4.xAdvance = sqlite3BtreeNext;
58765 pOp->p4type = P4_ADVANCE;
58766 }else if( opcode==OP_Prev ){
58767 pOp->p4.xAdvance = sqlite3BtreePrevious;
58768 pOp->p4type = P4_ADVANCE;
58769 }
58770
58771 if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
58772 assert( -1-pOp->p2<p->nLabel );
58773 pOp->p2 = aLabel[-1-pOp->p2];
@@ -58025,37 +58855,34 @@
58855 ** Change the value of the P1 operand for a specific instruction.
58856 ** This routine is useful when a large program is loaded from a
58857 ** static array using sqlite3VdbeAddOpList but we want to make a
58858 ** few minor changes to the program.
58859 */
58860 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
58861 assert( p!=0 );
58862 if( ((u32)p->nOp)>addr ){
 
58863 p->aOp[addr].p1 = val;
58864 }
58865 }
58866
58867 /*
58868 ** Change the value of the P2 operand for a specific instruction.
58869 ** This routine is useful for setting a jump destination.
58870 */
58871 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
58872 assert( p!=0 );
58873 if( ((u32)p->nOp)>addr ){
 
58874 p->aOp[addr].p2 = val;
58875 }
58876 }
58877
58878 /*
58879 ** Change the value of the P3 operand for a specific instruction.
58880 */
58881 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
58882 assert( p!=0 );
58883 if( ((u32)p->nOp)>addr ){
 
58884 p->aOp[addr].p3 = val;
58885 }
58886 }
58887
58888 /*
@@ -58442,10 +59269,14 @@
59269 break;
59270 }
59271 case P4_SUBPROGRAM: {
59272 sqlite3_snprintf(nTemp, zTemp, "program");
59273 break;
59274 }
59275 case P4_ADVANCE: {
59276 zTemp[0] = 0;
59277 break;
59278 }
59279 default: {
59280 zP4 = pOp->p4.z;
59281 if( zP4==0 ){
59282 zP4 = zTemp;
@@ -59006,10 +59837,11 @@
59837 nMem = 10;
59838 }
59839 memset(zCsr, 0, zEnd-zCsr);
59840 zCsr += (zCsr - (u8*)0)&7;
59841 assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
59842 p->expired = 0;
59843
59844 /* Memory for registers, parameters, cursor, etc, is allocated in two
59845 ** passes. On the first pass, we try to reuse unused space at the
59846 ** end of the opcode array. If we are unable to satisfy all memory
59847 ** requirements by reusing the opcode array tail, then the second
@@ -59065,10 +59897,11 @@
59897 */
59898 SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
59899 if( pCx==0 ){
59900 return;
59901 }
59902 sqlite3VdbeSorterClose(p->db, pCx);
59903 if( pCx->pBt ){
59904 sqlite3BtreeClose(pCx->pBt);
59905 /* The pCx->pCursor will be close automatically, if it exists, by
59906 ** the call above. */
59907 }else if( pCx->pCursor ){
@@ -61205,10 +62038,18 @@
62038 rc = db->errCode = p->rc;
62039 }
62040 return (rc&db->errMask);
62041 }
62042
62043 /*
62044 ** The maximum number of times that a statement will try to reparse
62045 ** itself before giving up and returning SQLITE_SCHEMA.
62046 */
62047 #ifndef SQLITE_MAX_SCHEMA_RETRY
62048 # define SQLITE_MAX_SCHEMA_RETRY 5
62049 #endif
62050
62051 /*
62052 ** This is the top-level implementation of sqlite3_step(). Call
62053 ** sqlite3Step() to do most of the work. If a schema error occurs,
62054 ** call sqlite3Reprepare() and try again.
62055 */
@@ -61223,14 +62064,14 @@
62064 return SQLITE_MISUSE_BKPT;
62065 }
62066 db = v->db;
62067 sqlite3_mutex_enter(db->mutex);
62068 while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
62069 && cnt++ < SQLITE_MAX_SCHEMA_RETRY
62070 && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
62071 sqlite3_reset(pStmt);
62072 assert( v->expired==0 );
62073 }
62074 if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
62075 /* This case occurs after failing to recompile an sql statement.
62076 ** The error message from the SQL compiler has already been loaded
62077 ** into the database handle. This block copies the error message
@@ -62357,10 +63198,17 @@
63198 ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
63199 ** P if required.
63200 */
63201 #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
63202
63203 /* Return true if the cursor was opened using the OP_OpenSorter opcode. */
63204 #ifdef SQLITE_OMIT_MERGE_SORT
63205 # define isSorter(x) 0
63206 #else
63207 # define isSorter(x) ((x)->pSorter!=0)
63208 #endif
63209
63210 /*
63211 ** Argument pMem points at a register that will be passed to a
63212 ** user-defined function or returned to the user as the result of a query.
63213 ** This routine sets the pMem->type variable used by the sqlite3_value_*()
63214 ** routines.
@@ -62951,10 +63799,11 @@
63799 u8 *zEndHdr; /* Pointer to first byte after the header */
63800 u32 offset; /* Offset into the data */
63801 u32 szField; /* Number of bytes in the content of a field */
63802 int szHdr; /* Size of the header size field at start of record */
63803 int avail; /* Number of bytes of available data */
63804 u32 t; /* A type code from the record header */
63805 Mem *pReg; /* PseudoTable input register */
63806 } am;
63807 struct OP_Affinity_stack_vars {
63808 const char *zAffinity; /* The affinity to be applied */
63809 char cAff; /* A single character of affinity */
@@ -63109,11 +63958,10 @@
63958 BtCursor *pCrsr;
63959 int res;
63960 } bl;
63961 struct OP_Next_stack_vars {
63962 VdbeCursor *pC;
 
63963 int res;
63964 } bm;
63965 struct OP_IdxInsert_stack_vars {
63966 VdbeCursor *pC;
63967 BtCursor *pCrsr;
@@ -63363,11 +64211,11 @@
64211 if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
64212 assert( pOp->p2>0 );
64213 assert( pOp->p2<=p->nMem );
64214 pOut = &aMem[pOp->p2];
64215 memAboutToChange(p, pOut);
64216 MemReleaseExt(pOut);
64217 pOut->flags = MEM_Int;
64218 }
64219
64220 /* Sanity checking on other operands */
64221 #ifdef SQLITE_DEBUG
@@ -63496,11 +64344,11 @@
64344 break;
64345 }
64346
64347 /* Opcode: HaltIfNull P1 P2 P3 P4 *
64348 **
64349 ** Check the value in register P3. If it is NULL then Halt using
64350 ** parameter P1, P2, and P4 as if this were a Halt instruction. If the
64351 ** value in register P3 is not NULL, then this routine is a no-op.
64352 */
64353 case OP_HaltIfNull: { /* in3 */
64354 pIn3 = &aMem[pOp->p3];
@@ -63730,10 +64578,15 @@
64578 assert( memIsValid(pIn1) );
64579 memAboutToChange(p, pOut);
64580 u.ac.zMalloc = pOut->zMalloc;
64581 pOut->zMalloc = 0;
64582 sqlite3VdbeMemMove(pOut, pIn1);
64583 #ifdef SQLITE_DEBUG
64584 if( pOut->pScopyFrom>=&aMem[u.ac.p1] && pOut->pScopyFrom<&aMem[u.ac.p1+pOp->p3] ){
64585 pOut->pScopyFrom += u.ac.p1 - pOp->p2;
64586 }
64587 #endif
64588 pIn1->zMalloc = u.ac.zMalloc;
64589 REGISTER_TRACE(u.ac.p2++, pOut);
64590 pIn1++;
64591 pOut++;
64592 }
@@ -64433,11 +65286,11 @@
65286 ** additional information.
65287 **
65288 ** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
65289 ** true or false and is never NULL. If both operands are NULL then the result
65290 ** of comparison is false. If either operand is NULL then the result is true.
65291 ** If neither operand is NULL the result is the same as it would be if
65292 ** the SQLITE_NULLEQ flag were omitted from P5.
65293 */
65294 /* Opcode: Eq P1 P2 P3 P4 P5
65295 **
65296 ** This works just like the Lt opcode except that the jump is taken if
@@ -64445,11 +65298,11 @@
65298 ** See the Lt opcode for additional information.
65299 **
65300 ** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
65301 ** true or false and is never NULL. If both operands are NULL then the result
65302 ** of comparison is true. If either operand is NULL then the result is false.
65303 ** If neither operand is NULL the result is the same as it would be if
65304 ** the SQLITE_NULLEQ flag were omitted from P5.
65305 */
65306 /* Opcode: Le P1 P2 P3 P4 P5
65307 **
65308 ** This works just like the Lt opcode except that the jump is taken if
@@ -64730,17 +65583,17 @@
65583 break;
65584 }
65585
65586 /* Opcode: If P1 P2 P3 * *
65587 **
65588 ** Jump to P2 if the value in register P1 is true. The value
65589 ** is considered true if it is numeric and non-zero. If the value
65590 ** in P1 is NULL then take the jump if P3 is true.
65591 */
65592 /* Opcode: IfNot P1 P2 P3 * *
65593 **
65594 ** Jump to P2 if the value in register P1 is False. The value
65595 ** is considered true if it has a numeric value of zero. If the value
65596 ** in P1 is NULL then take the jump if P3 is true.
65597 */
65598 case OP_If: /* jump, in1 */
65599 case OP_IfNot: { /* jump, in1 */
@@ -64828,10 +65681,11 @@
65681 u8 *zEndHdr; /* Pointer to first byte after the header */
65682 u32 offset; /* Offset into the data */
65683 u32 szField; /* Number of bytes in the content of a field */
65684 int szHdr; /* Size of the header size field at start of record */
65685 int avail; /* Number of bytes of available data */
65686 u32 t; /* A type code from the record header */
65687 Mem *pReg; /* PseudoTable input register */
65688 #endif /* local variables moved into u.am */
65689
65690
65691 u.am.p1 = pOp->p1;
@@ -64840,11 +65694,10 @@
65694 memset(&u.am.sMem, 0, sizeof(u.am.sMem));
65695 assert( u.am.p1<p->nCursor );
65696 assert( pOp->p3>0 && pOp->p3<=p->nMem );
65697 u.am.pDest = &aMem[pOp->p3];
65698 memAboutToChange(p, u.am.pDest);
 
65699 u.am.zRec = 0;
65700
65701 /* This block sets the variable u.am.payloadSize to be the total number of
65702 ** bytes in the record.
65703 **
@@ -64884,11 +65737,11 @@
65737 }else{
65738 assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) );
65739 rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize);
65740 assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
65741 }
65742 }else if( ALWAYS(u.am.pC->pseudoTableReg>0) ){
65743 u.am.pReg = &aMem[u.am.pC->pseudoTableReg];
65744 assert( u.am.pReg->flags & MEM_Blob );
65745 assert( memIsValid(u.am.pReg) );
65746 u.am.payloadSize = u.am.pReg->n;
65747 u.am.zRec = u.am.pReg->z;
@@ -64897,13 +65750,14 @@
65750 }else{
65751 /* Consider the row to be NULL */
65752 u.am.payloadSize = 0;
65753 }
65754
65755 /* If u.am.payloadSize is 0, then just store a NULL. This can happen because of
65756 ** nullRow or because of a corrupt database. */
65757 if( u.am.payloadSize==0 ){
65758 MemSetTypeFlag(u.am.pDest, MEM_Null);
65759 goto op_column_out;
65760 }
65761 assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
65762 if( u.am.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
65763 goto too_big;
@@ -65006,12 +65860,18 @@
65860 ** of the record to the start of the data for the u.am.i-th column
65861 */
65862 for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
65863 if( u.am.zIdx<u.am.zEndHdr ){
65864 u.am.aOffset[u.am.i] = u.am.offset;
65865 if( u.am.zIdx[0]<0x80 ){
65866 u.am.t = u.am.zIdx[0];
65867 u.am.zIdx++;
65868 }else{
65869 u.am.zIdx += sqlite3GetVarint32(u.am.zIdx, &u.am.t);
65870 }
65871 u.am.aType[u.am.i] = u.am.t;
65872 u.am.szField = sqlite3VdbeSerialTypeLen(u.am.t);
65873 u.am.offset += u.am.szField;
65874 if( u.am.offset<u.am.szField ){ /* True if u.am.offset overflows */
65875 u.am.zIdx = &u.am.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
65876 break;
65877 }
@@ -65048,11 +65908,11 @@
65908 ** a pointer to a Mem object.
65909 */
65910 if( u.am.aOffset[u.am.p2] ){
65911 assert( rc==SQLITE_OK );
65912 if( u.am.zRec ){
65913 MemReleaseExt(u.am.pDest);
65914 sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest);
65915 }else{
65916 u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]);
65917 sqlite3VdbeMemMove(&u.am.sMem, u.am.pDest);
65918 rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, u.am.aOffset[u.am.p2], u.am.len, u.am.pC->isIndex, &u.am.sMem);
@@ -65065,11 +65925,11 @@
65925 u.am.pDest->enc = encoding;
65926 }else{
65927 if( pOp->p4type==P4_MEM ){
65928 sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static);
65929 }else{
65930 MemSetTypeFlag(u.am.pDest, MEM_Null);
65931 }
65932 }
65933
65934 /* If we dynamically allocated space to hold the data (in the
65935 ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
@@ -65267,11 +66127,11 @@
66127 i64 nEntry;
66128 BtCursor *pCrsr;
66129 #endif /* local variables moved into u.ap */
66130
66131 u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor;
66132 if( ALWAYS(u.ap.pCrsr) ){
66133 rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry);
66134 }else{
66135 u.ap.nEntry = 0;
66136 }
66137 pOut->u.i = u.ap.nEntry;
@@ -65843,19 +66703,13 @@
66703 u.aw.pCur->nullRow = 1;
66704 u.aw.pCur->isOrdered = 1;
66705 rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor);
66706 u.aw.pCur->pKeyInfo = u.aw.pKeyInfo;
66707
66708 /* Since it performs no memory allocation or IO, the only value that
66709 ** sqlite3BtreeCursor() may return is SQLITE_OK. */
66710 assert( rc==SQLITE_OK );
 
 
 
 
 
 
66711
66712 /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
66713 ** SQLite used to check if the root-page flags were sane at this point
66714 ** and report database corruption if they were not, but this check has
66715 ** since moved into the btree layer. */
@@ -65862,11 +66716,11 @@
66716 u.aw.pCur->isTable = pOp->p4type!=P4_KEYINFO;
66717 u.aw.pCur->isIndex = !u.aw.pCur->isTable;
66718 break;
66719 }
66720
66721 /* Opcode: OpenEphemeral P1 P2 * P4 P5
66722 **
66723 ** Open a new cursor P1 to a transient table.
66724 ** The cursor is always opened read/write even if
66725 ** the main database is read-only. The ephemeral
66726 ** table is deleted automatically when the cursor is closed.
@@ -65879,18 +66733,30 @@
66733 ** This opcode was once called OpenTemp. But that created
66734 ** confusion because the term "temp table", might refer either
66735 ** to a TEMP table at the SQL level, or to a table opened by
66736 ** this opcode. Then this opcode was call OpenVirtual. But
66737 ** that created confusion with the whole virtual-table idea.
66738 **
66739 ** The P5 parameter can be a mask of the BTREE_* flags defined
66740 ** in btree.h. These flags control aspects of the operation of
66741 ** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
66742 ** added automatically.
66743 */
66744 /* Opcode: OpenAutoindex P1 P2 * P4 *
66745 **
66746 ** This opcode works the same as OP_OpenEphemeral. It has a
66747 ** different name to distinguish its use. Tables created using
66748 ** by this opcode will be used for automatically created transient
66749 ** indices in joins.
66750 */
66751 /* Opcode: OpenSorter P1 P2 * P4 *
66752 **
66753 ** This opcode works like OP_OpenEphemeral except that it opens
66754 ** a transient index that is specifically designed to sort large
66755 ** tables using an external merge-sort algorithm.
66756 */
66757 case OP_OpenSorter:
66758 case OP_OpenAutoindex:
66759 case OP_OpenEphemeral: {
66760 #if 0 /* local variables moved into u.ax */
66761 VdbeCursor *pCx;
66762 #endif /* local variables moved into u.ax */
@@ -65900,10 +66766,11 @@
66766 SQLITE_OPEN_EXCLUSIVE |
66767 SQLITE_OPEN_DELETEONCLOSE |
66768 SQLITE_OPEN_TRANSIENT_DB;
66769
66770 assert( pOp->p1>=0 );
66771 assert( (pOp->opcode==OP_OpenSorter)==((pOp->p5 & BTREE_SORTER)!=0) );
66772 u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
66773 if( u.ax.pCx==0 ) goto no_mem;
66774 u.ax.pCx->nullRow = 1;
66775 rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
66776 BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
@@ -65917,11 +66784,11 @@
66784 ** automatically created table with root-page 1 (an BLOB_INTKEY table).
66785 */
66786 if( pOp->p4.pKeyInfo ){
66787 int pgno;
66788 assert( pOp->p4type==P4_KEYINFO );
66789 rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
66790 if( rc==SQLITE_OK ){
66791 assert( pgno==MASTER_ROOT+1 );
66792 rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
66793 (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
66794 u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
@@ -65933,10 +66800,15 @@
66800 u.ax.pCx->isTable = 1;
66801 }
66802 }
66803 u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
66804 u.ax.pCx->isIndex = !u.ax.pCx->isTable;
66805 #ifndef SQLITE_OMIT_MERGE_SORT
66806 if( rc==SQLITE_OK && pOp->opcode==OP_OpenSorter ){
66807 rc = sqlite3VdbeSorterInit(db, u.ax.pCx);
66808 }
66809 #endif
66810 break;
66811 }
66812
66813 /* Opcode: OpenPseudo P1 P2 P3 * *
66814 **
@@ -66052,11 +66924,11 @@
66924 assert( u.az.pC->pseudoTableReg==0 );
66925 assert( OP_SeekLe == OP_SeekLt+1 );
66926 assert( OP_SeekGe == OP_SeekLt+2 );
66927 assert( OP_SeekGt == OP_SeekLt+3 );
66928 assert( u.az.pC->isOrdered );
66929 if( ALWAYS(u.az.pC->pCursor!=0) ){
66930 u.az.oc = pOp->opcode;
66931 u.az.pC->nullRow = 0;
66932 if( u.az.pC->isTable ){
66933 /* The input value in P3 might be of any type: integer, real, string,
66934 ** blob, or NULL. But it needs to be an integer before we can do
@@ -66390,11 +67262,11 @@
67262 break;
67263 }
67264
67265 /* Opcode: NotExists P1 P2 P3 * *
67266 **
67267 ** Use the content of register P3 as an integer key. If a record
67268 ** with that key does not exist in table of P1, then jump to P2.
67269 ** If the record does exist, then fall through. The cursor is left
67270 ** pointing to the record if it exists.
67271 **
67272 ** The difference between this operation and NotFound is that this
@@ -66418,11 +67290,11 @@
67290 u.bd.pC = p->apCsr[pOp->p1];
67291 assert( u.bd.pC!=0 );
67292 assert( u.bd.pC->isTable );
67293 assert( u.bd.pC->pseudoTableReg==0 );
67294 u.bd.pCrsr = u.bd.pC->pCursor;
67295 if( ALWAYS(u.bd.pCrsr!=0) ){
67296 u.bd.res = 0;
67297 u.bd.iKey = pIn3->u.i;
67298 rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res);
67299 u.bd.pC->lastRowid = pIn3->u.i;
67300 u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0;
@@ -66468,11 +67340,11 @@
67340 ** written to register P2.
67341 **
67342 ** If P3>0 then P3 is a register in the root frame of this VDBE that holds
67343 ** the largest previously generated record number. No new record numbers are
67344 ** allowed to be less than this value. When this value reaches its maximum,
67345 ** an SQLITE_FULL error is generated. The P3 register is updated with the '
67346 ** generated record number. This P3 mechanism is used to help implement the
67347 ** AUTOINCREMENT feature.
67348 */
67349 case OP_NewRowid: { /* out2-prerelease */
67350 #if 0 /* local variables moved into u.be */
@@ -66842,10 +67714,17 @@
67714 assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey );
67715 assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData );
67716 assert( u.bh.pC!=0 );
67717 assert( u.bh.pC->nullRow==0 );
67718 assert( u.bh.pC->pseudoTableReg==0 );
67719
67720 if( isSorter(u.bh.pC) ){
67721 assert( pOp->opcode==OP_RowKey );
67722 rc = sqlite3VdbeSorterRowkey(u.bh.pC, pOut);
67723 break;
67724 }
67725
67726 assert( u.bh.pC->pCursor!=0 );
67727 u.bh.pCrsr = u.bh.pC->pCursor;
67728 assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) );
67729
67730 /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
@@ -66950,10 +67829,11 @@
67829 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67830 u.bj.pC = p->apCsr[pOp->p1];
67831 assert( u.bj.pC!=0 );
67832 u.bj.pC->nullRow = 1;
67833 u.bj.pC->rowidIsValid = 0;
67834 assert( u.bj.pC->pCursor || u.bj.pC->pVtabCursor );
67835 if( u.bj.pC->pCursor ){
67836 sqlite3BtreeClearCursor(u.bj.pC->pCursor);
67837 }
67838 break;
67839 }
@@ -66975,11 +67855,11 @@
67855
67856 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67857 u.bk.pC = p->apCsr[pOp->p1];
67858 assert( u.bk.pC!=0 );
67859 u.bk.pCrsr = u.bk.pC->pCursor;
67860 if( NEVER(u.bk.pCrsr==0) ){
67861 u.bk.res = 1;
67862 }else{
67863 rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res);
67864 }
67865 u.bk.pC->nullRow = (u8)u.bk.res;
@@ -67030,11 +67910,15 @@
67910
67911 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67912 u.bl.pC = p->apCsr[pOp->p1];
67913 assert( u.bl.pC!=0 );
67914 u.bl.res = 1;
67915 if( isSorter(u.bl.pC) ){
67916 rc = sqlite3VdbeSorterRewind(db, u.bl.pC, &u.bl.res);
67917 }else{
67918 u.bl.pCrsr = u.bl.pC->pCursor;
67919 assert( u.bl.pCrsr );
67920 rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
67921 u.bl.pC->atFirst = u.bl.res==0 ?1:0;
67922 u.bl.pC->deferredMoveto = 0;
67923 u.bl.pC->cacheStatus = CACHE_STALE;
67924 u.bl.pC->rowidIsValid = 0;
@@ -67045,18 +67929,21 @@
67929 pc = pOp->p2 - 1;
67930 }
67931 break;
67932 }
67933
67934 /* Opcode: Next P1 P2 * P4 P5
67935 **
67936 ** Advance cursor P1 so that it points to the next key/data pair in its
67937 ** table or index. If there are no more key/value pairs then fall through
67938 ** to the following instruction. But if the cursor advance was successful,
67939 ** jump immediately to P2.
67940 **
67941 ** The P1 cursor must be for a real table, not a pseudo-table.
67942 **
67943 ** P4 is always of type P4_ADVANCE. The function pointer points to
67944 ** sqlite3BtreeNext().
67945 **
67946 ** If P5 is positive and the jump is taken, then event counter
67947 ** number P5-1 in the prepared statement is incremented.
67948 **
67949 ** See also: Prev
@@ -67067,19 +67954,21 @@
67954 ** table or index. If there is no previous key/value pairs then fall through
67955 ** to the following instruction. But if the cursor backup was successful,
67956 ** jump immediately to P2.
67957 **
67958 ** The P1 cursor must be for a real table, not a pseudo-table.
67959 **
67960 ** P4 is always of type P4_ADVANCE. The function pointer points to
67961 ** sqlite3BtreePrevious().
67962 **
67963 ** If P5 is positive and the jump is taken, then event counter
67964 ** number P5-1 in the prepared statement is incremented.
67965 */
67966 case OP_Prev: /* jump */
67967 case OP_Next: { /* jump */
67968 #if 0 /* local variables moved into u.bm */
67969 VdbeCursor *pC;
 
67970 int res;
67971 #endif /* local variables moved into u.bm */
67972
67973 CHECK_FOR_INTERRUPT;
67974 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -67086,19 +67975,21 @@
67975 assert( pOp->p5<=ArraySize(p->aCounter) );
67976 u.bm.pC = p->apCsr[pOp->p1];
67977 if( u.bm.pC==0 ){
67978 break; /* See ticket #2273 */
67979 }
67980 if( isSorter(u.bm.pC) ){
67981 assert( pOp->opcode==OP_Next );
67982 rc = sqlite3VdbeSorterNext(db, u.bm.pC, &u.bm.res);
67983 }else{
67984 u.bm.res = 1;
67985 assert( u.bm.pC->deferredMoveto==0 );
67986 assert( u.bm.pC->pCursor );
67987 assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
67988 assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
67989 rc = pOp->p4.xAdvance(u.bm.pC->pCursor, &u.bm.res);
67990 }
67991 u.bm.pC->nullRow = (u8)u.bm.res;
67992 u.bm.pC->cacheStatus = CACHE_STALE;
67993 if( u.bm.res==0 ){
67994 pc = pOp->p2 - 1;
67995 if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
@@ -67110,11 +68001,11 @@
68001 break;
68002 }
68003
68004 /* Opcode: IdxInsert P1 P2 P3 * P5
68005 **
68006 ** Register P2 holds an SQL index key made using the
68007 ** MakeRecord instructions. This opcode writes that key
68008 ** into the index P1. Data for the entry is nil.
68009 **
68010 ** P3 is a flag that provides a hint to the b-tree layer that this
68011 ** insert is likely to be an append.
@@ -67140,14 +68031,17 @@
68031 assert( u.bn.pC->isTable==0 );
68032 rc = ExpandBlob(pIn2);
68033 if( rc==SQLITE_OK ){
68034 u.bn.nKey = pIn2->n;
68035 u.bn.zKey = pIn2->z;
68036 rc = sqlite3VdbeSorterWrite(db, u.bn.pC, u.bn.nKey);
68037 if( rc==SQLITE_OK ){
68038 rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
68039 ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
68040 );
68041 assert( u.bn.pC->deferredMoveto==0 );
68042 }
68043 u.bn.pC->cacheStatus = CACHE_STALE;
68044 }
68045 }
68046 break;
68047 }
@@ -69323,10 +70217,722 @@
70217 }
70218
70219 #endif /* #ifndef SQLITE_OMIT_INCRBLOB */
70220
70221 /************** End of vdbeblob.c ********************************************/
70222 /************** Begin file vdbesort.c ****************************************/
70223 /*
70224 ** 2011 July 9
70225 **
70226 ** The author disclaims copyright to this source code. In place of
70227 ** a legal notice, here is a blessing:
70228 **
70229 ** May you do good and not evil.
70230 ** May you find forgiveness for yourself and forgive others.
70231 ** May you share freely, never taking more than you give.
70232 **
70233 *************************************************************************
70234 ** This file contains code for the VdbeSorter object, used in concert with
70235 ** a VdbeCursor to sort large numbers of keys (as may be required, for
70236 ** example, by CREATE INDEX statements on tables too large to fit in main
70237 ** memory).
70238 */
70239
70240
70241 #ifndef SQLITE_OMIT_MERGE_SORT
70242
70243 typedef struct VdbeSorterIter VdbeSorterIter;
70244
70245 /*
70246 ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
70247 **
70248 ** As keys are added to the sorter, they are written to disk in a series
70249 ** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly
70250 ** the same as the cache-size allowed for temporary databases. In order
70251 ** to allow the caller to extract keys from the sorter in sorted order,
70252 ** all PMAs currently stored on disk must be merged together. This comment
70253 ** describes the data structure used to do so. The structure supports
70254 ** merging any number of arrays in a single pass with no redundant comparison
70255 ** operations.
70256 **
70257 ** The aIter[] array contains an iterator for each of the PMAs being merged.
70258 ** An aIter[] iterator either points to a valid key or else is at EOF. For
70259 ** the purposes of the paragraphs below, we assume that the array is actually
70260 ** N elements in size, where N is the smallest power of 2 greater to or equal
70261 ** to the number of iterators being merged. The extra aIter[] elements are
70262 ** treated as if they are empty (always at EOF).
70263 **
70264 ** The aTree[] array is also N elements in size. The value of N is stored in
70265 ** the VdbeSorter.nTree variable.
70266 **
70267 ** The final (N/2) elements of aTree[] contain the results of comparing
70268 ** pairs of iterator keys together. Element i contains the result of
70269 ** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the
70270 ** aTree element is set to the index of it.
70271 **
70272 ** For the purposes of this comparison, EOF is considered greater than any
70273 ** other key value. If the keys are equal (only possible with two EOF
70274 ** values), it doesn't matter which index is stored.
70275 **
70276 ** The (N/4) elements of aTree[] that preceed the final (N/2) described
70277 ** above contains the index of the smallest of each block of 4 iterators.
70278 ** And so on. So that aTree[1] contains the index of the iterator that
70279 ** currently points to the smallest key value. aTree[0] is unused.
70280 **
70281 ** Example:
70282 **
70283 ** aIter[0] -> Banana
70284 ** aIter[1] -> Feijoa
70285 ** aIter[2] -> Elderberry
70286 ** aIter[3] -> Currant
70287 ** aIter[4] -> Grapefruit
70288 ** aIter[5] -> Apple
70289 ** aIter[6] -> Durian
70290 ** aIter[7] -> EOF
70291 **
70292 ** aTree[] = { X, 5 0, 5 0, 3, 5, 6 }
70293 **
70294 ** The current element is "Apple" (the value of the key indicated by
70295 ** iterator 5). When the Next() operation is invoked, iterator 5 will
70296 ** be advanced to the next key in its segment. Say the next key is
70297 ** "Eggplant":
70298 **
70299 ** aIter[5] -> Eggplant
70300 **
70301 ** The contents of aTree[] are updated first by comparing the new iterator
70302 ** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator
70303 ** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
70304 ** The value of iterator 6 - "Durian" - is now smaller than that of iterator
70305 ** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Banana<Durian),
70306 ** so the value written into element 1 of the array is 0. As follows:
70307 **
70308 ** aTree[] = { X, 0 0, 6 0, 3, 5, 6 }
70309 **
70310 ** In other words, each time we advance to the next sorter element, log2(N)
70311 ** key comparison operations are required, where N is the number of segments
70312 ** being merged (rounded up to the next power of 2).
70313 */
70314 struct VdbeSorter {
70315 int nWorking; /* Start a new b-tree after this many pages */
70316 int nBtree; /* Current size of b-tree contents as PMA */
70317 int nTree; /* Used size of aTree/aIter (power of 2) */
70318 VdbeSorterIter *aIter; /* Array of iterators to merge */
70319 int *aTree; /* Current state of incremental merge */
70320 i64 iWriteOff; /* Current write offset within file pTemp1 */
70321 i64 iReadOff; /* Current read offset within file pTemp1 */
70322 sqlite3_file *pTemp1; /* PMA file 1 */
70323 int nPMA; /* Number of PMAs stored in pTemp1 */
70324 };
70325
70326 /*
70327 ** The following type is an iterator for a PMA. It caches the current key in
70328 ** variables nKey/aKey. If the iterator is at EOF, pFile==0.
70329 */
70330 struct VdbeSorterIter {
70331 i64 iReadOff; /* Current read offset */
70332 i64 iEof; /* 1 byte past EOF for this iterator */
70333 sqlite3_file *pFile; /* File iterator is reading from */
70334 int nAlloc; /* Bytes of space at aAlloc */
70335 u8 *aAlloc; /* Allocated space */
70336 int nKey; /* Number of bytes in key */
70337 u8 *aKey; /* Pointer to current key */
70338 };
70339
70340 /* Minimum allowable value for the VdbeSorter.nWorking variable */
70341 #define SORTER_MIN_WORKING 10
70342
70343 /* Maximum number of segments to merge in a single pass. */
70344 #define SORTER_MAX_MERGE_COUNT 16
70345
70346 /*
70347 ** Free all memory belonging to the VdbeSorterIter object passed as the second
70348 ** argument. All structure fields are set to zero before returning.
70349 */
70350 static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
70351 sqlite3DbFree(db, pIter->aAlloc);
70352 memset(pIter, 0, sizeof(VdbeSorterIter));
70353 }
70354
70355 /*
70356 ** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
70357 ** no error occurs, or an SQLite error code if one does.
70358 */
70359 static int vdbeSorterIterNext(
70360 sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */
70361 VdbeSorterIter *pIter /* Iterator to advance */
70362 ){
70363 int rc; /* Return Code */
70364 int nRead; /* Number of bytes read */
70365 int nRec; /* Size of record in bytes */
70366 int iOff; /* Size of serialized size varint in bytes */
70367
70368 nRead = pIter->iEof - pIter->iReadOff;
70369 if( nRead>5 ) nRead = 5;
70370 if( nRead<=0 ){
70371 /* This is an EOF condition */
70372 vdbeSorterIterZero(db, pIter);
70373 return SQLITE_OK;
70374 }
70375
70376 rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
70377 iOff = getVarint32(pIter->aAlloc, nRec);
70378
70379 if( rc==SQLITE_OK && (iOff+nRec)>nRead ){
70380 int nRead2; /* Number of extra bytes to read */
70381 if( (iOff+nRec)>pIter->nAlloc ){
70382 int nNew = pIter->nAlloc*2;
70383 while( (iOff+nRec)>nNew ) nNew = nNew*2;
70384 pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
70385 if( !pIter->aAlloc ) return SQLITE_NOMEM;
70386 pIter->nAlloc = nNew;
70387 }
70388
70389 nRead2 = iOff + nRec - nRead;
70390 rc = sqlite3OsRead(
70391 pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
70392 );
70393 }
70394
70395 assert( nRec>0 || rc!=SQLITE_OK );
70396 pIter->iReadOff += iOff+nRec;
70397 pIter->nKey = nRec;
70398 pIter->aKey = &pIter->aAlloc[iOff];
70399 return rc;
70400 }
70401
70402 /*
70403 ** Write a single varint, value iVal, to file-descriptor pFile. Return
70404 ** SQLITE_OK if successful, or an SQLite error code if some error occurs.
70405 **
70406 ** The value of *piOffset when this function is called is used as the byte
70407 ** offset in file pFile to write to. Before returning, *piOffset is
70408 ** incremented by the number of bytes written.
70409 */
70410 static int vdbeSorterWriteVarint(
70411 sqlite3_file *pFile, /* File to write to */
70412 i64 iVal, /* Value to write as a varint */
70413 i64 *piOffset /* IN/OUT: Write offset in file pFile */
70414 ){
70415 u8 aVarint[9]; /* Buffer large enough for a varint */
70416 int nVarint; /* Number of used bytes in varint */
70417 int rc; /* Result of write() call */
70418
70419 nVarint = sqlite3PutVarint(aVarint, iVal);
70420 rc = sqlite3OsWrite(pFile, aVarint, nVarint, *piOffset);
70421 *piOffset += nVarint;
70422
70423 return rc;
70424 }
70425
70426 /*
70427 ** Read a single varint from file-descriptor pFile. Return SQLITE_OK if
70428 ** successful, or an SQLite error code if some error occurs.
70429 **
70430 ** The value of *piOffset when this function is called is used as the
70431 ** byte offset in file pFile from whence to read the varint. If successful
70432 ** (i.e. if no IO error occurs), then *piOffset is set to the offset of
70433 ** the first byte past the end of the varint before returning. *piVal is
70434 ** set to the integer value read. If an error occurs, the final values of
70435 ** both *piOffset and *piVal are undefined.
70436 */
70437 static int vdbeSorterReadVarint(
70438 sqlite3_file *pFile, /* File to read from */
70439 i64 iEof, /* Total number of bytes in file */
70440 i64 *piOffset, /* IN/OUT: Read offset in pFile */
70441 i64 *piVal /* OUT: Value read from file */
70442 ){
70443 u8 aVarint[9]; /* Buffer large enough for a varint */
70444 i64 iOff = *piOffset; /* Offset in file to read from */
70445 int nRead = 9; /* Number of bytes to read from file */
70446 int rc; /* Return code */
70447
70448 assert( iEof>iOff );
70449 if( (iEof-iOff)<nRead ){
70450 nRead = iEof-iOff;
70451 }
70452
70453 rc = sqlite3OsRead(pFile, aVarint, nRead, iOff);
70454 if( rc==SQLITE_OK ){
70455 *piOffset += getVarint(aVarint, (u64 *)piVal);
70456 }
70457
70458 return rc;
70459 }
70460
70461 /*
70462 ** Initialize iterator pIter to scan through the PMA stored in file pFile
70463 ** starting at offset iStart and ending at offset iEof-1. This function
70464 ** leaves the iterator pointing to the first key in the PMA (or EOF if the
70465 ** PMA is empty).
70466 */
70467 static int vdbeSorterIterInit(
70468 sqlite3 *db, /* Database handle */
70469 VdbeSorter *pSorter, /* Sorter object */
70470 i64 iStart, /* Start offset in pFile */
70471 VdbeSorterIter *pIter, /* Iterator to populate */
70472 i64 *pnByte /* IN/OUT: Increment this value by PMA size */
70473 ){
70474 int rc;
70475
70476 assert( pSorter->iWriteOff>iStart );
70477 assert( pIter->aAlloc==0 );
70478 pIter->pFile = pSorter->pTemp1;
70479 pIter->iReadOff = iStart;
70480 pIter->nAlloc = 128;
70481 pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
70482 if( !pIter->aAlloc ){
70483 rc = SQLITE_NOMEM;
70484 }else{
70485 i64 iEof = pSorter->iWriteOff; /* EOF of file pSorter->pTemp1 */
70486 i64 nByte; /* Total size of PMA in bytes */
70487 rc = vdbeSorterReadVarint(pSorter->pTemp1, iEof, &pIter->iReadOff, &nByte);
70488 *pnByte += nByte;
70489 pIter->iEof = pIter->iReadOff + nByte;
70490 }
70491 if( rc==SQLITE_OK ){
70492 rc = vdbeSorterIterNext(db, pIter);
70493 }
70494 return rc;
70495 }
70496
70497 /*
70498 ** This function is called to compare two iterator keys when merging
70499 ** multiple b-tree segments. Parameter iOut is the index of the aTree[]
70500 ** value to recalculate.
70501 */
70502 static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
70503 VdbeSorter *pSorter = pCsr->pSorter;
70504 int i1;
70505 int i2;
70506 int iRes;
70507 VdbeSorterIter *p1;
70508 VdbeSorterIter *p2;
70509
70510 assert( iOut<pSorter->nTree && iOut>0 );
70511
70512 if( iOut>=(pSorter->nTree/2) ){
70513 i1 = (iOut - pSorter->nTree/2) * 2;
70514 i2 = i1 + 1;
70515 }else{
70516 i1 = pSorter->aTree[iOut*2];
70517 i2 = pSorter->aTree[iOut*2+1];
70518 }
70519
70520 p1 = &pSorter->aIter[i1];
70521 p2 = &pSorter->aIter[i2];
70522
70523 if( p1->pFile==0 ){
70524 iRes = i2;
70525 }else if( p2->pFile==0 ){
70526 iRes = i1;
70527 }else{
70528 char aSpace[150];
70529 UnpackedRecord *r1;
70530
70531 r1 = sqlite3VdbeRecordUnpack(
70532 pCsr->pKeyInfo, p1->nKey, p1->aKey, aSpace, sizeof(aSpace)
70533 );
70534 if( r1==0 ) return SQLITE_NOMEM;
70535
70536 if( sqlite3VdbeRecordCompare(p2->nKey, p2->aKey, r1)>=0 ){
70537 iRes = i1;
70538 }else{
70539 iRes = i2;
70540 }
70541 sqlite3VdbeDeleteUnpackedRecord(r1);
70542 }
70543
70544 pSorter->aTree[iOut] = iRes;
70545 return SQLITE_OK;
70546 }
70547
70548 /*
70549 ** Initialize the temporary index cursor just opened as a sorter cursor.
70550 */
70551 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
70552 assert( pCsr->pKeyInfo && pCsr->pBt );
70553 pCsr->pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
70554 return (pCsr->pSorter ? SQLITE_OK : SQLITE_NOMEM);
70555 }
70556
70557 /*
70558 ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
70559 */
70560 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
70561 VdbeSorter *pSorter = pCsr->pSorter;
70562 if( pSorter ){
70563 if( pSorter->aIter ){
70564 int i;
70565 for(i=0; i<pSorter->nTree; i++){
70566 vdbeSorterIterZero(db, &pSorter->aIter[i]);
70567 }
70568 sqlite3DbFree(db, pSorter->aIter);
70569 }
70570 if( pSorter->pTemp1 ){
70571 sqlite3OsCloseFree(pSorter->pTemp1);
70572 }
70573 sqlite3DbFree(db, pSorter);
70574 pCsr->pSorter = 0;
70575 }
70576 }
70577
70578 /*
70579 ** Allocate space for a file-handle and open a temporary file. If successful,
70580 ** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK.
70581 ** Otherwise, set *ppFile to 0 and return an SQLite error code.
70582 */
70583 static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
70584 int dummy;
70585 return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
70586 SQLITE_OPEN_TEMP_JOURNAL |
70587 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
70588 SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy
70589 );
70590 }
70591
70592
70593 /*
70594 ** Write the current contents of the b-tree to a PMA. Return SQLITE_OK
70595 ** if successful, or an SQLite error code otherwise.
70596 **
70597 ** The format of a PMA is:
70598 **
70599 ** * A varint. This varint contains the total number of bytes of content
70600 ** in the PMA (not including the varint itself).
70601 **
70602 ** * One or more records packed end-to-end in order of ascending keys.
70603 ** Each record consists of a varint followed by a blob of data (the
70604 ** key). The varint is the number of bytes in the blob of data.
70605 */
70606 static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){
70607 int rc = SQLITE_OK; /* Return code */
70608 VdbeSorter *pSorter = pCsr->pSorter;
70609 int res = 0;
70610
70611 /* sqlite3BtreeFirst() cannot fail because sorter btrees are always held
70612 ** in memory and so an I/O error is not possible. */
70613 rc = sqlite3BtreeFirst(pCsr->pCursor, &res);
70614 if( NEVER(rc!=SQLITE_OK) || res ) return rc;
70615 assert( pSorter->nBtree>0 );
70616
70617 /* If the first temporary PMA file has not been opened, open it now. */
70618 if( pSorter->pTemp1==0 ){
70619 rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
70620 assert( rc!=SQLITE_OK || pSorter->pTemp1 );
70621 assert( pSorter->iWriteOff==0 );
70622 assert( pSorter->nPMA==0 );
70623 }
70624
70625 if( rc==SQLITE_OK ){
70626 i64 iWriteOff = pSorter->iWriteOff;
70627 void *aMalloc = 0; /* Array used to hold a single record */
70628 int nMalloc = 0; /* Allocated size of aMalloc[] in bytes */
70629
70630 pSorter->nPMA++;
70631 for(
70632 rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nBtree, &iWriteOff);
70633 rc==SQLITE_OK && res==0;
70634 rc = sqlite3BtreeNext(pCsr->pCursor, &res)
70635 ){
70636 i64 nKey; /* Size of this key in bytes */
70637
70638 /* Write the size of the record in bytes to the output file */
70639 (void)sqlite3BtreeKeySize(pCsr->pCursor, &nKey);
70640 rc = vdbeSorterWriteVarint(pSorter->pTemp1, nKey, &iWriteOff);
70641
70642 /* Make sure the aMalloc[] buffer is large enough for the record */
70643 if( rc==SQLITE_OK && nKey>nMalloc ){
70644 aMalloc = sqlite3DbReallocOrFree(db, aMalloc, nKey);
70645 if( !aMalloc ){
70646 rc = SQLITE_NOMEM;
70647 }else{
70648 nMalloc = nKey;
70649 }
70650 }
70651
70652 /* Write the record itself to the output file */
70653 if( rc==SQLITE_OK ){
70654 /* sqlite3BtreeKey() cannot fail because sorter btrees held in memory */
70655 rc = sqlite3BtreeKey(pCsr->pCursor, 0, nKey, aMalloc);
70656 if( ALWAYS(rc==SQLITE_OK) ){
70657 rc = sqlite3OsWrite(pSorter->pTemp1, aMalloc, nKey, iWriteOff);
70658 iWriteOff += nKey;
70659 }
70660 }
70661
70662 if( rc!=SQLITE_OK ) break;
70663 }
70664
70665 /* This assert verifies that unless an error has occurred, the size of
70666 ** the PMA on disk is the same as the expected size stored in
70667 ** pSorter->nBtree. */
70668 assert( rc!=SQLITE_OK || pSorter->nBtree==(
70669 iWriteOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nBtree)
70670 ));
70671
70672 pSorter->iWriteOff = iWriteOff;
70673 sqlite3DbFree(db, aMalloc);
70674 }
70675
70676 pSorter->nBtree = 0;
70677 return rc;
70678 }
70679
70680 /*
70681 ** This function is called on a sorter cursor by the VDBE before each row
70682 ** is inserted into VdbeCursor.pCsr. Argument nKey is the size of the key, in
70683 ** bytes, about to be inserted.
70684 **
70685 ** If it is determined that the temporary b-tree accessed via VdbeCursor.pCsr
70686 ** is large enough, its contents are written to a sorted PMA on disk and the
70687 ** tree emptied. This prevents the b-tree (which must be small enough to
70688 ** fit entirely in the cache in order to support efficient inserts) from
70689 ** growing too large.
70690 **
70691 ** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK.
70692 */
70693 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *db, VdbeCursor *pCsr, int nKey){
70694 int rc = SQLITE_OK; /* Return code */
70695 VdbeSorter *pSorter = pCsr->pSorter;
70696 if( pSorter ){
70697 Pager *pPager = sqlite3BtreePager(pCsr->pBt);
70698 int nPage; /* Current size of temporary file in pages */
70699
70700 /* Sorters never spill to disk */
70701 assert( sqlite3PagerFile(pPager)->pMethods==0 );
70702
70703 /* Determine how many pages the temporary b-tree has grown to */
70704 sqlite3PagerPagecount(pPager, &nPage);
70705
70706 /* If pSorter->nWorking is still zero, but the temporary file has been
70707 ** created in the file-system, then the most recent insert into the
70708 ** current b-tree segment probably caused the cache to overflow (it is
70709 ** also possible that sqlite3_release_memory() was called). So set the
70710 ** size of the working set to a little less than the current size of the
70711 ** file in pages. */
70712 if( pSorter->nWorking==0 && sqlite3PagerUnderStress(pPager) ){
70713 pSorter->nWorking = nPage-5;
70714 if( pSorter->nWorking<SORTER_MIN_WORKING ){
70715 pSorter->nWorking = SORTER_MIN_WORKING;
70716 }
70717 }
70718
70719 /* If the number of pages used by the current b-tree segment is greater
70720 ** than the size of the working set (VdbeSorter.nWorking), start a new
70721 ** segment b-tree. */
70722 if( pSorter->nWorking && nPage>=pSorter->nWorking ){
70723 BtCursor *p = pCsr->pCursor;/* Cursor structure to close and reopen */
70724 int iRoot; /* Root page of new tree */
70725
70726 /* Copy the current contents of the b-tree into a PMA in sorted order.
70727 ** Close the currently open b-tree cursor. */
70728 rc = vdbeSorterBtreeToPMA(db, pCsr);
70729 sqlite3BtreeCloseCursor(p);
70730
70731 if( rc==SQLITE_OK ){
70732 rc = sqlite3BtreeDropTable(pCsr->pBt, 2, 0);
70733 #ifdef SQLITE_DEBUG
70734 sqlite3PagerPagecount(pPager, &nPage);
70735 assert( rc!=SQLITE_OK || nPage==1 );
70736 #endif
70737 }
70738 if( rc==SQLITE_OK ){
70739 rc = sqlite3BtreeCreateTable(pCsr->pBt, &iRoot, BTREE_BLOBKEY);
70740 }
70741 if( rc==SQLITE_OK ){
70742 assert( iRoot==2 );
70743 rc = sqlite3BtreeCursor(pCsr->pBt, iRoot, 1, pCsr->pKeyInfo, p);
70744 }
70745 }
70746
70747 pSorter->nBtree += sqlite3VarintLen(nKey) + nKey;
70748 }
70749 return rc;
70750 }
70751
70752 /*
70753 ** Helper function for sqlite3VdbeSorterRewind().
70754 */
70755 static int vdbeSorterInitMerge(
70756 sqlite3 *db, /* Database handle */
70757 VdbeCursor *pCsr, /* Cursor handle for this sorter */
70758 i64 *pnByte /* Sum of bytes in all opened PMAs */
70759 ){
70760 VdbeSorter *pSorter = pCsr->pSorter;
70761 int rc = SQLITE_OK; /* Return code */
70762 int i; /* Used to iterator through aIter[] */
70763 i64 nByte = 0; /* Total bytes in all opened PMAs */
70764
70765 /* Initialize the iterators. */
70766 for(i=0; rc==SQLITE_OK && i<SORTER_MAX_MERGE_COUNT; i++){
70767 VdbeSorterIter *pIter = &pSorter->aIter[i];
70768 rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
70769 pSorter->iReadOff = pIter->iEof;
70770 assert( pSorter->iReadOff<=pSorter->iWriteOff || rc!=SQLITE_OK );
70771 if( pSorter->iReadOff>=pSorter->iWriteOff ) break;
70772 }
70773
70774 /* Initialize the aTree[] array. */
70775 for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
70776 rc = vdbeSorterDoCompare(pCsr, i);
70777 }
70778
70779 *pnByte = nByte;
70780 return rc;
70781 }
70782
70783 /*
70784 ** Once the sorter has been populated, this function is called to prepare
70785 ** for iterating through its contents in sorted order.
70786 */
70787 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
70788 VdbeSorter *pSorter = pCsr->pSorter;
70789 int rc; /* Return code */
70790 sqlite3_file *pTemp2 = 0; /* Second temp file to use */
70791 i64 iWrite2 = 0; /* Write offset for pTemp2 */
70792 int nIter; /* Number of iterators used */
70793 int nByte; /* Bytes of space required for aIter/aTree */
70794 int N = 2; /* Power of 2 >= nIter */
70795
70796 assert( pSorter );
70797
70798 /* Write the current b-tree to a PMA. Close the b-tree cursor. */
70799 rc = vdbeSorterBtreeToPMA(db, pCsr);
70800 sqlite3BtreeCloseCursor(pCsr->pCursor);
70801 if( rc!=SQLITE_OK ) return rc;
70802 if( pSorter->nPMA==0 ){
70803 *pbEof = 1;
70804 return SQLITE_OK;
70805 }
70806
70807 /* Allocate space for aIter[] and aTree[]. */
70808 nIter = pSorter->nPMA;
70809 if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
70810 assert( nIter>0 );
70811 while( N<nIter ) N += N;
70812 nByte = N * (sizeof(int) + sizeof(VdbeSorterIter));
70813 pSorter->aIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte);
70814 if( !pSorter->aIter ) return SQLITE_NOMEM;
70815 pSorter->aTree = (int *)&pSorter->aIter[N];
70816 pSorter->nTree = N;
70817
70818 do {
70819 int iNew; /* Index of new, merged, PMA */
70820
70821 for(iNew=0;
70822 rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA;
70823 iNew++
70824 ){
70825 i64 nWrite; /* Number of bytes in new PMA */
70826
70827 /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
70828 ** initialize an iterator for each of them and break out of the loop.
70829 ** These iterators will be incrementally merged as the VDBE layer calls
70830 ** sqlite3VdbeSorterNext().
70831 **
70832 ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs,
70833 ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs
70834 ** are merged into a single PMA that is written to file pTemp2.
70835 */
70836 rc = vdbeSorterInitMerge(db, pCsr, &nWrite);
70837 assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile );
70838 if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
70839 break;
70840 }
70841
70842 /* Open the second temp file, if it is not already open. */
70843 if( pTemp2==0 ){
70844 assert( iWrite2==0 );
70845 rc = vdbeSorterOpenTempFile(db, &pTemp2);
70846 }
70847
70848 if( rc==SQLITE_OK ){
70849 rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2);
70850 }
70851
70852 if( rc==SQLITE_OK ){
70853 int bEof = 0;
70854 while( rc==SQLITE_OK && bEof==0 ){
70855 int nToWrite;
70856 VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
70857 assert( pIter->pFile );
70858 nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey);
70859 rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2);
70860 iWrite2 += nToWrite;
70861 if( rc==SQLITE_OK ){
70862 rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
70863 }
70864 }
70865 }
70866 }
70867
70868 if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
70869 break;
70870 }else{
70871 sqlite3_file *pTmp = pSorter->pTemp1;
70872 pSorter->nPMA = iNew;
70873 pSorter->pTemp1 = pTemp2;
70874 pTemp2 = pTmp;
70875 pSorter->iWriteOff = iWrite2;
70876 pSorter->iReadOff = 0;
70877 iWrite2 = 0;
70878 }
70879 }while( rc==SQLITE_OK );
70880
70881 if( pTemp2 ){
70882 sqlite3OsCloseFree(pTemp2);
70883 }
70884 *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
70885 return rc;
70886 }
70887
70888 /*
70889 ** Advance to the next element in the sorter.
70890 */
70891 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
70892 VdbeSorter *pSorter = pCsr->pSorter;
70893 int iPrev = pSorter->aTree[1]; /* Index of iterator to advance */
70894 int i; /* Index of aTree[] to recalculate */
70895 int rc; /* Return code */
70896
70897 rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
70898 for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
70899 rc = vdbeSorterDoCompare(pCsr, i);
70900 }
70901
70902 *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
70903 return rc;
70904 }
70905
70906 /*
70907 ** Copy the current sorter key into the memory cell pOut.
70908 */
70909 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
70910 VdbeSorter *pSorter = pCsr->pSorter;
70911 VdbeSorterIter *pIter;
70912
70913 pIter = &pSorter->aIter[ pSorter->aTree[1] ];
70914
70915 /* Coverage testing note: As things are currently, this call will always
70916 ** succeed. This is because the memory cell passed by the VDBE layer
70917 ** happens to be the same one as was used to assemble the keys before they
70918 ** were passed to the sorter - meaning it is always large enough for the
70919 ** largest key. But this could change very easily, so we leave the call
70920 ** to sqlite3VdbeMemGrow() in. */
70921 if( NEVER(sqlite3VdbeMemGrow(pOut, pIter->nKey, 0)) ){
70922 return SQLITE_NOMEM;
70923 }
70924 pOut->n = pIter->nKey;
70925 MemSetTypeFlag(pOut, MEM_Blob);
70926 memcpy(pOut->z, pIter->aKey, pIter->nKey);
70927
70928 return SQLITE_OK;
70929 }
70930
70931 #endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
70932
70933 /************** End of vdbesort.c ********************************************/
70934 /************** Begin file journal.c *****************************************/
70935 /*
70936 ** 2007 August 22
70937 **
70938 ** The author disclaims copyright to this source code. In place of
@@ -69839,10 +71445,12 @@
71445 **
71446 *************************************************************************
71447 ** This file contains routines used for walking the parser tree for
71448 ** an SQL statement.
71449 */
71450 /* #include <stdlib.h> */
71451 /* #include <string.h> */
71452
71453
71454 /*
71455 ** Walk an expression tree. Invoke the callback once for each node
71456 ** of the expression, while decending. (In other words, the callback
@@ -69977,10 +71585,12 @@
71585 **
71586 ** This file contains routines used for walking the parser tree and
71587 ** resolve all identifiers by associating them with a particular
71588 ** table and column.
71589 */
71590 /* #include <stdlib.h> */
71591 /* #include <string.h> */
71592
71593 /*
71594 ** Turn the pExpr expression into an alias for the iCol-th column of the
71595 ** result set in pEList.
71596 **
@@ -70956,15 +72566,29 @@
72566 /* Recursively resolve names in all subqueries
72567 */
72568 for(i=0; i<p->pSrc->nSrc; i++){
72569 struct SrcList_item *pItem = &p->pSrc->a[i];
72570 if( pItem->pSelect ){
72571 NameContext *pNC; /* Used to iterate name contexts */
72572 int nRef = 0; /* Refcount for pOuterNC and outer contexts */
72573 const char *zSavedContext = pParse->zAuthContext;
72574
72575 /* Count the total number of references to pOuterNC and all of its
72576 ** parent contexts. After resolving references to expressions in
72577 ** pItem->pSelect, check if this value has changed. If so, then
72578 ** SELECT statement pItem->pSelect must be correlated. Set the
72579 ** pItem->isCorrelated flag if this is the case. */
72580 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
72581
72582 if( pItem->zName ) pParse->zAuthContext = pItem->zName;
72583 sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
72584 pParse->zAuthContext = zSavedContext;
72585 if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
72586
72587 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
72588 assert( pItem->isCorrelated==0 && nRef<=0 );
72589 pItem->isCorrelated = (nRef!=0);
72590 }
72591 }
72592
72593 /* If there are no aggregate functions in the result-set, and no GROUP BY
72594 ** expression, do not allow aggregates in any of the other expressions.
@@ -72068,10 +73692,11 @@
73692 pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
73693 pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
73694 pNewItem->jointype = pOldItem->jointype;
73695 pNewItem->iCursor = pOldItem->iCursor;
73696 pNewItem->isPopulated = pOldItem->isPopulated;
73697 pNewItem->isCorrelated = pOldItem->isCorrelated;
73698 pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
73699 pNewItem->notIndexed = pOldItem->notIndexed;
73700 pNewItem->pIndex = pOldItem->pIndex;
73701 pTab = pNewItem->pTab = pOldItem->pTab;
73702 if( pTab ){
@@ -78958,11 +80583,11 @@
80583 Table *p;
80584 int n;
80585 const char *z;
80586 Token sEnd;
80587 DbFixer sFix;
80588 Token *pName = 0;
80589 int iDb;
80590 sqlite3 *db = pParse->db;
80591
80592 if( pParse->nVar>0 ){
80593 sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
@@ -79263,10 +80888,33 @@
80888 iDestroyed = iLargest;
80889 }
80890 }
80891 #endif
80892 }
80893
80894 /*
80895 ** Remove entries from the sqlite_stat1 and sqlite_stat2 tables
80896 ** after a DROP INDEX or DROP TABLE command.
80897 */
80898 static void sqlite3ClearStatTables(
80899 Parse *pParse, /* The parsing context */
80900 int iDb, /* The database number */
80901 const char *zType, /* "idx" or "tbl" */
80902 const char *zName /* Name of index or table */
80903 ){
80904 static const char *azStatTab[] = { "sqlite_stat1", "sqlite_stat2" };
80905 int i;
80906 const char *zDbName = pParse->db->aDb[iDb].zName;
80907 for(i=0; i<ArraySize(azStatTab); i++){
80908 if( sqlite3FindTable(pParse->db, azStatTab[i], zDbName) ){
80909 sqlite3NestedParse(pParse,
80910 "DELETE FROM %Q.%s WHERE %s=%Q",
80911 zDbName, azStatTab[i], zType, zName
80912 );
80913 }
80914 }
80915 }
80916
80917 /*
80918 ** This routine is called to do the work of a DROP TABLE statement.
80919 ** pName is the name of the table to be dropped.
80920 */
@@ -79403,18 +81051,11 @@
81051 ** database.
81052 */
81053 sqlite3NestedParse(pParse,
81054 "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
81055 pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
81056 sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
 
 
 
 
 
 
 
81057 if( !isView && !IsVirtual(pTab) ){
81058 destroyTable(pParse, pTab);
81059 }
81060
81061 /* Remove the table entry from SQLite's internal schema and modify
@@ -79592,18 +81233,28 @@
81233 */
81234 static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
81235 Table *pTab = pIndex->pTable; /* The table that is indexed */
81236 int iTab = pParse->nTab++; /* Btree cursor used for pTab */
81237 int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
81238 int iSorter = iTab; /* Cursor opened by OpenSorter (if in use) */
81239 int addr1; /* Address of top of loop */
81240 int tnum; /* Root page of index */
81241 Vdbe *v; /* Generate code into this virtual machine */
81242 KeyInfo *pKey; /* KeyInfo for index */
81243 int regIdxKey; /* Registers containing the index key */
81244 int regRecord; /* Register holding assemblied index record */
81245 sqlite3 *db = pParse->db; /* The database connection */
81246 int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
81247
81248 /* Set bUseSorter to use OP_OpenSorter, or clear it to insert directly
81249 ** into the index. The sorter is used unless either OMIT_MERGE_SORT is
81250 ** defined or the system is configured to store temp files in-memory. */
81251 #ifdef SQLITE_OMIT_MERGE_SORT
81252 static const int bUseSorter = 0;
81253 #else
81254 const int bUseSorter = !sqlite3TempInMemory(pParse->db);
81255 #endif
81256
81257 #ifndef SQLITE_OMIT_AUTHORIZATION
81258 if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
81259 db->aDb[iDb].zName ) ){
81260 return;
@@ -79625,14 +81276,33 @@
81276 sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
81277 (char *)pKey, P4_KEYINFO_HANDOFF);
81278 if( memRootPage>=0 ){
81279 sqlite3VdbeChangeP5(v, 1);
81280 }
81281
81282 /* Open the sorter cursor if we are to use one. */
81283 if( bUseSorter ){
81284 iSorter = pParse->nTab++;
81285 sqlite3VdbeAddOp4(v, OP_OpenSorter, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
81286 sqlite3VdbeChangeP5(v, BTREE_SORTER);
81287 }
81288
81289 /* Open the table. Loop through all rows of the table, inserting index
81290 ** records into the sorter. */
81291 sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
81292 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
81293 regRecord = sqlite3GetTempReg(pParse);
81294 regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
81295
81296 if( bUseSorter ){
81297 sqlite3VdbeAddOp2(v, OP_IdxInsert, iSorter, regRecord);
81298 sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
81299 sqlite3VdbeJumpHere(v, addr1);
81300 addr1 = sqlite3VdbeAddOp2(v, OP_Sort, iSorter, 0);
81301 sqlite3VdbeAddOp2(v, OP_RowKey, iSorter, regRecord);
81302 }
81303
81304 if( pIndex->onError!=OE_None ){
81305 const int regRowid = regIdxKey + pIndex->nColumn;
81306 const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
81307 void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
81308
@@ -79647,17 +81317,19 @@
81317 */
81318 sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
81319 sqlite3HaltConstraint(
81320 pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
81321 }
81322 sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, bUseSorter);
81323 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
81324 sqlite3ReleaseTempReg(pParse, regRecord);
81325 sqlite3VdbeAddOp2(v, OP_Next, iSorter, addr1+1);
81326 sqlite3VdbeJumpHere(v, addr1);
81327
81328 sqlite3VdbeAddOp1(v, OP_Close, iTab);
81329 sqlite3VdbeAddOp1(v, OP_Close, iIdx);
81330 sqlite3VdbeAddOp1(v, OP_Close, iSorter);
81331 }
81332
81333 /*
81334 ** Create a new index for an SQL table. pName1.pName2 is the name of the index
81335 ** and pTblList is the name of the table that is to be indexed. Both will
@@ -80075,11 +81747,11 @@
81747 if( pStart ){
81748 assert( pEnd!=0 );
81749 /* A named index with an explicit CREATE INDEX statement */
81750 zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
81751 onError==OE_None ? "" : " UNIQUE",
81752 (int)(pEnd->z - pName->z) + 1,
81753 pName->z);
81754 }else{
81755 /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
81756 /* zStmt = sqlite3MPrintf(""); */
81757 zStmt = 0;
@@ -80233,19 +81905,13 @@
81905 v = sqlite3GetVdbe(pParse);
81906 if( v ){
81907 sqlite3BeginWriteOperation(pParse, 1, iDb);
81908 sqlite3NestedParse(pParse,
81909 "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
81910 db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName
81911 );
81912 sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
 
 
 
 
 
 
81913 sqlite3ChangeCookie(pParse, iDb);
81914 destroyRootPage(pParse, pIndex->tnum, iDb);
81915 sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
81916 }
81917
@@ -80613,12 +82279,13 @@
82279 ** The operator is "natural cross join". The A and B operands are stored
82280 ** in p->a[0] and p->a[1], respectively. The parser initially stores the
82281 ** operator with A. This routine shifts that operator over to B.
82282 */
82283 SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
82284 if( p ){
82285 int i;
82286 assert( p->a || p->nSrc==0 );
82287 for(i=p->nSrc-1; i>0; i--){
82288 p->a[i].jointype = p->a[i-1].jointype;
82289 }
82290 p->a[0].jointype = 0;
82291 }
@@ -81870,11 +83537,13 @@
83537 int regRowid; /* Actual register containing rowids */
83538
83539 /* Collect rowids of every row to be deleted.
83540 */
83541 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
83542 pWInfo = sqlite3WhereBegin(
83543 pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
83544 );
83545 if( pWInfo==0 ) goto delete_from_cleanup;
83546 regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
83547 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
83548 if( db->flags & SQLITE_CountRows ){
83549 sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
@@ -82135,12 +83804,18 @@
83804 sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
83805 sqlite3ColumnDefault(v, pTab, idx, -1);
83806 }
83807 }
83808 if( doMakeRec ){
83809 const char *zAff;
83810 if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
83811 zAff = 0;
83812 }else{
83813 zAff = sqlite3IndexAffinityStr(v, pIdx);
83814 }
83815 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
83816 sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
83817 }
83818 sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
83819 return regBase;
83820 }
83821
@@ -82162,10 +83837,12 @@
83837 **
83838 ** There is only one exported symbol in this file - the function
83839 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
83840 ** All other code has file scope.
83841 */
83842 /* #include <stdlib.h> */
83843 /* #include <assert.h> */
83844
83845 /*
83846 ** Return the collating function associated with a function.
83847 */
83848 static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
@@ -84311,11 +85988,11 @@
85988
85989 /* Create VDBE to loop through the entries in pSrc that match the WHERE
85990 ** clause. If the constraint is not deferred, throw an exception for
85991 ** each row found. Otherwise, for deferred constraints, increment the
85992 ** deferred constraint counter by nIncr for each row selected. */
85993 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
85994 if( nIncr>0 && pFKey->isDeferred==0 ){
85995 sqlite3ParseToplevel(pParse)->mayAbort = 1;
85996 }
85997 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
85998 if( pWInfo ){
@@ -84485,11 +86162,28 @@
86162 pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
86163 }else{
86164 pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
86165 }
86166 if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
86167 assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
86168 if( !isIgnoreErrors || db->mallocFailed ) return;
86169 if( pTo==0 ){
86170 /* If isIgnoreErrors is true, then a table is being dropped. In this
86171 ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
86172 ** before actually dropping it in order to check FK constraints.
86173 ** If the parent table of an FK constraint on the current table is
86174 ** missing, behave as if it is empty. i.e. decrement the relevant
86175 ** FK counter for each row of the current table with non-NULL keys.
86176 */
86177 Vdbe *v = sqlite3GetVdbe(pParse);
86178 int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
86179 for(i=0; i<pFKey->nCol; i++){
86180 int iReg = pFKey->aCol[i].iFrom + regOld + 1;
86181 sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump);
86182 }
86183 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
86184 }
86185 continue;
86186 }
86187 assert( pFKey->nCol==1 || (aiFree && pIdx) );
86188
86189 if( aiFree ){
@@ -87178,10 +88872,13 @@
88872 int (*strnicmp)(const char*,const char*,int);
88873 int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
88874 int (*wal_autocheckpoint)(sqlite3*,int);
88875 int (*wal_checkpoint)(sqlite3*,const char*);
88876 void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
88877 int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
88878 int (*vtab_config)(sqlite3*,int op,...);
88879 int (*vtab_on_conflict)(sqlite3*);
88880 };
88881
88882 /*
88883 ** The following macros redefine the API routines so that they are
88884 ** redirected throught the global sqlite3_api structure.
@@ -87378,19 +89075,23 @@
89075 #define sqlite3_strnicmp sqlite3_api->strnicmp
89076 #define sqlite3_unlock_notify sqlite3_api->unlock_notify
89077 #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
89078 #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
89079 #define sqlite3_wal_hook sqlite3_api->wal_hook
89080 #define sqlite3_blob_reopen sqlite3_api->blob_reopen
89081 #define sqlite3_vtab_config sqlite3_api->vtab_config
89082 #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
89083 #endif /* SQLITE_CORE */
89084
89085 #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
89086 #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
89087
89088 #endif /* _SQLITE3EXT_H_ */
89089
89090 /************** End of sqlite3ext.h ******************************************/
89091 /************** Continuing where we left off in loadext.c ********************/
89092 /* #include <string.h> */
89093
89094 #ifndef SQLITE_OMIT_LOAD_EXTENSION
89095
89096 /*
89097 ** Some API routines are omitted when various features are
@@ -87452,10 +89153,12 @@
89153
89154 #ifdef SQLITE_OMIT_VIRTUALTABLE
89155 # define sqlite3_create_module 0
89156 # define sqlite3_create_module_v2 0
89157 # define sqlite3_declare_vtab 0
89158 # define sqlite3_vtab_config 0
89159 # define sqlite3_vtab_on_conflict 0
89160 #endif
89161
89162 #ifdef SQLITE_OMIT_SHARED_CACHE
89163 # define sqlite3_enable_shared_cache 0
89164 #endif
@@ -87475,10 +89178,11 @@
89178 #define sqlite3_blob_bytes 0
89179 #define sqlite3_blob_close 0
89180 #define sqlite3_blob_open 0
89181 #define sqlite3_blob_read 0
89182 #define sqlite3_blob_write 0
89183 #define sqlite3_blob_reopen 0
89184 #endif
89185
89186 /*
89187 ** The following structure contains pointers to all SQLite API routines.
89188 ** A pointer to this structure is passed into extensions when they are
@@ -87740,10 +89444,13 @@
89444 #else
89445 0,
89446 0,
89447 0,
89448 #endif
89449 sqlite3_blob_reopen,
89450 sqlite3_vtab_config,
89451 sqlite3_vtab_on_conflict,
89452 };
89453
89454 /*
89455 ** Attempt to load an SQLite extension library contained in the file
89456 ** zFile. The entry point is zProc. zProc may be 0 in which case a
@@ -94129,10 +95836,11 @@
95836 Expr *pHaving; /* The HAVING clause. May be NULL */
95837 int isDistinct; /* True if the DISTINCT keyword is present */
95838 int distinct; /* Table to use for the distinct set */
95839 int rc = 1; /* Value to return from this function */
95840 int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
95841 int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
95842 AggInfo sAggInfo; /* Information used by aggregate queries */
95843 int iEnd; /* Address of the end of the query */
95844 sqlite3 *db; /* The database connection */
95845
95846 #ifndef SQLITE_OMIT_EXPLAIN
@@ -94255,20 +95963,10 @@
95963 explainSetInteger(pParse->iSelectId, iRestoreSelectId);
95964 return rc;
95965 }
95966 #endif
95967
 
 
 
 
 
 
 
 
 
 
95968 /* If there is both a GROUP BY and an ORDER BY clause and they are
95969 ** identical, then disable the ORDER BY clause since the GROUP BY
95970 ** will cause elements to come out in the correct order. This is
95971 ** an optimization - the correct answer should result regardless.
95972 ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
@@ -94276,10 +95974,34 @@
95974 */
95975 if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
95976 && (db->flags & SQLITE_GroupByOrder)==0 ){
95977 pOrderBy = 0;
95978 }
95979
95980 /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
95981 ** if the select-list is the same as the ORDER BY list, then this query
95982 ** can be rewritten as a GROUP BY. In other words, this:
95983 **
95984 ** SELECT DISTINCT xyz FROM ... ORDER BY xyz
95985 **
95986 ** is transformed to:
95987 **
95988 ** SELECT xyz FROM ... GROUP BY xyz
95989 **
95990 ** The second form is preferred as a single index (or temp-table) may be
95991 ** used for both the ORDER BY and DISTINCT processing. As originally
95992 ** written the query must use a temp-table for at least one of the ORDER
95993 ** BY and DISTINCT, and an index or separate temp-table for the other.
95994 */
95995 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
95996 && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
95997 ){
95998 p->selFlags &= ~SF_Distinct;
95999 p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
96000 pGroupBy = p->pGroupBy;
96001 pOrderBy = 0;
96002 }
96003
96004 /* If there is an ORDER BY clause, then this sorting
96005 ** index might end up being unused if the data can be
96006 ** extracted in pre-sorted order. If that is the case, then the
96007 ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
@@ -94312,26 +96034,25 @@
96034
96035 /* Open a virtual index to use for the distinct set.
96036 */
96037 if( p->selFlags & SF_Distinct ){
96038 KeyInfo *pKeyInfo;
 
96039 distinct = pParse->nTab++;
96040 pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
96041 addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
96042 (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
96043 sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
96044 }else{
96045 distinct = addrDistinctIndex = -1;
96046 }
96047
96048 /* Aggregate and non-aggregate queries are handled differently */
96049 if( !isAgg && pGroupBy==0 ){
96050 ExprList *pDist = (isDistinct ? p->pEList : 0);
96051
96052 /* Begin the database scan. */
96053 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
96054 if( pWInfo==0 ) goto select_end;
96055 if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
96056
96057 /* If sorting index that was created by a prior OP_OpenEphemeral
96058 ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -94340,14 +96061,56 @@
96061 if( addrSortIndex>=0 && pOrderBy==0 ){
96062 sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
96063 p->addrOpenEphm[2] = -1;
96064 }
96065
96066 if( pWInfo->eDistinct ){
96067 VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
96068
96069 assert( addrDistinctIndex>0 );
96070 pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
96071
96072 assert( isDistinct );
96073 assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
96074 || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
96075 );
96076 distinct = -1;
96077 if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
96078 int iJump;
96079 int iExpr;
96080 int iFlag = ++pParse->nMem;
96081 int iBase = pParse->nMem+1;
96082 int iBase2 = iBase + pEList->nExpr;
96083 pParse->nMem += (pEList->nExpr*2);
96084
96085 /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
96086 ** OP_Integer initializes the "first row" flag. */
96087 pOp->opcode = OP_Integer;
96088 pOp->p1 = 1;
96089 pOp->p2 = iFlag;
96090
96091 sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
96092 iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
96093 sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
96094 for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
96095 CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
96096 sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
96097 sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
96098 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
96099 }
96100 sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
96101
96102 sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
96103 assert( sqlite3VdbeCurrentAddr(v)==iJump );
96104 sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
96105 }else{
96106 pOp->opcode = OP_Noop;
96107 }
96108 }
96109
96110 /* Use the standard inner loop. */
96111 selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
96112 pWInfo->iContinue, pWInfo->iBreak);
96113
96114 /* End the database scan loop.
96115 */
96116 sqlite3WhereEnd(pWInfo);
@@ -94453,11 +96216,11 @@
96216 ** This might involve two separate loops with an OP_Sort in between, or
96217 ** it might be a single loop that uses an index to extract information
96218 ** in the right order to begin with.
96219 */
96220 sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
96221 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
96222 if( pWInfo==0 ) goto select_end;
96223 if( pGroupBy==0 ){
96224 /* The optimizer is able to deliver rows in group by order so
96225 ** we do not have to sort. The OP_OpenEphemeral table will be
96226 ** cancelled later because we still need to use the pKeyInfo
@@ -94715,11 +96478,11 @@
96478 /* This case runs if the aggregate has no GROUP BY clause. The
96479 ** processing is much simpler since there is only a single row
96480 ** of output.
96481 */
96482 resetAccumulator(pParse, &sAggInfo);
96483 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
96484 if( pWInfo==0 ){
96485 sqlite3ExprListDelete(db, pDel);
96486 goto select_end;
96487 }
96488 updateAccumulator(pParse, &sAggInfo);
@@ -94894,10 +96657,12 @@
96657 ** interface routine of sqlite3_exec().
96658 **
96659 ** These routines are in a separate files so that they will not be linked
96660 ** if they are not used.
96661 */
96662 /* #include <stdlib.h> */
96663 /* #include <string.h> */
96664
96665 #ifndef SQLITE_OMIT_GET_TABLE
96666
96667 /*
96668 ** This structure is used to pass data from sqlite3_get_table() through
@@ -95191,19 +96956,32 @@
96956 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
96957 if( iDb<0 ){
96958 goto trigger_cleanup;
96959 }
96960 }
96961 if( !pTableName || db->mallocFailed ){
96962 goto trigger_cleanup;
96963 }
96964
96965 /* A long-standing parser bug is that this syntax was allowed:
96966 **
96967 ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
96968 ** ^^^^^^^^
96969 **
96970 ** To maintain backwards compatibility, ignore the database
96971 ** name on pTableName if we are reparsing our of SQLITE_MASTER.
96972 */
96973 if( db->init.busy && iDb!=1 ){
96974 sqlite3DbFree(db, pTableName->a[0].zDatabase);
96975 pTableName->a[0].zDatabase = 0;
96976 }
96977
96978 /* If the trigger name was unqualified, and the table is a temp table,
96979 ** then set iDb to 1 to create the trigger in the temporary database.
96980 ** If sqlite3SrcListLookup() returns 0, indicating the table does not
96981 ** exist, the error is caught by the block below.
96982 */
 
 
 
96983 pTab = sqlite3SrcListLookup(pParse, pTableName);
96984 if( db->init.busy==0 && pName2->n==0 && pTab
96985 && pTab->pSchema==db->aDb[1].pSchema ){
96986 iDb = 1;
96987 }
@@ -96497,11 +98275,13 @@
98275 }
98276
98277 /* Begin the database scan
98278 */
98279 sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
98280 pWInfo = sqlite3WhereBegin(
98281 pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
98282 );
98283 if( pWInfo==0 ) goto update_cleanup;
98284 okOnePass = pWInfo->okOnePass;
98285
98286 /* Remember the rowid of every item to be updated.
98287 */
@@ -98523,10 +100303,11 @@
100303 #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
100304 #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
100305 #define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
100306 #define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
100307 #define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
100308 #define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
100309
100310 /*
100311 ** Initialize a preallocated WhereClause structure.
100312 */
100313 static void whereClauseInit(
@@ -99667,10 +101448,166 @@
101448 }
101449 }
101450 return 0;
101451 }
101452
101453 /*
101454 ** This function searches the expression list passed as the second argument
101455 ** for an expression of type TK_COLUMN that refers to the same column and
101456 ** uses the same collation sequence as the iCol'th column of index pIdx.
101457 ** Argument iBase is the cursor number used for the table that pIdx refers
101458 ** to.
101459 **
101460 ** If such an expression is found, its index in pList->a[] is returned. If
101461 ** no expression is found, -1 is returned.
101462 */
101463 static int findIndexCol(
101464 Parse *pParse, /* Parse context */
101465 ExprList *pList, /* Expression list to search */
101466 int iBase, /* Cursor for table associated with pIdx */
101467 Index *pIdx, /* Index to match column of */
101468 int iCol /* Column of index to match */
101469 ){
101470 int i;
101471 const char *zColl = pIdx->azColl[iCol];
101472
101473 for(i=0; i<pList->nExpr; i++){
101474 Expr *p = pList->a[i].pExpr;
101475 if( p->op==TK_COLUMN
101476 && p->iColumn==pIdx->aiColumn[iCol]
101477 && p->iTable==iBase
101478 ){
101479 CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
101480 if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
101481 return i;
101482 }
101483 }
101484 }
101485
101486 return -1;
101487 }
101488
101489 /*
101490 ** This routine determines if pIdx can be used to assist in processing a
101491 ** DISTINCT qualifier. In other words, it tests whether or not using this
101492 ** index for the outer loop guarantees that rows with equal values for
101493 ** all expressions in the pDistinct list are delivered grouped together.
101494 **
101495 ** For example, the query
101496 **
101497 ** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
101498 **
101499 ** can benefit from any index on columns "b" and "c".
101500 */
101501 static int isDistinctIndex(
101502 Parse *pParse, /* Parsing context */
101503 WhereClause *pWC, /* The WHERE clause */
101504 Index *pIdx, /* The index being considered */
101505 int base, /* Cursor number for the table pIdx is on */
101506 ExprList *pDistinct, /* The DISTINCT expressions */
101507 int nEqCol /* Number of index columns with == */
101508 ){
101509 Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
101510 int i; /* Iterator variable */
101511
101512 if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
101513 testcase( pDistinct->nExpr==BMS-1 );
101514
101515 /* Loop through all the expressions in the distinct list. If any of them
101516 ** are not simple column references, return early. Otherwise, test if the
101517 ** WHERE clause contains a "col=X" clause. If it does, the expression
101518 ** can be ignored. If it does not, and the column does not belong to the
101519 ** same table as index pIdx, return early. Finally, if there is no
101520 ** matching "col=X" expression and the column is on the same table as pIdx,
101521 ** set the corresponding bit in variable mask.
101522 */
101523 for(i=0; i<pDistinct->nExpr; i++){
101524 WhereTerm *pTerm;
101525 Expr *p = pDistinct->a[i].pExpr;
101526 if( p->op!=TK_COLUMN ) return 0;
101527 pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
101528 if( pTerm ){
101529 Expr *pX = pTerm->pExpr;
101530 CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
101531 CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
101532 if( p1==p2 ) continue;
101533 }
101534 if( p->iTable!=base ) return 0;
101535 mask |= (((Bitmask)1) << i);
101536 }
101537
101538 for(i=nEqCol; mask && i<pIdx->nColumn; i++){
101539 int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
101540 if( iExpr<0 ) break;
101541 mask &= ~(((Bitmask)1) << iExpr);
101542 }
101543
101544 return (mask==0);
101545 }
101546
101547
101548 /*
101549 ** Return true if the DISTINCT expression-list passed as the third argument
101550 ** is redundant. A DISTINCT list is redundant if the database contains a
101551 ** UNIQUE index that guarantees that the result of the query will be distinct
101552 ** anyway.
101553 */
101554 static int isDistinctRedundant(
101555 Parse *pParse,
101556 SrcList *pTabList,
101557 WhereClause *pWC,
101558 ExprList *pDistinct
101559 ){
101560 Table *pTab;
101561 Index *pIdx;
101562 int i;
101563 int iBase;
101564
101565 /* If there is more than one table or sub-select in the FROM clause of
101566 ** this query, then it will not be possible to show that the DISTINCT
101567 ** clause is redundant. */
101568 if( pTabList->nSrc!=1 ) return 0;
101569 iBase = pTabList->a[0].iCursor;
101570 pTab = pTabList->a[0].pTab;
101571
101572 /* If any of the expressions is an IPK column on table iBase, then return
101573 ** true. Note: The (p->iTable==iBase) part of this test may be false if the
101574 ** current SELECT is a correlated sub-query.
101575 */
101576 for(i=0; i<pDistinct->nExpr; i++){
101577 Expr *p = pDistinct->a[i].pExpr;
101578 if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
101579 }
101580
101581 /* Loop through all indices on the table, checking each to see if it makes
101582 ** the DISTINCT qualifier redundant. It does so if:
101583 **
101584 ** 1. The index is itself UNIQUE, and
101585 **
101586 ** 2. All of the columns in the index are either part of the pDistinct
101587 ** list, or else the WHERE clause contains a term of the form "col=X",
101588 ** where X is a constant value. The collation sequences of the
101589 ** comparison and select-list expressions must match those of the index.
101590 */
101591 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
101592 if( pIdx->onError==OE_None ) continue;
101593 for(i=0; i<pIdx->nColumn; i++){
101594 int iCol = pIdx->aiColumn[i];
101595 if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx)
101596 && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
101597 ){
101598 break;
101599 }
101600 }
101601 if( i==pIdx->nColumn ){
101602 /* This index implies that the DISTINCT qualifier is redundant. */
101603 return 1;
101604 }
101605 }
101606
101607 return 0;
101608 }
101609
101610 /*
101611 ** This routine decides if pIdx can be used to satisfy the ORDER BY
101612 ** clause. If it can, it returns 1. If pIdx cannot satisfy the
101613 ** ORDER BY clause, this routine returns 0.
@@ -99703,11 +101640,14 @@
101640 int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
101641 int nTerm; /* Number of ORDER BY terms */
101642 struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
101643 sqlite3 *db = pParse->db;
101644
101645 if( !pOrderBy ) return 0;
101646 if( wsFlags & WHERE_COLUMN_IN ) return 0;
101647 if( pIdx->bUnordered ) return 0;
101648
101649 nTerm = pOrderBy->nExpr;
101650 assert( nTerm>0 );
101651
101652 /* Argument pIdx must either point to a 'real' named index structure,
101653 ** or an index structure allocated on the stack by bestBtreeIndex() to
@@ -100016,10 +101956,14 @@
101956 double costTempIdx; /* per-query cost of the transient index */
101957 WhereTerm *pTerm; /* A single term of the WHERE clause */
101958 WhereTerm *pWCEnd; /* End of pWC->a[] */
101959 Table *pTable; /* Table tht might be indexed */
101960
101961 if( pParse->nQueryLoop<=(double)1 ){
101962 /* There is no point in building an automatic index for a single scan */
101963 return;
101964 }
101965 if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
101966 /* Automatic indices are disabled at run-time */
101967 return;
101968 }
101969 if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
@@ -100027,10 +101971,14 @@
101971 return;
101972 }
101973 if( pSrc->notIndexed ){
101974 /* The NOT INDEXED clause appears in the SQL. */
101975 return;
101976 }
101977 if( pSrc->isCorrelated ){
101978 /* The source is a correlated sub-query. No point in indexing it. */
101979 return;
101980 }
101981
101982 assert( pParse->nQueryLoop >= (double)1 );
101983 pTable = pSrc->pTab;
101984 nTableRow = pTable->nRowEst;
@@ -100244,10 +102192,11 @@
102192 if( pTerm->leftCursor != pSrc->iCursor ) continue;
102193 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
102194 testcase( pTerm->eOperator==WO_IN );
102195 testcase( pTerm->eOperator==WO_ISNULL );
102196 if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
102197 if( pTerm->wtFlags & TERM_VNULL ) continue;
102198 nTerm++;
102199 }
102200
102201 /* If the ORDER BY clause contains only columns in the current
102202 ** virtual table then allocate space for the aOrderBy part of
@@ -100294,10 +102243,11 @@
102243 if( pTerm->leftCursor != pSrc->iCursor ) continue;
102244 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
102245 testcase( pTerm->eOperator==WO_IN );
102246 testcase( pTerm->eOperator==WO_ISNULL );
102247 if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
102248 if( pTerm->wtFlags & TERM_VNULL ) continue;
102249 pIdxCons[j].iColumn = pTerm->u.leftColumn;
102250 pIdxCons[j].iTermOffset = i;
102251 pIdxCons[j].op = (u8)pTerm->eOperator;
102252 /* The direct assignment in the previous line is possible only because
102253 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
@@ -100959,10 +102909,11 @@
102909 WhereClause *pWC, /* The WHERE clause */
102910 struct SrcList_item *pSrc, /* The FROM clause term to search */
102911 Bitmask notReady, /* Mask of cursors not available for indexing */
102912 Bitmask notValid, /* Cursors not available for any purpose */
102913 ExprList *pOrderBy, /* The ORDER BY clause */
102914 ExprList *pDistinct, /* The select-list if query is DISTINCT */
102915 WhereCost *pCost /* Lowest cost query plan */
102916 ){
102917 int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
102918 Index *pProbe; /* An index we are evaluating */
102919 Index *pIdx; /* Copy of pProbe, or zero for IPK index */
@@ -101099,11 +103050,12 @@
103050 int nEq; /* Number of == or IN terms matching index */
103051 int bInEst = 0; /* True if "x IN (SELECT...)" seen */
103052 int nInMul = 1; /* Number of distinct equalities to lookup */
103053 int estBound = 100; /* Estimated reduction in search space */
103054 int nBound = 0; /* Number of range constraints seen */
103055 int bSort = !!pOrderBy; /* True if external sort required */
103056 int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */
103057 int bLookup = 0; /* True if not a covering index */
103058 WhereTerm *pTerm; /* A single term of the WHERE clause */
103059 #ifdef SQLITE_ENABLE_STAT2
103060 WhereTerm *pFirstTerm = 0; /* First term matching the index */
103061 #endif
@@ -101163,21 +103115,24 @@
103115
103116 /* If there is an ORDER BY clause and the index being considered will
103117 ** naturally scan rows in the required order, set the appropriate flags
103118 ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
103119 ** will scan rows in a different order, set the bSort variable. */
103120 if( isSortingIndex(
103121 pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
103122 ){
103123 bSort = 0;
103124 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
103125 wsFlags |= (rev ? WHERE_REVERSE : 0);
103126 }
103127
103128 /* If there is a DISTINCT qualifier and this index will scan rows in
103129 ** order of the DISTINCT expressions, clear bDist and set the appropriate
103130 ** flags in wsFlags. */
103131 if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
103132 bDist = 0;
103133 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
103134 }
103135
103136 /* If currently calculating the cost of using an index (not the IPK
103137 ** index), determine if all required column data may be obtained without
103138 ** using the main table (i.e. if the index is a covering
@@ -101208,16 +103163,17 @@
103163 nRow = aiRowEst[0]/2;
103164 nInMul = (int)(nRow / aiRowEst[nEq]);
103165 }
103166
103167 #ifdef SQLITE_ENABLE_STAT2
103168 /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
103169 ** and we do not think that values of x are unique and if histogram
103170 ** data is available for column x, then it might be possible
103171 ** to get a better estimate on the number of rows based on
103172 ** VALUE and how common that value is according to the histogram.
103173 */
103174 if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
103175 if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
103176 testcase( pFirstTerm->eOperator==WO_EQ );
103177 testcase( pFirstTerm->eOperator==WO_ISNULL );
103178 whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
103179 }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
@@ -101290,10 +103246,13 @@
103246 ** difference and select C of 3.0.
103247 */
103248 if( bSort ){
103249 cost += nRow*estLog(nRow)*3;
103250 }
103251 if( bDist ){
103252 cost += nRow*estLog(nRow)*3;
103253 }
103254
103255 /**** Cost of using this index has now been computed ****/
103256
103257 /* If there are additional constraints on this table that cannot
103258 ** be used with the current index, but which might lower the number
@@ -101435,11 +103394,11 @@
103394 }
103395 sqlite3DbFree(pParse->db, p);
103396 }else
103397 #endif
103398 {
103399 bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
103400 }
103401 }
103402
103403 /*
103404 ** Disable a term in the WHERE clause. Except, do not disable the term
@@ -102397,11 +104356,11 @@
104356 for(ii=0; ii<pOrWc->nTerm; ii++){
104357 WhereTerm *pOrTerm = &pOrWc->a[ii];
104358 if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
104359 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
104360 /* Loop through table entries that match term pOrTerm. */
104361 pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0, 0,
104362 WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
104363 WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
104364 if( pSubWInfo ){
104365 explainOneScan(
104366 pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -102638,10 +104597,11 @@
104597 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
104598 Parse *pParse, /* The parser context */
104599 SrcList *pTabList, /* A list of all tables to be scanned */
104600 Expr *pWhere, /* The WHERE clause */
104601 ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
104602 ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
104603 u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
104604 ){
104605 int i; /* Loop counter */
104606 int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
104607 int nTabList; /* Number of elements in pTabList */
@@ -102697,10 +104657,14 @@
104657 pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
104658 pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
104659 pWInfo->wctrlFlags = wctrlFlags;
104660 pWInfo->savedNQueryLoop = pParse->nQueryLoop;
104661 pMaskSet = (WhereMaskSet*)&pWC[1];
104662
104663 /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
104664 ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
104665 if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
104666
104667 /* Split the WHERE clause into separate subexpressions where each
104668 ** subexpression is separated by an AND operator.
104669 */
104670 initMaskSet(pMaskSet);
@@ -102764,10 +104728,19 @@
104728 */
104729 exprAnalyzeAll(pTabList, pWC);
104730 if( db->mallocFailed ){
104731 goto whereBeginError;
104732 }
104733
104734 /* Check if the DISTINCT qualifier, if there is one, is redundant.
104735 ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
104736 ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
104737 */
104738 if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
104739 pDistinct = 0;
104740 pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
104741 }
104742
104743 /* Chose the best index to use for each table in the FROM clause.
104744 **
104745 ** This loop fills in the following fields:
104746 **
@@ -102848,10 +104821,11 @@
104821 Bitmask mask; /* Mask of tables not yet ready */
104822 for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
104823 int doNotReorder; /* True if this table should not be reordered */
104824 WhereCost sCost; /* Cost information from best[Virtual]Index() */
104825 ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
104826 ExprList *pDist; /* DISTINCT clause for index to optimize */
104827
104828 doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
104829 if( j!=iFrom && doNotReorder ) break;
104830 m = getMask(pMaskSet, pTabItem->iCursor);
104831 if( (m & notReady)==0 ){
@@ -102858,10 +104832,11 @@
104832 if( j==iFrom ) iFrom++;
104833 continue;
104834 }
104835 mask = (isOptimal ? m : notReady);
104836 pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
104837 pDist = (i==0 ? pDistinct : 0);
104838 if( pTabItem->pIndex==0 ) nUnconstrained++;
104839
104840 WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
104841 j, isOptimal));
104842 assert( pTabItem->pTab );
@@ -102872,11 +104847,11 @@
104847 &sCost, pp);
104848 }else
104849 #endif
104850 {
104851 bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
104852 pDist, &sCost);
104853 }
104854 assert( isOptimal || (sCost.used&notReady)==0 );
104855
104856 /* If an INDEXED BY clause is present, then the plan must use that
104857 ** index if it uses any index at all */
@@ -102932,10 +104907,14 @@
104907 WHERETRACE(("*** Optimizer selects table %d for loop %d"
104908 " with cost=%g and nRow=%g\n",
104909 bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
104910 if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
104911 *ppOrderBy = 0;
104912 }
104913 if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
104914 assert( pWInfo->eDistinct==0 );
104915 pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
104916 }
104917 andFlags &= bestPlan.plan.wsFlags;
104918 pLevel->plan = bestPlan.plan;
104919 testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
104920 testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
@@ -103267,10 +105246,11 @@
105246 ** LALR(1) grammar but which are always false in the
105247 ** specific grammar used by SQLite.
105248 */
105249 /* First off, code is included that follows the "include" declaration
105250 ** in the input grammar file. */
105251 /* #include <stdio.h> */
105252
105253
105254 /*
105255 ** Disable all error recovery processing in the parser push-down
105256 ** automaton.
@@ -104127,10 +106107,11 @@
106107 #endif
106108 };
106109 typedef struct yyParser yyParser;
106110
106111 #ifndef NDEBUG
106112 /* #include <stdio.h> */
106113 static FILE *yyTraceFILE = 0;
106114 static char *yyTracePrompt = 0;
106115 #endif /* NDEBUG */
106116
106117 #ifndef NDEBUG
@@ -106702,10 +108683,11 @@
108683 **
108684 ** This file contains C code that splits an SQL input string up into
108685 ** individual tokens and sends those tokens one-by-one over to the
108686 ** parser for analysis.
108687 */
108688 /* #include <stdlib.h> */
108689
108690 /*
108691 ** The charMap() macro maps alphabetic characters into their
108692 ** lower-case ASCII equivalent. On ASCII machines, this is just
108693 ** an upper-to-lower case map. On EBCDIC machines we also need
@@ -108093,10 +110075,20 @@
110075 memcpy(&y, &x, 8);
110076 assert( sqlite3IsNaN(y) );
110077 }
110078 #endif
110079 #endif
110080
110081 /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
110082 ** compile-time option.
110083 */
110084 #ifdef SQLITE_EXTRA_INIT
110085 if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
110086 int SQLITE_EXTRA_INIT(void);
110087 rc = SQLITE_EXTRA_INIT();
110088 }
110089 #endif
110090
110091 return rc;
110092 }
110093
110094 /*
@@ -110763,10 +112755,21 @@
112755 if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
112756 sqlite3ScratchFree(pFree);
112757 break;
112758 }
112759
112760 /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
112761 **
112762 ** If parameter onoff is non-zero, configure the wrappers so that all
112763 ** subsequent calls to localtime() and variants fail. If onoff is zero,
112764 ** undo this setting.
112765 */
112766 case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
112767 sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
112768 break;
112769 }
112770
112771 }
112772 va_end(ap);
112773 #endif /* SQLITE_OMIT_BUILTIN_TEST */
112774 return rc;
112775 }
@@ -111420,16 +113423,10 @@
113423 ** TODO(shess) Provide a VACUUM type operation to clear out all
113424 ** deletions and duplications. This would basically be a forced merge
113425 ** into a single segment.
113426 */
113427
 
 
 
 
 
 
113428 /************** Include fts3Int.h in the middle of fts3.c ********************/
113429 /************** Begin file fts3Int.h *****************************************/
113430 /*
113431 ** 2009 Nov 12
113432 **
@@ -111441,18 +113438,33 @@
113438 ** May you share freely, never taking more than you give.
113439 **
113440 ******************************************************************************
113441 **
113442 */
 
113443 #ifndef _FTSINT_H
113444 #define _FTSINT_H
113445
113446 #if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
113447 # define NDEBUG 1
113448 #endif
113449
113450 /*
113451 ** FTS4 is really an extension for FTS3. It is enabled using the
113452 ** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
113453 ** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
113454 */
113455 #if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
113456 # define SQLITE_ENABLE_FTS3
113457 #endif
113458
113459 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
113460
113461 /* If not building as part of the core, include sqlite3ext.h. */
113462 #ifndef SQLITE_CORE
113463 SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
113464 #endif
113465
113466 /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
113467 /************** Begin file fts3_tokenizer.h **********************************/
113468 /*
113469 ** 2006 July 10
113470 **
@@ -111940,11 +113952,11 @@
113952 char *aDoclist; /* List of docids for full-text queries */
113953 int nDoclist; /* Size of buffer at aDoclist */
113954 u8 bDesc; /* True to sort in descending order */
113955 int eEvalmode; /* An FTS3_EVAL_XX constant */
113956 int nRowAvg; /* Average size of database rows, in pages */
113957 sqlite3_int64 nDoc; /* Documents in table */
113958
113959 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
113960 u32 *aMatchinfo; /* Information about most recent match */
113961 int nMatchinfo; /* Number of elements in aMatchinfo[] */
113962 char *zMatchinfo; /* Matchinfo specification */
@@ -111981,11 +113993,11 @@
113993
113994 sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
113995 int bFreeList; /* True if pList should be sqlite3_free()d */
113996 char *pList; /* Pointer to position list following iDocid */
113997 int nList; /* Length of position list */
113998 };
113999
114000 /*
114001 ** A "phrase" is a sequence of one or more tokens that must match in
114002 ** sequence. A single token is the base case and the most common case.
114003 ** For a sequence of tokens contained in double-quotes (i.e. "one two three")
@@ -111997,19 +114009,19 @@
114009 int isPrefix; /* True if token ends with a "*" character */
114010
114011 /* Variables above this point are populated when the expression is
114012 ** parsed (by code in fts3_expr.c). Below this point the variables are
114013 ** used when evaluating the expression. */
 
114014 Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
114015 Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */
114016 };
114017
114018 struct Fts3Phrase {
114019 /* Cache of doclist for this phrase. */
114020 Fts3Doclist doclist;
114021 int bIncr; /* True if doclist is loaded incrementally */
114022 int iDoclistToken;
114023
114024 /* Variables below this point are populated by fts3_expr.c when parsing
114025 ** a MATCH expression. Everything above is part of the evaluation phase.
114026 */
114027 int nToken; /* Number of tokens in the phrase */
@@ -112130,10 +114142,11 @@
114142 Fts3SegFilter *pFilter; /* Pointer to filter object */
114143 char *aBuffer; /* Buffer to merge doclists in */
114144 int nBuffer; /* Allocated size of aBuffer[] in bytes */
114145
114146 int iColFilter; /* If >=0, filter for this column */
114147 int bRestart;
114148
114149 /* Used by fts3.c only. */
114150 int nCost; /* Cost of running iterator */
114151 int bLookup; /* True if a lookup of a single entry. */
114152
@@ -112180,43 +114193,49 @@
114193 #endif
114194
114195 /* fts3_aux.c */
114196 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
114197
 
 
 
 
 
 
 
 
114198 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
114199
 
 
 
114200 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
114201 Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
114202 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
114203 Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
114204 SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
114205 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
114206 SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
114207
114208 SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
114209
114210 #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
114211 #endif /* _FTSINT_H */
114212
114213 /************** End of fts3Int.h *********************************************/
114214 /************** Continuing where we left off in fts3.c ***********************/
114215 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
114216
114217 #if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
114218 # define SQLITE_CORE 1
114219 #endif
114220
114221 /* #include <assert.h> */
114222 /* #include <stdlib.h> */
114223 /* #include <stddef.h> */
114224 /* #include <stdio.h> */
114225 /* #include <string.h> */
114226 /* #include <stdarg.h> */
114227
114228 #ifndef SQLITE_CORE
114229 SQLITE_EXTENSION_INIT1
114230 #endif
114231
114232 static int fts3EvalNext(Fts3Cursor *pCsr);
114233 static int fts3EvalStart(Fts3Cursor *pCsr);
114234 static int fts3TermSegReaderCursor(
114235 Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
114236
114237 /*
114238 ** Write a 64-bit variable-length integer to memory starting at p[0].
114239 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
114240 ** The number of bytes written is returned.
114241 */
@@ -112545,10 +114564,13 @@
114564 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
114565 if( rc==SQLITE_OK ){
114566 sqlite3_step(pStmt);
114567 p->nPgsz = sqlite3_column_int(pStmt, 0);
114568 rc = sqlite3_finalize(pStmt);
114569 }else if( rc==SQLITE_AUTH ){
114570 p->nPgsz = 1024;
114571 rc = SQLITE_OK;
114572 }
114573 }
114574 assert( p->nPgsz>0 || rc!=SQLITE_OK );
114575 sqlite3_free(zSql);
114576 *pRc = rc;
@@ -112718,31 +114740,60 @@
114740 }
114741 sqlite3_free(zFree);
114742 return zRet;
114743 }
114744
114745 /*
114746 ** This function interprets the string at (*pp) as a non-negative integer
114747 ** value. It reads the integer and sets *pnOut to the value read, then
114748 ** sets *pp to point to the byte immediately following the last byte of
114749 ** the integer value.
114750 **
114751 ** Only decimal digits ('0'..'9') may be part of an integer value.
114752 **
114753 ** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
114754 ** the output value undefined. Otherwise SQLITE_OK is returned.
114755 **
114756 ** This function is used when parsing the "prefix=" FTS4 parameter.
114757 */
114758 static int fts3GobbleInt(const char **pp, int *pnOut){
114759 const char *p = *pp; /* Iterator pointer */
114760 int nInt = 0; /* Output value */
114761
114762 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
114763 nInt = nInt * 10 + (p[0] - '0');
114764 }
114765 if( p==*pp ) return SQLITE_ERROR;
114766 *pnOut = nInt;
114767 *pp = p;
114768 return SQLITE_OK;
114769 }
114770
114771 /*
114772 ** This function is called to allocate an array of Fts3Index structures
114773 ** representing the indexes maintained by the current FTS table. FTS tables
114774 ** always maintain the main "terms" index, but may also maintain one or
114775 ** more "prefix" indexes, depending on the value of the "prefix=" parameter
114776 ** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
114777 **
114778 ** Argument zParam is passed the value of the "prefix=" option if one was
114779 ** specified, or NULL otherwise.
114780 **
114781 ** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
114782 ** the allocated array. *pnIndex is set to the number of elements in the
114783 ** array. If an error does occur, an SQLite error code is returned.
114784 **
114785 ** Regardless of whether or not an error is returned, it is the responsibility
114786 ** of the caller to call sqlite3_free() on the output array to free it.
114787 */
114788 static int fts3PrefixParameter(
114789 const char *zParam, /* ABC in prefix=ABC parameter to parse */
114790 int *pnIndex, /* OUT: size of *apIndex[] array */
114791 struct Fts3Index **apIndex /* OUT: Array of indexes for this table */
 
114792 ){
114793 struct Fts3Index *aIndex; /* Allocated array */
114794 int nIndex = 1; /* Number of entries in array */
114795
114796 if( zParam && zParam[0] ){
114797 const char *p;
114798 nIndex++;
114799 for(p=zParam; *p; p++){
@@ -112749,11 +114800,11 @@
114800 if( *p==',' ) nIndex++;
114801 }
114802 }
114803
114804 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
114805 *apIndex = aIndex;
114806 *pnIndex = nIndex;
114807 if( !aIndex ){
114808 return SQLITE_NOMEM;
114809 }
114810
@@ -112806,12 +114857,11 @@
114857 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
114858 const char **aCol; /* Array of column names */
114859 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
114860
114861 int nIndex; /* Size of aIndex[] array */
114862 struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
 
114863
114864 /* The results of parsing supported FTS4 key=value options: */
114865 int bNoDocsize = 0; /* True to omit %_docsize table */
114866 int bDescIdx = 0; /* True to store descending indexes */
114867 char *zPrefix = 0; /* Prefix parameter value (or NULL) */
@@ -112944,11 +114994,11 @@
114994 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
114995 if( rc!=SQLITE_OK ) goto fts3_init_out;
114996 }
114997 assert( pTokenizer );
114998
114999 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
115000 if( rc==SQLITE_ERROR ){
115001 assert( zPrefix );
115002 *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
115003 }
115004 if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -112995,11 +115045,11 @@
115045 zCsr += nDb;
115046
115047 /* Fill in the azColumn array */
115048 for(iCol=0; iCol<nCol; iCol++){
115049 char *z;
115050 int n = 0;
115051 z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
115052 memcpy(zCsr, z, n);
115053 zCsr[n] = '\0';
115054 sqlite3Fts3Dequote(zCsr);
115055 p->azColumn[iCol] = zCsr;
@@ -113031,11 +115081,11 @@
115081 /* Declare the table schema to SQLite. */
115082 fts3DeclareVtab(&rc, p);
115083
115084 fts3_init_out:
115085 sqlite3_free(zPrefix);
115086 sqlite3_free(aIndex);
115087 sqlite3_free(zCompress);
115088 sqlite3_free(zUncompress);
115089 sqlite3_free((void *)aCol);
115090 if( rc!=SQLITE_OK ){
115091 if( p ){
@@ -113622,12 +115672,10 @@
115672 *pp1 = p1 + 1;
115673 *pp2 = p2 + 1;
115674 }
115675
115676 /*
 
 
115677 ** This function is used to merge two position lists into one. When it is
115678 ** called, *pp1 and *pp2 must both point to position lists. A position-list is
115679 ** the part of a doclist that follows each document id. For example, if a row
115680 ** contains:
115681 **
@@ -113643,10 +115691,12 @@
115691 ** If isSaveLeft is 0, an entry is added to the output position list for
115692 ** each position in *pp2 for which there exists one or more positions in
115693 ** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
115694 ** when the *pp1 token appears before the *pp2 token, but not more than nToken
115695 ** slots before it.
115696 **
115697 ** e.g. nToken==1 searches for adjacent positions.
115698 */
115699 static int fts3PoslistPhraseMerge(
115700 char **pp, /* IN/OUT: Preallocated output buffer */
115701 int nToken, /* Maximum difference in token positions */
115702 int isSaveLeft, /* Save the left position */
@@ -113809,26 +115859,38 @@
115859
115860 return res;
115861 }
115862
115863 /*
115864 ** An instance of this function is used to merge together the (potentially
115865 ** large number of) doclists for each term that matches a prefix query.
115866 ** See function fts3TermSelectMerge() for details.
115867 */
115868 typedef struct TermSelect TermSelect;
115869 struct TermSelect {
115870 char *aaOutput[16]; /* Malloc'd output buffers */
115871 int anOutput[16]; /* Size each output buffer in bytes */
 
115872 };
115873
115874 /*
115875 ** This function is used to read a single varint from a buffer. Parameter
115876 ** pEnd points 1 byte past the end of the buffer. When this function is
115877 ** called, if *pp points to pEnd or greater, then the end of the buffer
115878 ** has been reached. In this case *pp is set to 0 and the function returns.
115879 **
115880 ** If *pp does not point to or past pEnd, then a single varint is read
115881 ** from *pp. *pp is then set to point 1 byte past the end of the read varint.
115882 **
115883 ** If bDescIdx is false, the value read is added to *pVal before returning.
115884 ** If it is true, the value read is subtracted from *pVal before this
115885 ** function returns.
115886 */
115887 static void fts3GetDeltaVarint3(
115888 char **pp, /* IN/OUT: Point to read varint from */
115889 char *pEnd, /* End of buffer */
115890 int bDescIdx, /* True if docids are descending */
115891 sqlite3_int64 *pVal /* IN/OUT: Integer value */
115892 ){
115893 if( *pp>=pEnd ){
115894 *pp = 0;
115895 }else{
115896 sqlite3_int64 iVal;
@@ -113839,10 +115901,25 @@
115901 *pVal += iVal;
115902 }
115903 }
115904 }
115905
115906 /*
115907 ** This function is used to write a single varint to a buffer. The varint
115908 ** is written to *pp. Before returning, *pp is set to point 1 byte past the
115909 ** end of the value written.
115910 **
115911 ** If *pbFirst is zero when this function is called, the value written to
115912 ** the buffer is that of parameter iVal.
115913 **
115914 ** If *pbFirst is non-zero when this function is called, then the value
115915 ** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
115916 ** (if bDescIdx is non-zero).
115917 **
115918 ** Before returning, this function always sets *pbFirst to 1 and *piPrev
115919 ** to the value of parameter iVal.
115920 */
115921 static void fts3PutDeltaVarint3(
115922 char **pp, /* IN/OUT: Output pointer */
115923 int bDescIdx, /* True for descending docids */
115924 sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
115925 int *pbFirst, /* IN/OUT: True after first int written */
@@ -113859,14 +115936,38 @@
115936 *pp += sqlite3Fts3PutVarint(*pp, iWrite);
115937 *piPrev = iVal;
115938 *pbFirst = 1;
115939 }
115940
 
115941
115942 /*
115943 ** This macro is used by various functions that merge doclists. The two
115944 ** arguments are 64-bit docid values. If the value of the stack variable
115945 ** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
115946 ** Otherwise, (i2-i1).
115947 **
115948 ** Using this makes it easier to write code that can merge doclists that are
115949 ** sorted in either ascending or descending order.
115950 */
115951 #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
115952
115953 /*
115954 ** This function does an "OR" merge of two doclists (output contains all
115955 ** positions contained in either argument doclist). If the docids in the
115956 ** input doclists are sorted in ascending order, parameter bDescDoclist
115957 ** should be false. If they are sorted in ascending order, it should be
115958 ** passed a non-zero value.
115959 **
115960 ** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
115961 ** containing the output doclist and SQLITE_OK is returned. In this case
115962 ** *pnOut is set to the number of bytes in the output doclist.
115963 **
115964 ** If an error occurs, an SQLite error code is returned. The output values
115965 ** are undefined in this case.
115966 */
115967 static int fts3DoclistOrMerge(
115968 int bDescDoclist, /* True if arguments are desc */
115969 char *a1, int n1, /* First doclist */
115970 char *a2, int n2, /* Second doclist */
115971 char **paOut, int *pnOut /* OUT: Malloc'd doclist */
115972 ){
115973 sqlite3_int64 i1 = 0;
@@ -113887,35 +115988,47 @@
115988
115989 p = aOut;
115990 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
115991 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
115992 while( p1 || p2 ){
115993 sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
115994
115995 if( p2 && p1 && iDiff==0 ){
115996 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
115997 fts3PoslistMerge(&p, &p1, &p2);
115998 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
115999 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
116000 }else if( !p2 || (p1 && iDiff<0) ){
116001 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
116002 fts3PoslistCopy(&p, &p1);
116003 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
116004 }else{
116005 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
116006 fts3PoslistCopy(&p, &p2);
116007 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
116008 }
116009 }
116010
116011 *paOut = aOut;
116012 *pnOut = (p-aOut);
116013 return SQLITE_OK;
116014 }
116015
116016 /*
116017 ** This function does a "phrase" merge of two doclists. In a phrase merge,
116018 ** the output contains a copy of each position from the right-hand input
116019 ** doclist for which there is a position in the left-hand input doclist
116020 ** exactly nDist tokens before it.
116021 **
116022 ** If the docids in the input doclists are sorted in ascending order,
116023 ** parameter bDescDoclist should be false. If they are sorted in ascending
116024 ** order, it should be passed a non-zero value.
116025 **
116026 ** The right-hand input doclist is overwritten by this function.
116027 */
116028 static void fts3DoclistPhraseMerge(
116029 int bDescDoclist, /* True if arguments are desc */
116030 int nDist, /* Distance from left to right (1=adjacent) */
116031 char *aLeft, int nLeft, /* Left doclist */
116032 char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
116033 ){
116034 sqlite3_int64 i1 = 0;
@@ -113934,30 +116047,30 @@
116047 p = aOut;
116048 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
116049 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
116050
116051 while( p1 && p2 ){
116052 sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
116053 if( iDiff==0 ){
116054 char *pSave = p;
116055 sqlite3_int64 iPrevSave = iPrev;
116056 int bFirstOutSave = bFirstOut;
116057
116058 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
116059 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
116060 p = pSave;
116061 iPrev = iPrevSave;
116062 bFirstOut = bFirstOutSave;
116063 }
116064 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
116065 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
116066 }else if( iDiff<0 ){
116067 fts3PoslistCopy(0, &p1);
116068 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
116069 }else{
116070 fts3PoslistCopy(0, &p2);
116071 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
116072 }
116073 }
116074
116075 *pnRight = p - aOut;
116076 }
@@ -113970,11 +116083,11 @@
116083 **
116084 ** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
116085 ** the responsibility of the caller to free any doclists left in the
116086 ** TermSelect.aaOutput[] array.
116087 */
116088 static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
116089 char *aOut = 0;
116090 int nOut = 0;
116091 int i;
116092
116093 /* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -114011,28 +116124,29 @@
116124 pTS->anOutput[0] = nOut;
116125 return SQLITE_OK;
116126 }
116127
116128 /*
116129 ** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
116130 ** as the first argument. The merge is an "OR" merge (see function
116131 ** fts3DoclistOrMerge() for details).
116132 **
116133 ** This function is called with the doclist for each term that matches
116134 ** a queried prefix. It merges all these doclists into one, the doclist
116135 ** for the specified prefix. Since there can be a very large number of
116136 ** doclists to merge, the merging is done pair-wise using the TermSelect
116137 ** object.
116138 **
116139 ** This function returns SQLITE_OK if the merge is successful, or an
116140 ** SQLite error code (SQLITE_NOMEM) if an error occurs.
116141 */
116142 static int fts3TermSelectMerge(
116143 Fts3Table *p, /* FTS table handle */
116144 TermSelect *pTS, /* TermSelect object to merge into */
116145 char *aDoclist, /* Pointer to doclist */
116146 int nDoclist /* Size of aDoclist in bytes */
 
 
116147 ){
 
 
 
 
 
 
116148 if( pTS->aaOutput[0]==0 ){
116149 /* If this is the first term selected, copy the doclist to the output
116150 ** buffer using memcpy(). */
116151 pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
116152 pTS->anOutput[0] = nDoclist;
@@ -114099,23 +116213,30 @@
116213 }
116214 pCsr->apSegment[pCsr->nSegment++] = pNew;
116215 return SQLITE_OK;
116216 }
116217
116218 /*
116219 ** Add seg-reader objects to the Fts3MultiSegReader object passed as the
116220 ** 8th argument.
116221 **
116222 ** This function returns SQLITE_OK if successful, or an SQLite error code
116223 ** otherwise.
116224 */
116225 static int fts3SegReaderCursor(
116226 Fts3Table *p, /* FTS3 table handle */
116227 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
116228 int iLevel, /* Level of segments to scan */
116229 const char *zTerm, /* Term to query for */
116230 int nTerm, /* Size of zTerm in bytes */
116231 int isPrefix, /* True for a prefix search */
116232 int isScan, /* True to scan from zTerm to EOF */
116233 Fts3MultiSegReader *pCsr /* Cursor object to populate */
116234 ){
116235 int rc = SQLITE_OK; /* Error code */
116236 sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
116237 int rc2; /* Result of sqlite3_reset() */
116238
116239 /* If iLevel is less than 0 and this is not a scan, include a seg-reader
116240 ** for the pending-terms. If this is a scan, then this call must be being
116241 ** made by an fts4aux module, not an FTS table. In this case calling
116242 ** Fts3SegReaderPending might segfault, as the data structures used by
@@ -114200,28 +116321,46 @@
116321 return fts3SegReaderCursor(
116322 p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
116323 );
116324 }
116325
116326 /*
116327 ** In addition to its current configuration, have the Fts3MultiSegReader
116328 ** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
116329 **
116330 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
116331 */
116332 static int fts3SegReaderCursorAddZero(
116333 Fts3Table *p, /* FTS virtual table handle */
116334 const char *zTerm, /* Term to scan doclist of */
116335 int nTerm, /* Number of bytes in zTerm */
116336 Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
116337 ){
116338 return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
116339 }
116340
116341 /*
116342 ** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
116343 ** if isPrefix is true, to scan the doclist for all terms for which
116344 ** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
116345 ** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
116346 ** an SQLite error code.
116347 **
116348 ** It is the responsibility of the caller to free this object by eventually
116349 ** passing it to fts3SegReaderCursorFree()
116350 **
116351 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
116352 ** Output parameter *ppSegcsr is set to 0 if an error occurs.
116353 */
116354 static int fts3TermSegReaderCursor(
116355 Fts3Cursor *pCsr, /* Virtual table cursor handle */
116356 const char *zTerm, /* Term to query for */
116357 int nTerm, /* Size of zTerm in bytes */
116358 int isPrefix, /* True for a prefix search */
116359 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
116360 ){
116361 Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
116362 int rc = SQLITE_NOMEM; /* Return code */
116363
116364 pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
116365 if( pSegcsr ){
116366 int i;
@@ -114261,62 +116400,53 @@
116400
116401 *ppSegcsr = pSegcsr;
116402 return rc;
116403 }
116404
116405 /*
116406 ** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
116407 */
116408 static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
116409 sqlite3Fts3SegReaderFinish(pSegcsr);
116410 sqlite3_free(pSegcsr);
116411 }
116412
116413 /*
116414 ** This function retreives the doclist for the specified term (or term
116415 ** prefix) from the database.
 
 
 
 
 
 
 
116416 */
116417 static int fts3TermSelect(
116418 Fts3Table *p, /* Virtual table handle */
116419 Fts3PhraseToken *pTok, /* Token to query for */
116420 int iColumn, /* Column to query (or -ve for all columns) */
 
116421 int *pnOut, /* OUT: Size of buffer at *ppOut */
116422 char **ppOut /* OUT: Malloced result buffer */
116423 ){
116424 int rc; /* Return code */
116425 Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
116426 TermSelect tsc; /* Object for pair-wise doclist merging */
116427 Fts3SegFilter filter; /* Segment term filter configuration */
116428
116429 pSegcsr = pTok->pSegcsr;
116430 memset(&tsc, 0, sizeof(TermSelect));
 
116431
116432 filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
116433 | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
 
116434 | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
116435 filter.iCol = iColumn;
116436 filter.zTerm = pTok->z;
116437 filter.nTerm = pTok->n;
116438
116439 rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
116440 while( SQLITE_OK==rc
116441 && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
116442 ){
116443 rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
 
 
116444 }
116445
116446 if( rc==SQLITE_OK ){
116447 rc = fts3TermSelectFinishMerge(p, &tsc);
116448 }
116449 if( rc==SQLITE_OK ){
116450 *ppOut = tsc.aaOutput[0];
116451 *pnOut = tsc.anOutput[0];
116452 }else{
@@ -114338,28 +116468,19 @@
116468 ** If the isPoslist argument is true, then it is assumed that the doclist
116469 ** contains a position-list following each docid. Otherwise, it is assumed
116470 ** that the doclist is simply a list of docids stored as delta encoded
116471 ** varints.
116472 */
116473 static int fts3DoclistCountDocids(char *aList, int nList){
116474 int nDoc = 0; /* Return value */
116475 if( aList ){
116476 char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
116477 char *p = aList; /* Cursor */
116478 while( p<aEnd ){
116479 nDoc++;
116480 while( (*p++)&0x80 ); /* Skip docid varint */
116481 fts3PoslistCopy(0, &p); /* Skip over position list */
 
 
 
 
 
 
 
 
 
116482 }
116483 }
116484
116485 return nDoc;
116486 }
@@ -114385,11 +116506,11 @@
116506 }else{
116507 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
116508 rc = SQLITE_OK;
116509 }
116510 }else{
116511 rc = fts3EvalNext((Fts3Cursor *)pCursor);
116512 }
116513 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
116514 return rc;
116515 }
116516
@@ -114462,11 +116583,11 @@
116583 }
116584
116585 rc = sqlite3Fts3ReadLock(p);
116586 if( rc!=SQLITE_OK ) return rc;
116587
116588 rc = fts3EvalStart(pCsr);
116589
116590 sqlite3Fts3SegmentsClose(p);
116591 if( rc!=SQLITE_OK ) return rc;
116592 pCsr->pNextId = pCsr->aDoclist;
116593 pCsr->iPrevId = 0;
@@ -114581,12 +116702,12 @@
116702
116703 /*
116704 ** Implementation of xBegin() method. This is a no-op.
116705 */
116706 static int fts3BeginMethod(sqlite3_vtab *pVtab){
 
116707 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
116708 UNUSED_PARAMETER(pVtab);
116709 assert( p->pSegments==0 );
116710 assert( p->nPendingData==0 );
116711 assert( p->inTransaction!=1 );
116712 TESTONLY( p->inTransaction = 1 );
116713 TESTONLY( p->mxSavepoint = -1; );
@@ -114597,12 +116718,12 @@
116718 ** Implementation of xCommit() method. This is a no-op. The contents of
116719 ** the pending-terms hash-table have already been flushed into the database
116720 ** by fts3SyncMethod().
116721 */
116722 static int fts3CommitMethod(sqlite3_vtab *pVtab){
 
116723 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
116724 UNUSED_PARAMETER(pVtab);
116725 assert( p->nPendingData==0 );
116726 assert( p->inTransaction!=0 );
116727 assert( p->pSegments==0 );
116728 TESTONLY( p->inTransaction = 0 );
116729 TESTONLY( p->mxSavepoint = -1; );
@@ -114869,26 +116990,43 @@
116990 p->zDb, p->zName, zName
116991 );
116992 return rc;
116993 }
116994
116995 /*
116996 ** The xSavepoint() method.
116997 **
116998 ** Flush the contents of the pending-terms table to disk.
116999 */
117000 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
117001 UNUSED_PARAMETER(iSavepoint);
117002 assert( ((Fts3Table *)pVtab)->inTransaction );
117003 assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
117004 TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
117005 return fts3SyncMethod(pVtab);
117006 }
117007
117008 /*
117009 ** The xRelease() method.
117010 **
117011 ** This is a no-op.
117012 */
117013 static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
117014 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
117015 UNUSED_PARAMETER(iSavepoint);
117016 UNUSED_PARAMETER(pVtab);
117017 assert( p->inTransaction );
117018 assert( p->mxSavepoint >= iSavepoint );
117019 TESTONLY( p->mxSavepoint = iSavepoint-1 );
117020 return SQLITE_OK;
117021 }
117022
117023 /*
117024 ** The xRollbackTo() method.
117025 **
117026 ** Discard the contents of the pending terms table.
117027 */
117028 static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
117029 Fts3Table *p = (Fts3Table*)pVtab;
117030 UNUSED_PARAMETER(iSavepoint);
117031 assert( p->inTransaction );
117032 assert( p->mxSavepoint >= iSavepoint );
@@ -115033,22 +117171,10 @@
117171 sqlite3Fts3HashClear(pHash);
117172 sqlite3_free(pHash);
117173 }
117174 return rc;
117175 }
 
 
 
 
 
 
 
 
 
 
 
 
117176
117177 /*
117178 ** Allocate an Fts3MultiSegReader for each token in the expression headed
117179 ** by pExpr.
117180 **
@@ -115062,99 +117188,151 @@
117188 ** there exists prefix b-tree of the right length) then it may be traversed
117189 ** and merged incrementally. Otherwise, it has to be merged into an in-memory
117190 ** doclist and then traversed.
117191 */
117192 static void fts3EvalAllocateReaders(
117193 Fts3Cursor *pCsr, /* FTS cursor handle */
117194 Fts3Expr *pExpr, /* Allocate readers for this expression */
117195 int *pnToken, /* OUT: Total number of tokens in phrase. */
117196 int *pnOr, /* OUT: Total number of OR nodes in expr. */
117197 int *pRc /* IN/OUT: Error code */
117198 ){
117199 if( pExpr && SQLITE_OK==*pRc ){
117200 if( pExpr->eType==FTSQUERY_PHRASE ){
117201 int i;
117202 int nToken = pExpr->pPhrase->nToken;
117203 *pnToken += nToken;
117204 for(i=0; i<nToken; i++){
117205 Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
117206 int rc = fts3TermSegReaderCursor(pCsr,
117207 pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
117208 );
117209 if( rc!=SQLITE_OK ){
117210 *pRc = rc;
117211 return;
117212 }
117213 }
117214 assert( pExpr->pPhrase->iDoclistToken==0 );
117215 pExpr->pPhrase->iDoclistToken = -1;
117216 }else{
117217 *pnOr += (pExpr->eType==FTSQUERY_OR);
117218 fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
117219 fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
117220 }
117221 }
117222 }
117223
117224 /*
117225 ** Arguments pList/nList contain the doclist for token iToken of phrase p.
117226 ** It is merged into the main doclist stored in p->doclist.aAll/nAll.
117227 **
117228 ** This function assumes that pList points to a buffer allocated using
117229 ** sqlite3_malloc(). This function takes responsibility for eventually
117230 ** freeing the buffer.
117231 */
117232 static void fts3EvalPhraseMergeToken(
117233 Fts3Table *pTab, /* FTS Table pointer */
117234 Fts3Phrase *p, /* Phrase to merge pList/nList into */
117235 int iToken, /* Token pList/nList corresponds to */
117236 char *pList, /* Pointer to doclist */
117237 int nList /* Number of bytes in pList */
117238 ){
117239 assert( iToken!=p->iDoclistToken );
117240
117241 if( pList==0 ){
117242 sqlite3_free(p->doclist.aAll);
117243 p->doclist.aAll = 0;
117244 p->doclist.nAll = 0;
117245 }
117246
117247 else if( p->iDoclistToken<0 ){
117248 p->doclist.aAll = pList;
117249 p->doclist.nAll = nList;
117250 }
117251
117252 else if( p->doclist.aAll==0 ){
117253 sqlite3_free(pList);
117254 }
117255
117256 else {
117257 char *pLeft;
117258 char *pRight;
117259 int nLeft;
117260 int nRight;
117261 int nDiff;
117262
117263 if( p->iDoclistToken<iToken ){
117264 pLeft = p->doclist.aAll;
117265 nLeft = p->doclist.nAll;
117266 pRight = pList;
117267 nRight = nList;
117268 nDiff = iToken - p->iDoclistToken;
117269 }else{
117270 pRight = p->doclist.aAll;
117271 nRight = p->doclist.nAll;
117272 pLeft = pList;
117273 nLeft = nList;
117274 nDiff = p->iDoclistToken - iToken;
117275 }
117276
117277 fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight);
117278 sqlite3_free(pLeft);
117279 p->doclist.aAll = pRight;
117280 p->doclist.nAll = nRight;
117281 }
117282
117283 if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
117284 }
117285
117286 /*
117287 ** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
117288 ** does not take deferred tokens into account.
117289 **
117290 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
117291 */
117292 static int fts3EvalPhraseLoad(
117293 Fts3Cursor *pCsr, /* FTS Cursor handle */
117294 Fts3Phrase *p /* Phrase object */
117295 ){
117296 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
117297 int iToken;
117298 int rc = SQLITE_OK;
117299
 
 
 
 
117300 for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
117301 Fts3PhraseToken *pToken = &p->aToken[iToken];
117302 assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
117303
117304 if( pToken->pSegcsr ){
117305 int nThis = 0;
117306 char *pThis = 0;
117307 rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
117308 if( rc==SQLITE_OK ){
117309 fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
117310 }
117311 }
117312 assert( pToken->pSegcsr==0 );
117313 }
117314
117315 return rc;
117316 }
117317
117318 /*
117319 ** This function is called on each phrase after the position lists for
117320 ** any deferred tokens have been loaded into memory. It updates the phrases
117321 ** current position list to include only those positions that are really
117322 ** instances of the phrase (after considering deferred tokens). If this
117323 ** means that the phrase does not appear in the current row, doclist.pList
117324 ** and doclist.nList are both zeroed.
117325 **
117326 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
117327 */
 
 
 
 
 
 
 
 
 
 
 
 
117328 static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
117329 int iToken; /* Used to iterate through phrase tokens */
117330 int rc = SQLITE_OK; /* Return code */
117331 char *aPoslist = 0; /* Position list for deferred tokens */
117332 int nPoslist = 0; /* Number of bytes in aPoslist */
117333 int iPrev = -1; /* Token number of previous deferred token */
 
 
117334
117335 assert( pPhrase->doclist.bFreeList==0 );
117336
117337 for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
117338 Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -115192,16 +117370,15 @@
117370 pPhrase->doclist.nList = 0;
117371 return SQLITE_OK;
117372 }
117373 }
117374 iPrev = iToken;
 
 
117375 }
117376 }
117377
117378 if( iPrev>=0 ){
117379 int nMaxUndeferred = pPhrase->iDoclistToken;
117380 if( nMaxUndeferred<0 ){
117381 pPhrase->doclist.pList = aPoslist;
117382 pPhrase->doclist.nList = nPoslist;
117383 pPhrase->doclist.iDocid = pCsr->iPrevId;
117384 pPhrase->doclist.bFreeList = 1;
@@ -115246,19 +117423,27 @@
117423 /*
117424 ** This function is called for each Fts3Phrase in a full-text query
117425 ** expression to initialize the mechanism for returning rows. Once this
117426 ** function has been called successfully on an Fts3Phrase, it may be
117427 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
117428 **
117429 ** If parameter bOptOk is true, then the phrase may (or may not) use the
117430 ** incremental loading strategy. Otherwise, the entire doclist is loaded into
117431 ** memory within this call.
117432 **
117433 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
117434 */
117435 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
117436 int rc; /* Error code */
117437 Fts3PhraseToken *pFirst = &p->aToken[0];
117438 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
117439
117440 if( pCsr->bDesc==pTab->bDescIdx
117441 && bOptOk==1
117442 && p->nToken==1
117443 && pFirst->pSegcsr
117444 && pFirst->pSegcsr->bLookup
117445 ){
117446 /* Use the incremental approach. */
117447 int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
117448 rc = sqlite3Fts3MsrIncrStart(
117449 pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
@@ -115274,11 +117459,17 @@
117459 return rc;
117460 }
117461
117462 /*
117463 ** This function is used to iterate backwards (from the end to start)
117464 ** through doclists. It is used by this module to iterate through phrase
117465 ** doclists in reverse and by the fts3_write.c module to iterate through
117466 ** pending-terms lists when writing to databases with "order=desc".
117467 **
117468 ** The doclist may be sorted in ascending (parameter bDescIdx==0) or
117469 ** descending (parameter bDescIdx==1) order of docid. Regardless, this
117470 ** function iterates from the end of the doclist to the beginning.
117471 */
117472 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
117473 int bDescIdx, /* True if the doclist is desc */
117474 char *aDoclist, /* Pointer to entire doclist */
117475 int nDoclist, /* Length of aDoclist in bytes */
@@ -115339,13 +117530,13 @@
117530 ** If there is no "next" entry and no error occurs, then *pbEof is set to
117531 ** 1 before returning. Otherwise, if no error occurs and the iterator is
117532 ** successfully advanced, *pbEof is set to 0.
117533 */
117534 static int fts3EvalPhraseNext(
117535 Fts3Cursor *pCsr, /* FTS Cursor handle */
117536 Fts3Phrase *p, /* Phrase object to advance to next docid */
117537 u8 *pbEof /* OUT: Set to 1 if EOF */
117538 ){
117539 int rc = SQLITE_OK;
117540 Fts3Doclist *pDL = &p->doclist;
117541 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
117542
@@ -115387,30 +117578,46 @@
117578 fts3PoslistCopy(0, &pIter);
117579 pDL->nList = (pIter - pDL->pList);
117580
117581 /* pIter now points just past the 0x00 that terminates the position-
117582 ** list for document pDL->iDocid. However, if this position-list was
117583 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
117584 ** point to the start of the next docid value. The following line deals
117585 ** with this case by advancing pIter past the zero-padding added by
117586 ** fts3EvalNearTrim(). */
117587 while( pIter<pEnd && *pIter==0 ) pIter++;
117588
117589 pDL->pNextDocid = pIter;
117590 assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
117591 *pbEof = 0;
117592 }
117593 }
117594
117595 return rc;
117596 }
117597
117598 /*
117599 **
117600 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
117601 ** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
117602 ** expression. Also the Fts3Expr.bDeferred variable is set to true for any
117603 ** expressions for which all descendent tokens are deferred.
117604 **
117605 ** If parameter bOptOk is zero, then it is guaranteed that the
117606 ** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
117607 ** each phrase in the expression (subject to deferred token processing).
117608 ** Or, if bOptOk is non-zero, then one or more tokens within the expression
117609 ** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
117610 **
117611 ** If an error occurs within this function, *pRc is set to an SQLite error
117612 ** code before returning.
117613 */
117614 static void fts3EvalStartReaders(
117615 Fts3Cursor *pCsr, /* FTS Cursor handle */
117616 Fts3Expr *pExpr, /* Expression to initialize phrases in */
117617 int bOptOk, /* True to enable incremental loading */
117618 int *pRc /* IN/OUT: Error code */
117619 ){
117620 if( pExpr && SQLITE_OK==*pRc ){
117621 if( pExpr->eType==FTSQUERY_PHRASE ){
117622 int i;
117623 int nToken = pExpr->pPhrase->nToken;
@@ -115425,33 +117632,55 @@
117632 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
117633 }
117634 }
117635 }
117636
117637 /*
117638 ** An array of the following structures is assembled as part of the process
117639 ** of selecting tokens to defer before the query starts executing (as part
117640 ** of the xFilter() method). There is one element in the array for each
117641 ** token in the FTS expression.
117642 **
117643 ** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
117644 ** to phrases that are connected only by AND and NEAR operators (not OR or
117645 ** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
117646 ** separately. The root of a tokens AND/NEAR cluster is stored in
117647 ** Fts3TokenAndCost.pRoot.
117648 */
117649 typedef struct Fts3TokenAndCost Fts3TokenAndCost;
117650 struct Fts3TokenAndCost {
117651 Fts3Phrase *pPhrase; /* The phrase the token belongs to */
117652 int iToken; /* Position of token in phrase */
117653 Fts3PhraseToken *pToken; /* The token itself */
117654 Fts3Expr *pRoot; /* Root of NEAR/AND cluster */
117655 int nOvfl; /* Number of overflow pages to load doclist */
117656 int iCol; /* The column the token must match */
117657 };
117658
117659 /*
117660 ** This function is used to populate an allocated Fts3TokenAndCost array.
117661 **
117662 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
117663 ** Otherwise, if an error occurs during execution, *pRc is set to an
117664 ** SQLite error code.
117665 */
117666 static void fts3EvalTokenCosts(
117667 Fts3Cursor *pCsr, /* FTS Cursor handle */
117668 Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */
117669 Fts3Expr *pExpr, /* Expression to consider */
117670 Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */
117671 Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */
117672 int *pRc /* IN/OUT: Error code */
117673 ){
117674 if( *pRc==SQLITE_OK && pExpr ){
117675 if( pExpr->eType==FTSQUERY_PHRASE ){
117676 Fts3Phrase *pPhrase = pExpr->pPhrase;
117677 int i;
117678 for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
117679 Fts3TokenAndCost *pTC = (*ppTC)++;
117680 pTC->pPhrase = pPhrase;
117681 pTC->iToken = i;
117682 pTC->pRoot = pRoot;
117683 pTC->pToken = &pPhrase->aToken[i];
117684 pTC->iCol = pPhrase->iColumn;
117685 *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
117686 }
@@ -115470,23 +117699,34 @@
117699 fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
117700 }
117701 }
117702 }
117703
117704 /*
117705 ** Determine the average document (row) size in pages. If successful,
117706 ** write this value to *pnPage and return SQLITE_OK. Otherwise, return
117707 ** an SQLite error code.
117708 **
117709 ** The average document size in pages is calculated by first calculating
117710 ** determining the average size in bytes, B. If B is less than the amount
117711 ** of data that will fit on a single leaf page of an intkey table in
117712 ** this database, then the average docsize is 1. Otherwise, it is 1 plus
117713 ** the number of overflow pages consumed by a record B bytes in size.
117714 */
117715 static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
117716 if( pCsr->nRowAvg==0 ){
117717 /* The average document size, which is required to calculate the cost
117718 ** of each doclist, has not yet been determined. Read the required
117719 ** data from the %_stat table to calculate it.
117720 **
117721 ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
117722 ** varints, where nCol is the number of columns in the FTS3 table.
117723 ** The first varint is the number of documents currently stored in
117724 ** the table. The following nCol varints contain the total amount of
117725 ** data stored in all rows of each column of the table, from left
117726 ** to right.
117727 */
117728 int rc;
117729 Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
117730 sqlite3_stmt *pStmt;
117731 sqlite3_int64 nDoc = 0;
117732 sqlite3_int64 nByte = 0;
@@ -115517,113 +117757,151 @@
117757
117758 *pnPage = pCsr->nRowAvg;
117759 return SQLITE_OK;
117760 }
117761
117762 /*
117763 ** This function is called to select the tokens (if any) that will be
117764 ** deferred. The array aTC[] has already been populated when this is
117765 ** called.
117766 **
117767 ** This function is called once for each AND/NEAR cluster in the
117768 ** expression. Each invocation determines which tokens to defer within
117769 ** the cluster with root node pRoot. See comments above the definition
117770 ** of struct Fts3TokenAndCost for more details.
117771 **
117772 ** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
117773 ** called on each token to defer. Otherwise, an SQLite error code is
117774 ** returned.
117775 */
117776 static int fts3EvalSelectDeferred(
117777 Fts3Cursor *pCsr, /* FTS Cursor handle */
117778 Fts3Expr *pRoot, /* Consider tokens with this root node */
117779 Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */
117780 int nTC /* Number of entries in aTC[] */
117781 ){
 
 
 
117782 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
117783 int nDocSize = 0; /* Number of pages per doc loaded */
117784 int rc = SQLITE_OK; /* Return code */
117785 int ii; /* Iterator variable for various purposes */
117786 int nOvfl = 0; /* Total overflow pages used by doclists */
117787 int nToken = 0; /* Total number of tokens in cluster */
117788
117789 int nMinEst = 0; /* The minimum count for any phrase so far. */
117790 int nLoad4 = 1; /* (Phrases that will be loaded)^4. */
117791
117792 /* Count the tokens in this AND/NEAR cluster. If none of the doclists
117793 ** associated with the tokens spill onto overflow pages, or if there is
117794 ** only 1 token, exit early. No tokens to defer in this case. */
117795 for(ii=0; ii<nTC; ii++){
117796 if( aTC[ii].pRoot==pRoot ){
117797 nOvfl += aTC[ii].nOvfl;
117798 nToken++;
117799 }
117800 }
117801 if( nOvfl==0 || nToken<2 ) return SQLITE_OK;
117802
117803 /* Obtain the average docsize (in pages). */
117804 rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
117805 assert( rc!=SQLITE_OK || nDocSize>0 );
117806
117807
117808 /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
117809 ** of the number of overflow pages that will be loaded by the pager layer
117810 ** to retrieve the entire doclist for the token from the full-text index.
117811 ** Load the doclists for tokens that are either:
117812 **
117813 ** a. The cheapest token in the entire query (i.e. the one visited by the
117814 ** first iteration of this loop), or
117815 **
117816 ** b. Part of a multi-token phrase.
117817 **
117818 ** After each token doclist is loaded, merge it with the others from the
117819 ** same phrase and count the number of documents that the merged doclist
117820 ** contains. Set variable "nMinEst" to the smallest number of documents in
117821 ** any phrase doclist for which 1 or more token doclists have been loaded.
117822 ** Let nOther be the number of other phrases for which it is certain that
117823 ** one or more tokens will not be deferred.
117824 **
117825 ** Then, for each token, defer it if loading the doclist would result in
117826 ** loading N or more overflow pages into memory, where N is computed as:
117827 **
117828 ** (nMinEst + 4^nOther - 1) / (4^nOther)
117829 */
117830 for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
117831 int iTC; /* Used to iterate through aTC[] array. */
117832 Fts3TokenAndCost *pTC = 0; /* Set to cheapest remaining token. */
117833
117834 /* Set pTC to point to the cheapest remaining token. */
117835 for(iTC=0; iTC<nTC; iTC++){
117836 if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
117837 && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
117838 ){
117839 pTC = &aTC[iTC];
117840 }
117841 }
117842 assert( pTC );
117843
117844 if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
117845 /* The number of overflow pages to load for this (and therefore all
117846 ** subsequent) tokens is greater than the estimated number of pages
117847 ** that will be loaded if all subsequent tokens are deferred.
117848 */
117849 Fts3PhraseToken *pToken = pTC->pToken;
117850 rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
117851 fts3SegReaderCursorFree(pToken->pSegcsr);
117852 pToken->pSegcsr = 0;
117853 }else{
117854 nLoad4 = nLoad4*4;
117855 if( ii==0 || pTC->pPhrase->nToken>1 ){
117856 /* Either this is the cheapest token in the entire query, or it is
117857 ** part of a multi-token phrase. Either way, the entire doclist will
117858 ** (eventually) be loaded into memory. It may as well be now. */
117859 Fts3PhraseToken *pToken = pTC->pToken;
117860 int nList = 0;
117861 char *pList = 0;
117862 rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
117863 assert( rc==SQLITE_OK || pList==0 );
117864 if( rc==SQLITE_OK ){
117865 int nCount;
117866 fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
117867 nCount = fts3DoclistCountDocids(
117868 pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
 
117869 );
117870 if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
117871 }
117872 }
 
 
 
 
 
 
 
 
117873 }
117874 pTC->pToken = 0;
117875 }
117876
117877 return rc;
117878 }
117879
117880 /*
117881 ** This function is called from within the xFilter method. It initializes
117882 ** the full-text query currently stored in pCsr->pExpr. To iterate through
117883 ** the results of a query, the caller does:
117884 **
117885 ** fts3EvalStart(pCsr);
117886 ** while( 1 ){
117887 ** fts3EvalNext(pCsr);
117888 ** if( pCsr->bEof ) break;
117889 ** ... return row pCsr->iPrevId to the caller ...
117890 ** }
117891 */
117892 static int fts3EvalStart(Fts3Cursor *pCsr){
117893 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
117894 int rc = SQLITE_OK;
117895 int nToken = 0;
117896 int nOr = 0;
117897
117898 /* Allocate a MultiSegReader for each token in the expression. */
117899 fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
117900
117901 /* Determine which, if any, tokens in the expression should be deferred. */
117902 if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117903 Fts3TokenAndCost *aTC;
117904 Fts3Expr **apOr;
117905 aTC = (Fts3TokenAndCost *)sqlite3_malloc(
117906 sizeof(Fts3TokenAndCost) * nToken
117907 + sizeof(Fts3Expr *) * nOr * 2
@@ -115635,11 +117913,11 @@
117913 }else{
117914 int ii;
117915 Fts3TokenAndCost *pTC = aTC;
117916 Fts3Expr **ppOr = apOr;
117917
117918 fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
117919 nToken = pTC-aTC;
117920 nOr = ppOr-apOr;
117921
117922 if( rc==SQLITE_OK ){
117923 rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
@@ -115650,25 +117928,50 @@
117928
117929 sqlite3_free(aTC);
117930 }
117931 }
117932
117933 fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
117934 return rc;
117935 }
117936
117937 /*
117938 ** Invalidate the current position list for phrase pPhrase.
117939 */
117940 static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
117941 if( pPhrase->doclist.bFreeList ){
117942 sqlite3_free(pPhrase->doclist.pList);
117943 }
117944 pPhrase->doclist.pList = 0;
117945 pPhrase->doclist.nList = 0;
117946 pPhrase->doclist.bFreeList = 0;
117947 }
117948
117949 /*
117950 ** This function is called to edit the position list associated with
117951 ** the phrase object passed as the fifth argument according to a NEAR
117952 ** condition. For example:
117953 **
117954 ** abc NEAR/5 "def ghi"
117955 **
117956 ** Parameter nNear is passed the NEAR distance of the expression (5 in
117957 ** the example above). When this function is called, *paPoslist points to
117958 ** the position list, and *pnToken is the number of phrase tokens in, the
117959 ** phrase on the other side of the NEAR operator to pPhrase. For example,
117960 ** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
117961 ** the position list associated with phrase "abc".
117962 **
117963 ** All positions in the pPhrase position list that are not sufficiently
117964 ** close to a position in the *paPoslist position list are removed. If this
117965 ** leaves 0 positions, zero is returned. Otherwise, non-zero.
117966 **
117967 ** Before returning, *paPoslist is set to point to the position lsit
117968 ** associated with pPhrase. And *pnToken is set to the number of tokens in
117969 ** pPhrase.
117970 */
117971 static int fts3EvalNearTrim(
117972 int nNear, /* NEAR distance. As in "NEAR/nNear". */
117973 char *aTmp, /* Temporary space to use */
117974 char **paPoslist, /* IN/OUT: Position list */
117975 int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
117976 Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
117977 ){
@@ -115696,10 +117999,176 @@
117999 }
118000
118001 return res;
118002 }
118003
118004 /*
118005 ** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
118006 ** Otherwise, it advances the expression passed as the second argument to
118007 ** point to the next matching row in the database. Expressions iterate through
118008 ** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
118009 ** or descending if it is non-zero.
118010 **
118011 ** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
118012 ** successful, the following variables in pExpr are set:
118013 **
118014 ** Fts3Expr.bEof (non-zero if EOF - there is no next row)
118015 ** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row)
118016 **
118017 ** If the expression is of type FTSQUERY_PHRASE, and the expression is not
118018 ** at EOF, then the following variables are populated with the position list
118019 ** for the phrase for the visited row:
118020 **
118021 ** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes)
118022 ** FTs3Expr.pPhrase->doclist.pList (pointer to position list)
118023 **
118024 ** It says above that this function advances the expression to the next
118025 ** matching row. This is usually true, but there are the following exceptions:
118026 **
118027 ** 1. Deferred tokens are not taken into account. If a phrase consists
118028 ** entirely of deferred tokens, it is assumed to match every row in
118029 ** the db. In this case the position-list is not populated at all.
118030 **
118031 ** Or, if a phrase contains one or more deferred tokens and one or
118032 ** more non-deferred tokens, then the expression is advanced to the
118033 ** next possible match, considering only non-deferred tokens. In other
118034 ** words, if the phrase is "A B C", and "B" is deferred, the expression
118035 ** is advanced to the next row that contains an instance of "A * C",
118036 ** where "*" may match any single token. The position list in this case
118037 ** is populated as for "A * C" before returning.
118038 **
118039 ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
118040 ** advanced to point to the next row that matches "x AND y".
118041 **
118042 ** See fts3EvalTestDeferredAndNear() for details on testing if a row is
118043 ** really a match, taking into account deferred tokens and NEAR operators.
118044 */
118045 static void fts3EvalNextRow(
118046 Fts3Cursor *pCsr, /* FTS Cursor handle */
118047 Fts3Expr *pExpr, /* Expr. to advance to next matching row */
118048 int *pRc /* IN/OUT: Error code */
118049 ){
118050 if( *pRc==SQLITE_OK ){
118051 int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */
118052 assert( pExpr->bEof==0 );
118053 pExpr->bStart = 1;
118054
118055 switch( pExpr->eType ){
118056 case FTSQUERY_NEAR:
118057 case FTSQUERY_AND: {
118058 Fts3Expr *pLeft = pExpr->pLeft;
118059 Fts3Expr *pRight = pExpr->pRight;
118060 assert( !pLeft->bDeferred || !pRight->bDeferred );
118061
118062 if( pLeft->bDeferred ){
118063 /* LHS is entirely deferred. So we assume it matches every row.
118064 ** Advance the RHS iterator to find the next row visited. */
118065 fts3EvalNextRow(pCsr, pRight, pRc);
118066 pExpr->iDocid = pRight->iDocid;
118067 pExpr->bEof = pRight->bEof;
118068 }else if( pRight->bDeferred ){
118069 /* RHS is entirely deferred. So we assume it matches every row.
118070 ** Advance the LHS iterator to find the next row visited. */
118071 fts3EvalNextRow(pCsr, pLeft, pRc);
118072 pExpr->iDocid = pLeft->iDocid;
118073 pExpr->bEof = pLeft->bEof;
118074 }else{
118075 /* Neither the RHS or LHS are deferred. */
118076 fts3EvalNextRow(pCsr, pLeft, pRc);
118077 fts3EvalNextRow(pCsr, pRight, pRc);
118078 while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
118079 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
118080 if( iDiff==0 ) break;
118081 if( iDiff<0 ){
118082 fts3EvalNextRow(pCsr, pLeft, pRc);
118083 }else{
118084 fts3EvalNextRow(pCsr, pRight, pRc);
118085 }
118086 }
118087 pExpr->iDocid = pLeft->iDocid;
118088 pExpr->bEof = (pLeft->bEof || pRight->bEof);
118089 }
118090 break;
118091 }
118092
118093 case FTSQUERY_OR: {
118094 Fts3Expr *pLeft = pExpr->pLeft;
118095 Fts3Expr *pRight = pExpr->pRight;
118096 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
118097
118098 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
118099 assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
118100
118101 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
118102 fts3EvalNextRow(pCsr, pLeft, pRc);
118103 }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
118104 fts3EvalNextRow(pCsr, pRight, pRc);
118105 }else{
118106 fts3EvalNextRow(pCsr, pLeft, pRc);
118107 fts3EvalNextRow(pCsr, pRight, pRc);
118108 }
118109
118110 pExpr->bEof = (pLeft->bEof && pRight->bEof);
118111 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
118112 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
118113 pExpr->iDocid = pLeft->iDocid;
118114 }else{
118115 pExpr->iDocid = pRight->iDocid;
118116 }
118117
118118 break;
118119 }
118120
118121 case FTSQUERY_NOT: {
118122 Fts3Expr *pLeft = pExpr->pLeft;
118123 Fts3Expr *pRight = pExpr->pRight;
118124
118125 if( pRight->bStart==0 ){
118126 fts3EvalNextRow(pCsr, pRight, pRc);
118127 assert( *pRc!=SQLITE_OK || pRight->bStart );
118128 }
118129
118130 fts3EvalNextRow(pCsr, pLeft, pRc);
118131 if( pLeft->bEof==0 ){
118132 while( !*pRc
118133 && !pRight->bEof
118134 && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
118135 ){
118136 fts3EvalNextRow(pCsr, pRight, pRc);
118137 }
118138 }
118139 pExpr->iDocid = pLeft->iDocid;
118140 pExpr->bEof = pLeft->bEof;
118141 break;
118142 }
118143
118144 default: {
118145 Fts3Phrase *pPhrase = pExpr->pPhrase;
118146 fts3EvalInvalidatePoslist(pPhrase);
118147 *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
118148 pExpr->iDocid = pPhrase->doclist.iDocid;
118149 break;
118150 }
118151 }
118152 }
118153 }
118154
118155 /*
118156 ** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
118157 ** cluster, then this function returns 1 immediately.
118158 **
118159 ** Otherwise, it checks if the current row really does match the NEAR
118160 ** expression, using the data currently stored in the position lists
118161 ** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
118162 **
118163 ** If the current row is a match, the position list associated with each
118164 ** phrase in the NEAR expression is edited in place to contain only those
118165 ** phrase instances sufficiently close to their peers to satisfy all NEAR
118166 ** constraints. In this case it returns 1. If the NEAR expression does not
118167 ** match the current row, 0 is returned. The position lists may or may not
118168 ** be edited if 0 is returned.
118169 */
118170 static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
118171 int res = 1;
118172
118173 /* The following block runs if pExpr is the root of a NEAR query.
118174 ** For example, the query:
@@ -115717,11 +118186,11 @@
118186 ** | |
118187 ** "w" "x"
118188 **
118189 ** The right-hand child of a NEAR node is always a phrase. The
118190 ** left-hand child may be either a phrase or a NEAR node. There are
118191 ** no exceptions to this - it's the way the parser in fts3_expr.c works.
118192 */
118193 if( *pRc==SQLITE_OK
118194 && pExpr->eType==FTSQUERY_NEAR
118195 && pExpr->bEof==0
118196 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
@@ -115744,21 +118213,21 @@
118213 int nToken = p->pPhrase->nToken;
118214
118215 for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
118216 Fts3Phrase *pPhrase = p->pRight->pPhrase;
118217 int nNear = p->nNear;
118218 res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
118219 }
118220
118221 aPoslist = pExpr->pRight->pPhrase->doclist.pList;
118222 nToken = pExpr->pRight->pPhrase->nToken;
118223 for(p=pExpr->pLeft; p && res; p=p->pLeft){
118224 int nNear = p->pParent->nNear;
118225 Fts3Phrase *pPhrase = (
118226 p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
118227 );
118228 res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
118229 }
118230 }
118231
118232 sqlite3_free(aTmp);
118233 }
@@ -115765,132 +118234,33 @@
118234
118235 return res;
118236 }
118237
118238 /*
118239 ** This function is a helper function for fts3EvalTestDeferredAndNear().
118240 ** Assuming no error occurs or has occurred, It returns non-zero if the
118241 ** expression passed as the second argument matches the row that pCsr
118242 ** currently points to, or zero if it does not.
118243 **
118244 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
118245 ** If an error occurs during execution of this function, *pRc is set to
118246 ** the appropriate SQLite error code. In this case the returned value is
118247 ** undefined.
118248 */
118249 static int fts3EvalTestExpr(
118250 Fts3Cursor *pCsr, /* FTS cursor handle */
118251 Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
118252 int *pRc /* IN/OUT: Error code */
118253 ){
118254 int bHit = 1; /* Return value */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118255 if( *pRc==SQLITE_OK ){
118256 switch( pExpr->eType ){
118257 case FTSQUERY_NEAR:
118258 case FTSQUERY_AND:
118259 bHit = (
118260 fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
118261 && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
118262 && fts3EvalNearTest(pExpr, pRc)
118263 );
118264
118265 /* If the NEAR expression does not match any rows, zero the doclist for
118266 ** all phrases involved in the NEAR. This is because the snippet(),
@@ -115912,31 +118282,31 @@
118282 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
118283 ){
118284 Fts3Expr *p;
118285 for(p=pExpr; p->pPhrase==0; p=p->pLeft){
118286 if( p->pRight->iDocid==pCsr->iPrevId ){
118287 fts3EvalInvalidatePoslist(p->pRight->pPhrase);
118288 }
118289 }
118290 if( p->iDocid==pCsr->iPrevId ){
118291 fts3EvalInvalidatePoslist(p->pPhrase);
118292 }
118293 }
118294
118295 break;
118296
118297 case FTSQUERY_OR: {
118298 int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
118299 int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
118300 bHit = bHit1 || bHit2;
118301 break;
118302 }
118303
118304 case FTSQUERY_NOT:
118305 bHit = (
118306 fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
118307 && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
118308 );
118309 break;
118310
118311 default: {
118312 if( pCsr->pDeferred
@@ -115943,11 +118313,11 @@
118313 && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
118314 ){
118315 Fts3Phrase *pPhrase = pExpr->pPhrase;
118316 assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
118317 if( pExpr->bDeferred ){
118318 fts3EvalInvalidatePoslist(pPhrase);
118319 }
118320 *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
118321 bHit = (pPhrase->doclist.pList!=0);
118322 pExpr->iDocid = pCsr->iPrevId;
118323 }else{
@@ -115959,31 +118329,53 @@
118329 }
118330 return bHit;
118331 }
118332
118333 /*
118334 ** This function is called as the second part of each xNext operation when
118335 ** iterating through the results of a full-text query. At this point the
118336 ** cursor points to a row that matches the query expression, with the
118337 ** following caveats:
118338 **
118339 ** * Up until this point, "NEAR" operators in the expression have been
118340 ** treated as "AND".
118341 **
118342 ** * Deferred tokens have not yet been considered.
118343 **
118344 ** If *pRc is not SQLITE_OK when this function is called, it immediately
118345 ** returns 0. Otherwise, it tests whether or not after considering NEAR
118346 ** operators and deferred tokens the current row is still a match for the
118347 ** expression. It returns 1 if both of the following are true:
118348 **
118349 ** 1. *pRc is SQLITE_OK when this function returns, and
118350 **
118351 ** 2. After scanning the current FTS table row for the deferred tokens,
118352 ** it is determined that the row does *not* match the query.
118353 **
118354 ** Or, if no error occurs and it seems the current row does match the FTS
118355 ** query, return 0.
118356 */
118357 static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
118358 int rc = *pRc;
118359 int bMiss = 0;
118360 if( rc==SQLITE_OK ){
118361
118362 /* If there are one or more deferred tokens, load the current row into
118363 ** memory and scan it to determine the position list for each deferred
118364 ** token. Then, see if this row is really a match, considering deferred
118365 ** tokens and NEAR operators (neither of which were taken into account
118366 ** earlier, by fts3EvalNextRow()).
118367 */
118368 if( pCsr->pDeferred ){
118369 rc = fts3CursorSeek(0, pCsr);
118370 if( rc==SQLITE_OK ){
118371 rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
118372 }
118373 }
118374 bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
118375
118376 /* Free the position-lists accumulated for each deferred token above. */
118377 sqlite3Fts3FreeDeferredDoclists(pCsr);
118378 *pRc = rc;
118379 }
118380 return (rc==SQLITE_OK && bMiss);
118381 }
@@ -115990,11 +118382,11 @@
118382
118383 /*
118384 ** Advance to the next document that matches the FTS expression in
118385 ** Fts3Cursor.pExpr.
118386 */
118387 static int fts3EvalNext(Fts3Cursor *pCsr){
118388 int rc = SQLITE_OK; /* Return Code */
118389 Fts3Expr *pExpr = pCsr->pExpr;
118390 assert( pCsr->isEof==0 );
118391 if( pExpr==0 ){
118392 pCsr->isEof = 1;
@@ -116002,23 +118394,23 @@
118394 do {
118395 if( pCsr->isRequireSeek==0 ){
118396 sqlite3_reset(pCsr->pStmt);
118397 }
118398 assert( sqlite3_data_count(pCsr->pStmt)==0 );
118399 fts3EvalNextRow(pCsr, pExpr, &rc);
118400 pCsr->isEof = pExpr->bEof;
118401 pCsr->isRequireSeek = 1;
118402 pCsr->isMatchinfoNeeded = 1;
118403 pCsr->iPrevId = pExpr->iDocid;
118404 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
118405 }
118406 return rc;
118407 }
118408
118409 /*
118410 ** Restart interation for expression pExpr so that the next call to
118411 ** fts3EvalNext() visits the first row. Do not allow incremental
118412 ** loading or merging of phrase doclists for this iteration.
118413 **
118414 ** If *pRc is other than SQLITE_OK when this function is called, it is
118415 ** a no-op. If an error occurs within this function, *pRc is set to an
118416 ** SQLite error code before returning.
@@ -116030,19 +118422,20 @@
118422 ){
118423 if( pExpr && *pRc==SQLITE_OK ){
118424 Fts3Phrase *pPhrase = pExpr->pPhrase;
118425
118426 if( pPhrase ){
118427 fts3EvalInvalidatePoslist(pPhrase);
118428 if( pPhrase->bIncr ){
118429 assert( pPhrase->nToken==1 );
118430 assert( pPhrase->aToken[0].pSegcsr );
118431 sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
118432 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
 
 
118433 }
118434
118435 pPhrase->doclist.pNextDocid = 0;
118436 pPhrase->doclist.iDocid = 0;
118437 }
118438
118439 pExpr->iDocid = 0;
118440 pExpr->bEof = 0;
118441 pExpr->bStart = 0;
@@ -116145,18 +118538,18 @@
118538 /* Ensure the %_content statement is reset. */
118539 if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
118540 assert( sqlite3_data_count(pCsr->pStmt)==0 );
118541
118542 /* Advance to the next document */
118543 fts3EvalNextRow(pCsr, pRoot, &rc);
118544 pCsr->isEof = pRoot->bEof;
118545 pCsr->isRequireSeek = 1;
118546 pCsr->isMatchinfoNeeded = 1;
118547 pCsr->iPrevId = pRoot->iDocid;
118548 }while( pCsr->isEof==0
118549 && pRoot->eType==FTSQUERY_NEAR
118550 && fts3EvalTestDeferredAndNear(pCsr, &rc)
118551 );
118552
118553 if( rc==SQLITE_OK && pCsr->isEof==0 ){
118554 fts3EvalUpdateCounts(pRoot);
118555 }
@@ -116174,14 +118567,14 @@
118567 **
118568 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
118569 */
118570 fts3EvalRestart(pCsr, pRoot, &rc);
118571 do {
118572 fts3EvalNextRow(pCsr, pRoot, &rc);
118573 assert( pRoot->bEof==0 );
118574 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
118575 fts3EvalTestDeferredAndNear(pCsr, &rc);
118576 }
118577 }
118578 return rc;
118579 }
118580
@@ -116225,12 +118618,12 @@
118618 int iCol;
118619
118620 if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
118621 assert( pCsr->nDoc>0 );
118622 for(iCol=0; iCol<pTab->nColumn; iCol++){
118623 aiOut[iCol*3 + 1] = (u32)pCsr->nDoc;
118624 aiOut[iCol*3 + 2] = (u32)pCsr->nDoc;
118625 }
118626 }else{
118627 rc = fts3EvalGatherStats(pCsr, pExpr);
118628 if( rc==SQLITE_OK ){
118629 assert( pExpr->aMI );
@@ -116308,18 +118701,32 @@
118701 */
118702 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
118703 if( pPhrase ){
118704 int i;
118705 sqlite3_free(pPhrase->doclist.aAll);
118706 fts3EvalInvalidatePoslist(pPhrase);
118707 memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
118708 for(i=0; i<pPhrase->nToken; i++){
118709 fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
118710 pPhrase->aToken[i].pSegcsr = 0;
118711 }
118712 }
118713 }
118714
118715 #if !SQLITE_CORE
118716 /*
118717 ** Initialize API pointer table, if required.
118718 */
118719 SQLITE_API int sqlite3_extension_init(
118720 sqlite3 *db,
118721 char **pzErrMsg,
118722 const sqlite3_api_routines *pApi
118723 ){
118724 SQLITE_EXTENSION_INIT2(pApi)
118725 return sqlite3Fts3Init(db);
118726 }
118727 #endif
118728
118729 #endif
118730
118731 /************** End of fts3.c ************************************************/
118732 /************** Begin file fts3_aux.c ****************************************/
@@ -116334,13 +118741,14 @@
118741 ** May you share freely, never taking more than you give.
118742 **
118743 ******************************************************************************
118744 **
118745 */
 
118746 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
118747
118748 /* #include <string.h> */
118749 /* #include <assert.h> */
118750
118751 typedef struct Fts3auxTable Fts3auxTable;
118752 typedef struct Fts3auxCursor Fts3auxCursor;
118753
118754 struct Fts3auxTable {
@@ -116875,10 +119283,12 @@
119283 /*
119284 ** Default span for NEAR operators.
119285 */
119286 #define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
119287
119288 /* #include <string.h> */
119289 /* #include <assert.h> */
119290
119291 /*
119292 ** isNot:
119293 ** This variable is used by function getNextNode(). When getNextNode() is
119294 ** called, it sets ParseContext.isNot to true if the 'next node' is a
@@ -117576,10 +119986,11 @@
119986 ** Everything after this point is just test code.
119987 */
119988
119989 #ifdef SQLITE_TEST
119990
119991 /* #include <stdio.h> */
119992
119993 /*
119994 ** Function to query the hash-table of tokenizers (see README.tokenizers).
119995 */
119996 static int queryTestTokenizer(
@@ -117786,10 +120197,13 @@
120197 ** * The FTS3 module is being built into the core of
120198 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
120199 */
120200 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
120201
120202 /* #include <assert.h> */
120203 /* #include <stdlib.h> */
120204 /* #include <string.h> */
120205
120206
120207 /*
120208 ** Malloc and Free functions
120209 */
@@ -118166,11 +120580,14 @@
120580 ** * The FTS3 module is being built into the core of
120581 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
120582 */
120583 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
120584
120585 /* #include <assert.h> */
120586 /* #include <stdlib.h> */
120587 /* #include <stdio.h> */
120588 /* #include <string.h> */
120589
120590
120591 /*
120592 ** Class derived from sqlite3_tokenizer
120593 */
@@ -118810,14 +121227,12 @@
121227 ** * The FTS3 module is being built into the core of
121228 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
121229 */
121230 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
121231
121232 /* #include <assert.h> */
121233 /* #include <string.h> */
 
 
121234
121235 /*
121236 ** Implementation of the SQL scalar function for accessing the underlying
121237 ** hash table. This function may be called as follows:
121238 **
@@ -118937,11 +121352,11 @@
121352 sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
121353 char **pzErr /* OUT: Set to malloced error message */
121354 ){
121355 int rc;
121356 char *z = (char *)zArg;
121357 int n = 0;
121358 char *zCopy;
121359 char *zEnd; /* Pointer to nul-term of zCopy */
121360 sqlite3_tokenizer_module *m;
121361
121362 zCopy = sqlite3_mprintf("%s", zArg);
@@ -118989,10 +121404,12 @@
121404 }
121405
121406
121407 #ifdef SQLITE_TEST
121408
121409 /* #include <tcl.h> */
121410 /* #include <string.h> */
121411
121412 /*
121413 ** Implementation of a special SQL scalar function for testing tokenizers
121414 ** designed to be used in concert with the Tcl testing framework. This
121415 ** function must be called with two arguments:
@@ -119300,11 +121717,14 @@
121717 ** * The FTS3 module is being built into the core of
121718 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
121719 */
121720 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
121721
121722 /* #include <assert.h> */
121723 /* #include <stdlib.h> */
121724 /* #include <stdio.h> */
121725 /* #include <string.h> */
121726
121727
121728 typedef struct simple_tokenizer {
121729 sqlite3_tokenizer base;
121730 char delim[128]; /* flag ASCII delimiters */
@@ -119526,10 +121946,13 @@
121946 ** code in fts3.c.
121947 */
121948
121949 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
121950
121951 /* #include <string.h> */
121952 /* #include <assert.h> */
121953 /* #include <stdlib.h> */
121954
121955 /*
121956 ** When full-text index nodes are loaded from disk, the buffer that they
121957 ** are loaded into has the following number of bytes of padding at the end
121958 ** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
@@ -120750,10 +123173,11 @@
123173 pReader->pOffsetList = 0;
123174 }else{
123175 pReader->pOffsetList = p;
123176 }
123177 }else{
123178 char *pEnd = &pReader->aDoclist[pReader->nDoclist];
123179
123180 /* Pointer p currently points at the first byte of an offset list. The
123181 ** following block advances it to point one byte past the end of
123182 ** the same offset list. */
123183 while( 1 ){
@@ -120778,17 +123202,19 @@
123202 */
123203 if( ppOffsetList ){
123204 *ppOffsetList = pReader->pOffsetList;
123205 *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
123206 }
123207
123208 while( p<pEnd && *p==0 ) p++;
123209
123210 /* If there are no more entries in the doclist, set pOffsetList to
123211 ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
123212 ** Fts3SegReader.pOffsetList to point to the next offset list before
123213 ** returning.
123214 */
123215 if( p>=pEnd ){
123216 pReader->pOffsetList = 0;
123217 }else{
123218 rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
123219 if( rc==SQLITE_OK ){
123220 sqlite3_int64 iDelta;
@@ -120823,11 +123249,11 @@
123249 for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
123250 Fts3SegReader *pReader = pMsr->apSegment[ii];
123251 if( !fts3SegReaderIsPending(pReader)
123252 && !fts3SegReaderIsRootOnly(pReader)
123253 ){
123254 sqlite3_int64 jj;
123255 for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
123256 int nBlob;
123257 rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
123258 if( rc!=SQLITE_OK ) break;
123259 if( (nBlob+35)>pgsz ){
@@ -121768,55 +124194,31 @@
124194
124195 *ppList = pList;
124196 *pnList = nList;
124197 }
124198
124199 /*
124200 ** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
124201 ** existing data). Grow the buffer if required.
124202 **
124203 ** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered
124204 ** trying to resize the buffer, return SQLITE_NOMEM.
124205 */
124206 static int fts3MsrBufferData(
124207 Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
124208 char *pList,
124209 int nList
124210 ){
124211 if( nList>pMsr->nBuffer ){
124212 char *pNew;
124213 pMsr->nBuffer = nList*2;
124214 pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
124215 if( !pNew ) return SQLITE_NOMEM;
124216 pMsr->aBuffer = pNew;
124217 }
124218
124219 memcpy(pMsr->aBuffer, pList, nList);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124220 return SQLITE_OK;
124221 }
124222
124223 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
124224 Fts3Table *p, /* Virtual table handle */
@@ -121866,52 +124268,138 @@
124268 if( pMsr->iColFilter>=0 ){
124269 fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
124270 }
124271
124272 if( nList>0 ){
124273 if( fts3SegReaderIsPending(apSegment[0]) ){
124274 rc = fts3MsrBufferData(pMsr, pList, nList+1);
124275 if( rc!=SQLITE_OK ) return rc;
124276 *paPoslist = pMsr->aBuffer;
124277 assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
124278 }else{
124279 *paPoslist = pList;
124280 }
124281 *piDocid = iDocid;
 
124282 *pnPoslist = nList;
124283 break;
124284 }
124285 }
 
124286 }
124287
124288 return SQLITE_OK;
124289 }
124290
124291 static int fts3SegReaderStart(
124292 Fts3Table *p, /* Virtual table handle */
124293 Fts3MultiSegReader *pCsr, /* Cursor object */
124294 const char *zTerm, /* Term searched for (or NULL) */
124295 int nTerm /* Length of zTerm in bytes */
124296 ){
124297 int i;
124298 int nSeg = pCsr->nSegment;
124299
124300 /* If the Fts3SegFilter defines a specific term (or term prefix) to search
124301 ** for, then advance each segment iterator until it points to a term of
124302 ** equal or greater value than the specified term. This prevents many
124303 ** unnecessary merge/sort operations for the case where single segment
124304 ** b-tree leaf nodes contain more than one term.
124305 */
124306 for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
124307 Fts3SegReader *pSeg = pCsr->apSegment[i];
124308 do {
124309 int rc = fts3SegReaderNext(p, pSeg, 0);
124310 if( rc!=SQLITE_OK ) return rc;
124311 }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
124312 }
124313 fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
124314
124315 return SQLITE_OK;
124316 }
124317
124318 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
124319 Fts3Table *p, /* Virtual table handle */
124320 Fts3MultiSegReader *pCsr, /* Cursor object */
124321 Fts3SegFilter *pFilter /* Restrictions on range of iteration */
124322 ){
 
 
 
124323 pCsr->pFilter = pFilter;
124324 return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm);
124325 }
124326
124327 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
124328 Fts3Table *p, /* Virtual table handle */
124329 Fts3MultiSegReader *pCsr, /* Cursor object */
124330 int iCol, /* Column to match on. */
124331 const char *zTerm, /* Term to iterate through a doclist for */
124332 int nTerm /* Number of bytes in zTerm */
124333 ){
124334 int i;
124335 int rc;
124336 int nSegment = pCsr->nSegment;
124337 int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
124338 p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
124339 );
124340
124341 assert( pCsr->pFilter==0 );
124342 assert( zTerm && nTerm>0 );
124343
124344 /* Advance each segment iterator until it points to the term zTerm/nTerm. */
124345 rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm);
124346 if( rc!=SQLITE_OK ) return rc;
124347
124348 /* Determine how many of the segments actually point to zTerm/nTerm. */
124349 for(i=0; i<nSegment; i++){
124350 Fts3SegReader *pSeg = pCsr->apSegment[i];
124351 if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
124352 break;
124353 }
 
124354 }
124355 pCsr->nAdvance = i;
124356
124357 /* Advance each of the segments to point to the first docid. */
124358 for(i=0; i<pCsr->nAdvance; i++){
124359 rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
124360 if( rc!=SQLITE_OK ) return rc;
124361 }
124362 fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
124363
124364 assert( iCol<0 || iCol<p->nColumn );
124365 pCsr->iColFilter = iCol;
124366
124367 return SQLITE_OK;
124368 }
124369
124370 /*
124371 ** This function is called on a MultiSegReader that has been started using
124372 ** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also
124373 ** have been made. Calling this function puts the MultiSegReader in such
124374 ** a state that if the next two calls are:
124375 **
124376 ** sqlite3Fts3SegReaderStart()
124377 ** sqlite3Fts3SegReaderStep()
124378 **
124379 ** then the entire doclist for the term is available in
124380 ** MultiSegReader.aDoclist/nDoclist.
124381 */
124382 SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
124383 int i; /* Used to iterate through segment-readers */
124384
124385 assert( pCsr->zTerm==0 );
124386 assert( pCsr->nTerm==0 );
124387 assert( pCsr->aDoclist==0 );
124388 assert( pCsr->nDoclist==0 );
124389
124390 pCsr->nAdvance = 0;
124391 pCsr->bRestart = 1;
124392 for(i=0; i<pCsr->nSegment; i++){
124393 pCsr->apSegment[i]->pOffsetList = 0;
124394 pCsr->apSegment[i]->nOffsetList = 0;
124395 pCsr->apSegment[i]->iDocid = 0;
124396 }
124397
124398 return SQLITE_OK;
124399 }
124400
124401
124402 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
124403 Fts3Table *p, /* Virtual table handle */
124404 Fts3MultiSegReader *pCsr /* Cursor object */
124405 ){
@@ -121981,13 +124469,18 @@
124469 assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
124470 if( nMerge==1
124471 && !isIgnoreEmpty
124472 && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
124473 ){
 
124474 pCsr->nDoclist = apSegment[0]->nDoclist;
124475 if( fts3SegReaderIsPending(apSegment[0]) ){
124476 rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
124477 pCsr->aDoclist = pCsr->aBuffer;
124478 }else{
124479 pCsr->aDoclist = apSegment[0]->aDoclist;
124480 }
124481 if( rc==SQLITE_OK ) rc = SQLITE_ROW;
124482 }else{
124483 int nDoclist = 0; /* Size of doclist */
124484 sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */
124485
124486 /* The current term of the first nMerge entries in the array
@@ -122717,10 +125210,12 @@
125210 ******************************************************************************
125211 */
125212
125213 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
125214
125215 /* #include <string.h> */
125216 /* #include <assert.h> */
125217
125218 /*
125219 ** Characters that may appear in the second argument to matchinfo().
125220 */
125221 #define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */
@@ -123725,11 +126220,11 @@
126220 if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
126221 break;
126222
126223 case FTS3_MATCHINFO_NDOC:
126224 if( bGlobal ){
126225 sqlite3_int64 nDoc = 0;
126226 rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
126227 pInfo->aMatchinfo[0] = (u32)nDoc;
126228 }
126229 break;
126230
@@ -124304,10 +126799,12 @@
126799 #ifndef SQLITE_CORE
126800 SQLITE_EXTENSION_INIT1
126801 #else
126802 #endif
126803
126804 /* #include <string.h> */
126805 /* #include <assert.h> */
126806
126807 #ifndef SQLITE_AMALGAMATION
126808 #include "sqlite3rtree.h"
126809 typedef sqlite3_int64 i64;
126810 typedef unsigned char u8;
@@ -125620,11 +128117,11 @@
128117 */
128118 static float cellArea(Rtree *pRtree, RtreeCell *p){
128119 float area = 1.0;
128120 int ii;
128121 for(ii=0; ii<(pRtree->nDim*2); ii+=2){
128122 area = (float)(area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])));
128123 }
128124 return area;
128125 }
128126
128127 /*
@@ -125633,11 +128130,11 @@
128130 */
128131 static float cellMargin(Rtree *pRtree, RtreeCell *p){
128132 float margin = 0.0;
128133 int ii;
128134 for(ii=0; ii<(pRtree->nDim*2); ii+=2){
128135 margin += (float)(DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
128136 }
128137 return margin;
128138 }
128139
128140 /*
@@ -125718,11 +128215,11 @@
128215
128216 if( x2<x1 ){
128217 o = 0.0;
128218 break;
128219 }else{
128220 o = o * (float)(x2-x1);
128221 }
128222 }
128223 overlap += o;
128224 }
128225 }
@@ -125737,16 +128234,16 @@
128234 RtreeCell *pInsert,
128235 RtreeCell *aCell,
128236 int nCell,
128237 int iExclude
128238 ){
128239 double before;
128240 double after;
128241 before = cellOverlap(pRtree, p, aCell, nCell, iExclude);
128242 cellUnion(pRtree, p, pInsert);
128243 after = cellOverlap(pRtree, p, aCell, nCell, iExclude);
128244 return (float)(after-before);
128245 }
128246 #endif
128247
128248
128249 /*
@@ -125764,15 +128261,15 @@
128261 RtreeNode *pNode;
128262 rc = nodeAcquire(pRtree, 1, 0, &pNode);
128263
128264 for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
128265 int iCell;
128266 sqlite3_int64 iBest = 0;
128267
128268 float fMinGrowth = 0.0;
128269 float fMinArea = 0.0;
128270 float fMinOverlap = 0.0;
128271
128272 int nCell = NCELL(pNode);
128273 RtreeCell cell;
128274 RtreeNode *pChild;
128275
@@ -126198,13 +128695,13 @@
128695 ){
128696 int **aaSorted;
128697 int *aSpare;
128698 int ii;
128699
128700 int iBestDim = 0;
128701 int iBestSplit = 0;
128702 float fBestMargin = 0.0;
128703
128704 int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
128705
128706 aaSorted = (int **)sqlite3_malloc(nByte);
128707 if( !aaSorted ){
@@ -126222,13 +128719,13 @@
128719 SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);
128720 }
128721
128722 for(ii=0; ii<pRtree->nDim; ii++){
128723 float margin = 0.0;
128724 float fBestOverlap = 0.0;
128725 float fBestArea = 0.0;
128726 int iBestLeft = 0;
128727 int nLeft;
128728
128729 for(
128730 nLeft=RTREE_MINCELLS(pRtree);
128731 nLeft<=(nCell-RTREE_MINCELLS(pRtree));
@@ -126539,11 +129036,11 @@
129036 static int deleteCell(Rtree *, RtreeNode *, int, int);
129037
129038 static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
129039 int rc;
129040 int rc2;
129041 RtreeNode *pParent = 0;
129042 int iCell;
129043
129044 assert( pNode->nRef==1 );
129045
129046 /* Remove the entry in the parent cell. */
@@ -126687,23 +129184,23 @@
129184 }else{
129185 nodeGetCell(pRtree, pNode, ii, &aCell[ii]);
129186 }
129187 aOrder[ii] = ii;
129188 for(iDim=0; iDim<pRtree->nDim; iDim++){
129189 aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2]);
129190 aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2+1]);
129191 }
129192 }
129193 for(iDim=0; iDim<pRtree->nDim; iDim++){
129194 aCenterCoord[iDim] = (float)(aCenterCoord[iDim]/((float)nCell*2.0));
129195 }
129196
129197 for(ii=0; ii<nCell; ii++){
129198 aDistance[ii] = 0.0;
129199 for(iDim=0; iDim<pRtree->nDim; iDim++){
129200 float coord = (float)(DCOORD(aCell[ii].aCoord[iDim*2+1]) -
129201 DCOORD(aCell[ii].aCoord[iDim*2]));
129202 aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
129203 }
129204 }
129205
129206 SortByDistance(aOrder, nCell, aDistance, aSpare);
@@ -126798,14 +129295,14 @@
129295 nodeGetCell(pRtree, pNode, ii, &cell);
129296
129297 /* Find a node to store this cell in. pNode->iNode currently contains
129298 ** the height of the sub-tree headed by the cell.
129299 */
129300 rc = ChooseLeaf(pRtree, &cell, (int)pNode->iNode, &pInsert);
129301 if( rc==SQLITE_OK ){
129302 int rc2;
129303 rc = rtreeInsertCell(pRtree, pInsert, &cell, (int)pNode->iNode);
129304 rc2 = nodeRelease(pRtree, pInsert);
129305 if( rc==SQLITE_OK ){
129306 rc = rc2;
129307 }
129308 }
@@ -127190,11 +129687,11 @@
129687 int isCreate /* True for xCreate, false for xConnect */
129688 ){
129689 int rc;
129690 char *zSql;
129691 if( isCreate ){
129692 int iPageSize = 0;
129693 zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
129694 rc = getIntFromStmt(db, zSql, &iPageSize);
129695 if( rc==SQLITE_OK ){
129696 pRtree->iNodeSize = iPageSize-64;
129697 if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
@@ -127518,10 +130015,11 @@
130015 #include <unicode/utypes.h>
130016 #include <unicode/uregex.h>
130017 #include <unicode/ustring.h>
130018 #include <unicode/ucol.h>
130019
130020 /* #include <assert.h> */
130021
130022 #ifndef SQLITE_CORE
130023 SQLITE_EXTENSION_INIT1
130024 #else
130025 #endif
@@ -127993,19 +130491,20 @@
130491 ** May you find forgiveness for yourself and forgive others.
130492 ** May you share freely, never taking more than you give.
130493 **
130494 *************************************************************************
130495 ** This file implements a tokenizer for fts3 based on the ICU library.
 
 
130496 */
 
130497 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
130498 #ifdef SQLITE_ENABLE_ICU
130499
130500 /* #include <assert.h> */
130501 /* #include <string.h> */
130502
130503 #include <unicode/ubrk.h>
130504 /* #include <unicode/ucol.h> */
130505 /* #include <unicode/ustring.h> */
130506 #include <unicode/utf16.h>
130507
130508 typedef struct IcuTokenizer IcuTokenizer;
130509 typedef struct IcuCursor IcuCursor;
130510
130511
+50 -23
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105105
**
106106
** See also: [sqlite3_libversion()],
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110
-#define SQLITE_VERSION "3.7.7"
111
-#define SQLITE_VERSION_NUMBER 3007007
112
-#define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
110
+#define SQLITE_VERSION "3.7.8"
111
+#define SQLITE_VERSION_NUMBER 3007008
112
+#define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -308,11 +308,11 @@
308308
** semicolon-separate SQL statements passed into its 2nd argument,
309309
** in the context of the [database connection] passed in as its 1st
310310
** argument. ^If the callback function of the 3rd argument to
311311
** sqlite3_exec() is not NULL, then it is invoked for each result row
312312
** coming out of the evaluated SQL statements. ^The 4th argument to
313
-** to sqlite3_exec() is relayed through to the 1st argument of each
313
+** sqlite3_exec() is relayed through to the 1st argument of each
314314
** callback invocation. ^If the callback pointer to sqlite3_exec()
315315
** is NULL, then no callback is ever invoked and result rows are
316316
** ignored.
317317
**
318318
** ^If an error occurs while evaluating the SQL statements passed into
@@ -739,20 +739,52 @@
739739
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
740740
** VFSes do not need this signal and should silently ignore this opcode.
741741
** Applications should not call [sqlite3_file_control()] with this
742742
** opcode as doing so may disrupt the operation of the specialized VFSes
743743
** that do require it.
744
+**
745
+** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
746
+** retry counts and intervals for certain disk I/O operations for the
747
+** windows [VFS] in order to work to provide robustness against
748
+** anti-virus programs. By default, the windows VFS will retry file read,
749
+** file write, and file delete opertions up to 10 times, with a delay
750
+** of 25 milliseconds before the first retry and with the delay increasing
751
+** by an additional 25 milliseconds with each subsequent retry. This
752
+** opcode allows those to values (10 retries and 25 milliseconds of delay)
753
+** to be adjusted. The values are changed for all database connections
754
+** within the same process. The argument is a pointer to an array of two
755
+** integers where the first integer i the new retry count and the second
756
+** integer is the delay. If either integer is negative, then the setting
757
+** is not changed but instead the prior value of that setting is written
758
+** into the array entry, allowing the current retry settings to be
759
+** interrogated. The zDbName parameter is ignored.
760
+**
761
+** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
762
+** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
763
+** write ahead log and shared memory files used for transaction control
764
+** are automatically deleted when the latest connection to the database
765
+** closes. Setting persistent WAL mode causes those files to persist after
766
+** close. Persisting the files is useful when other processes that do not
767
+** have write permission on the directory containing the database file want
768
+** to read the database file, as the WAL and shared memory files must exist
769
+** in order for the database to be readable. The fourth parameter to
770
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
771
+** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
772
+** WAL mode. If the integer is -1, then it is overwritten with the current
773
+** WAL persistence setting.
774
+**
744775
*/
745776
#define SQLITE_FCNTL_LOCKSTATE 1
746777
#define SQLITE_GET_LOCKPROXYFILE 2
747778
#define SQLITE_SET_LOCKPROXYFILE 3
748779
#define SQLITE_LAST_ERRNO 4
749780
#define SQLITE_FCNTL_SIZE_HINT 5
750781
#define SQLITE_FCNTL_CHUNK_SIZE 6
751782
#define SQLITE_FCNTL_FILE_POINTER 7
752783
#define SQLITE_FCNTL_SYNC_OMITTED 8
753
-
784
+#define SQLITE_FCNTL_WIN32_AV_RETRY 9
785
+#define SQLITE_FCNTL_PERSIST_WAL 10
754786
755787
/*
756788
** CAPI3REF: Mutex Handle
757789
**
758790
** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -900,11 +932,11 @@
900932
** The xSleep() method causes the calling thread to sleep for at
901933
** least the number of microseconds given. ^The xCurrentTime()
902934
** method returns a Julian Day Number for the current date and time as
903935
** a floating point value.
904936
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
905
-** Day Number multipled by 86400000 (the number of milliseconds in
937
+** Day Number multiplied by 86400000 (the number of milliseconds in
906938
** a 24-hour day).
907939
** ^SQLite will use the xCurrentTimeInt64() method to get the current
908940
** date and time if that method is available (if iVersion is 2 or
909941
** greater and the function pointer is not NULL) and will fall back
910942
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
@@ -1176,20 +1208,14 @@
11761208
** also used during testing of SQLite in order to specify an alternative
11771209
** memory allocator that simulates memory out-of-memory conditions in
11781210
** order to verify that SQLite recovers gracefully from such
11791211
** conditions.
11801212
**
1181
-** The xMalloc and xFree methods must work like the
1182
-** malloc() and free() functions from the standard C library.
1183
-** The xRealloc method must work like realloc() from the standard C library
1184
-** with the exception that if the second argument to xRealloc is zero,
1185
-** xRealloc must be a no-op - it must not perform any allocation or
1186
-** deallocation. ^SQLite guarantees that the second argument to
1213
+** The xMalloc, xRealloc, and xFree methods must work like the
1214
+** malloc(), realloc() and free() functions from the standard C library.
1215
+** ^SQLite guarantees that the second argument to
11871216
** xRealloc is always a value returned by a prior call to xRoundup.
1188
-** And so in cases where xRoundup always returns a positive number,
1189
-** xRealloc can perform exactly as the standard library realloc() and
1190
-** still be in compliance with this specification.
11911217
**
11921218
** xSize should return the allocated size of a memory allocation
11931219
** previously obtained from xMalloc or xRealloc. The allocated size
11941220
** is always at least as big as the requested size but may be larger.
11951221
**
@@ -1338,11 +1364,11 @@
13381364
** scratch memory beyond what is provided by this configuration option, then
13391365
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
13401366
**
13411367
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
13421368
** <dd> ^This option specifies a static memory buffer that SQLite can use for
1343
-** the database page cache with the default page cache implemenation.
1369
+** the database page cache with the default page cache implementation.
13441370
** This configuration should not be used if an application-define page
13451371
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
13461372
** There are three arguments to this option: A pointer to 8-byte aligned
13471373
** memory, the size of each page buffer (sz), and the number of pages (N).
13481374
** The sz argument should be the size of the largest database page
@@ -2436,16 +2462,16 @@
24362462
** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
24372463
**
24382464
** ^If [URI filename] interpretation is enabled, and the filename argument
24392465
** begins with "file:", then the filename is interpreted as a URI. ^URI
24402466
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2441
-** is set in the fourth argument to sqlite3_open_v2(), or if it has
2467
+** set in the fourth argument to sqlite3_open_v2(), or if it has
24422468
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
24432469
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
24442470
** As of SQLite version 3.7.7, URI filename interpretation is turned off
24452471
** by default, but future releases of SQLite might enable URI filename
2446
-** intepretation by default. See "[URI filenames]" for additional
2472
+** interpretation by default. See "[URI filenames]" for additional
24472473
** information.
24482474
**
24492475
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
24502476
** authority, then it must be either an empty string or the string
24512477
** "localhost". ^If the authority is not an empty string or "localhost", an
@@ -3260,11 +3286,11 @@
32603286
** [extended result codes] might be returned as well.
32613287
**
32623288
** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
32633289
** database locks it needs to do its job. ^If the statement is a [COMMIT]
32643290
** or occurs outside of an explicit transaction, then you can retry the
3265
-** statement. If the statement is not a [COMMIT] and occurs within a
3291
+** statement. If the statement is not a [COMMIT] and occurs within an
32663292
** explicit transaction then you should rollback the transaction before
32673293
** continuing.
32683294
**
32693295
** ^[SQLITE_DONE] means that the statement has finished executing
32703296
** successfully. sqlite3_step() should not be called again on this virtual
@@ -3539,11 +3565,11 @@
35393565
35403566
/*
35413567
** CAPI3REF: Destroy A Prepared Statement Object
35423568
**
35433569
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
3544
-** ^If the most recent evaluation of the statement encountered no errors or
3570
+** ^If the most recent evaluation of the statement encountered no errors
35453571
** or if the statement is never been evaluated, then sqlite3_finalize() returns
35463572
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
35473573
** sqlite3_finalize(S) returns the appropriate [error code] or
35483574
** [extended error code].
35493575
**
@@ -5453,11 +5479,11 @@
54535479
** versions of these routines, it should at least provide stubs that always
54545480
** return true so that one does not get spurious assertion failures.
54555481
**
54565482
** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
54575483
** the routine should return 1. This seems counter-intuitive since
5458
-** clearly the mutex cannot be held if it does not exist. But the
5484
+** clearly the mutex cannot be held if it does not exist. But
54595485
** the reason the mutex does not exist is because the build is not
54605486
** using mutexes. And we do not want the assert() containing the
54615487
** call to sqlite3_mutex_held() to fail, so a non-zero return is
54625488
** the appropriate thing to do. ^The sqlite3_mutex_notheld()
54635489
** interface should also return 1 when given a NULL pointer.
@@ -5576,11 +5602,12 @@
55765602
#define SQLITE_TESTCTRL_RESERVE 14
55775603
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
55785604
#define SQLITE_TESTCTRL_ISKEYWORD 16
55795605
#define SQLITE_TESTCTRL_PGHDRSZ 17
55805606
#define SQLITE_TESTCTRL_SCRATCHMALLOC 18
5581
-#define SQLITE_TESTCTRL_LAST 18
5607
+#define SQLITE_TESTCTRL_LOCALTIME_FAULT 19
5608
+#define SQLITE_TESTCTRL_LAST 19
55825609
55835610
/*
55845611
** CAPI3REF: SQLite Runtime Status
55855612
**
55865613
** ^This interface is used to retrieve runtime status information
@@ -5962,11 +5989,11 @@
59625989
** [[the xFetch() page cache methods]]
59635990
** The xFetch() method locates a page in the cache and returns a pointer to
59645991
** the page, or a NULL pointer.
59655992
** A "page", in this context, means a buffer of szPage bytes aligned at an
59665993
** 8-byte boundary. The page to be fetched is determined by the key. ^The
5967
-** mimimum key value is 1. After it has been retrieved using xFetch, the page
5994
+** minimum key value is 1. After it has been retrieved using xFetch, the page
59685995
** is considered to be "pinned".
59695996
**
59705997
** If the requested page is already in the page cache, then the page cache
59715998
** implementation must return a pointer to the page buffer with its content
59725999
** intact. If the requested page is not already in the cache, then the
59736000
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.7"
111 #define SQLITE_VERSION_NUMBER 3007007
112 #define SQLITE_SOURCE_ID "2011-06-15 13:11:06 f9750870ee04935f338e4d808900fee5a8b2b389"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -308,11 +308,11 @@
308 ** semicolon-separate SQL statements passed into its 2nd argument,
309 ** in the context of the [database connection] passed in as its 1st
310 ** argument. ^If the callback function of the 3rd argument to
311 ** sqlite3_exec() is not NULL, then it is invoked for each result row
312 ** coming out of the evaluated SQL statements. ^The 4th argument to
313 ** to sqlite3_exec() is relayed through to the 1st argument of each
314 ** callback invocation. ^If the callback pointer to sqlite3_exec()
315 ** is NULL, then no callback is ever invoked and result rows are
316 ** ignored.
317 **
318 ** ^If an error occurs while evaluating the SQL statements passed into
@@ -739,20 +739,52 @@
739 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
740 ** VFSes do not need this signal and should silently ignore this opcode.
741 ** Applications should not call [sqlite3_file_control()] with this
742 ** opcode as doing so may disrupt the operation of the specialized VFSes
743 ** that do require it.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
744 */
745 #define SQLITE_FCNTL_LOCKSTATE 1
746 #define SQLITE_GET_LOCKPROXYFILE 2
747 #define SQLITE_SET_LOCKPROXYFILE 3
748 #define SQLITE_LAST_ERRNO 4
749 #define SQLITE_FCNTL_SIZE_HINT 5
750 #define SQLITE_FCNTL_CHUNK_SIZE 6
751 #define SQLITE_FCNTL_FILE_POINTER 7
752 #define SQLITE_FCNTL_SYNC_OMITTED 8
753
 
754
755 /*
756 ** CAPI3REF: Mutex Handle
757 **
758 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -900,11 +932,11 @@
900 ** The xSleep() method causes the calling thread to sleep for at
901 ** least the number of microseconds given. ^The xCurrentTime()
902 ** method returns a Julian Day Number for the current date and time as
903 ** a floating point value.
904 ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
905 ** Day Number multipled by 86400000 (the number of milliseconds in
906 ** a 24-hour day).
907 ** ^SQLite will use the xCurrentTimeInt64() method to get the current
908 ** date and time if that method is available (if iVersion is 2 or
909 ** greater and the function pointer is not NULL) and will fall back
910 ** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
@@ -1176,20 +1208,14 @@
1176 ** also used during testing of SQLite in order to specify an alternative
1177 ** memory allocator that simulates memory out-of-memory conditions in
1178 ** order to verify that SQLite recovers gracefully from such
1179 ** conditions.
1180 **
1181 ** The xMalloc and xFree methods must work like the
1182 ** malloc() and free() functions from the standard C library.
1183 ** The xRealloc method must work like realloc() from the standard C library
1184 ** with the exception that if the second argument to xRealloc is zero,
1185 ** xRealloc must be a no-op - it must not perform any allocation or
1186 ** deallocation. ^SQLite guarantees that the second argument to
1187 ** xRealloc is always a value returned by a prior call to xRoundup.
1188 ** And so in cases where xRoundup always returns a positive number,
1189 ** xRealloc can perform exactly as the standard library realloc() and
1190 ** still be in compliance with this specification.
1191 **
1192 ** xSize should return the allocated size of a memory allocation
1193 ** previously obtained from xMalloc or xRealloc. The allocated size
1194 ** is always at least as big as the requested size but may be larger.
1195 **
@@ -1338,11 +1364,11 @@
1338 ** scratch memory beyond what is provided by this configuration option, then
1339 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1340 **
1341 ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
1342 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1343 ** the database page cache with the default page cache implemenation.
1344 ** This configuration should not be used if an application-define page
1345 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1346 ** There are three arguments to this option: A pointer to 8-byte aligned
1347 ** memory, the size of each page buffer (sz), and the number of pages (N).
1348 ** The sz argument should be the size of the largest database page
@@ -2436,16 +2462,16 @@
2436 ** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
2437 **
2438 ** ^If [URI filename] interpretation is enabled, and the filename argument
2439 ** begins with "file:", then the filename is interpreted as a URI. ^URI
2440 ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2441 ** is set in the fourth argument to sqlite3_open_v2(), or if it has
2442 ** been enabled globally using the [SQLITE_CONFIG_URI] option with the
2443 ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
2444 ** As of SQLite version 3.7.7, URI filename interpretation is turned off
2445 ** by default, but future releases of SQLite might enable URI filename
2446 ** intepretation by default. See "[URI filenames]" for additional
2447 ** information.
2448 **
2449 ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
2450 ** authority, then it must be either an empty string or the string
2451 ** "localhost". ^If the authority is not an empty string or "localhost", an
@@ -3260,11 +3286,11 @@
3260 ** [extended result codes] might be returned as well.
3261 **
3262 ** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
3263 ** database locks it needs to do its job. ^If the statement is a [COMMIT]
3264 ** or occurs outside of an explicit transaction, then you can retry the
3265 ** statement. If the statement is not a [COMMIT] and occurs within a
3266 ** explicit transaction then you should rollback the transaction before
3267 ** continuing.
3268 **
3269 ** ^[SQLITE_DONE] means that the statement has finished executing
3270 ** successfully. sqlite3_step() should not be called again on this virtual
@@ -3539,11 +3565,11 @@
3539
3540 /*
3541 ** CAPI3REF: Destroy A Prepared Statement Object
3542 **
3543 ** ^The sqlite3_finalize() function is called to delete a [prepared statement].
3544 ** ^If the most recent evaluation of the statement encountered no errors or
3545 ** or if the statement is never been evaluated, then sqlite3_finalize() returns
3546 ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
3547 ** sqlite3_finalize(S) returns the appropriate [error code] or
3548 ** [extended error code].
3549 **
@@ -5453,11 +5479,11 @@
5453 ** versions of these routines, it should at least provide stubs that always
5454 ** return true so that one does not get spurious assertion failures.
5455 **
5456 ** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
5457 ** the routine should return 1. This seems counter-intuitive since
5458 ** clearly the mutex cannot be held if it does not exist. But the
5459 ** the reason the mutex does not exist is because the build is not
5460 ** using mutexes. And we do not want the assert() containing the
5461 ** call to sqlite3_mutex_held() to fail, so a non-zero return is
5462 ** the appropriate thing to do. ^The sqlite3_mutex_notheld()
5463 ** interface should also return 1 when given a NULL pointer.
@@ -5576,11 +5602,12 @@
5576 #define SQLITE_TESTCTRL_RESERVE 14
5577 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15
5578 #define SQLITE_TESTCTRL_ISKEYWORD 16
5579 #define SQLITE_TESTCTRL_PGHDRSZ 17
5580 #define SQLITE_TESTCTRL_SCRATCHMALLOC 18
5581 #define SQLITE_TESTCTRL_LAST 18
 
5582
5583 /*
5584 ** CAPI3REF: SQLite Runtime Status
5585 **
5586 ** ^This interface is used to retrieve runtime status information
@@ -5962,11 +5989,11 @@
5962 ** [[the xFetch() page cache methods]]
5963 ** The xFetch() method locates a page in the cache and returns a pointer to
5964 ** the page, or a NULL pointer.
5965 ** A "page", in this context, means a buffer of szPage bytes aligned at an
5966 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
5967 ** mimimum key value is 1. After it has been retrieved using xFetch, the page
5968 ** is considered to be "pinned".
5969 **
5970 ** If the requested page is already in the page cache, then the page cache
5971 ** implementation must return a pointer to the page buffer with its content
5972 ** intact. If the requested page is not already in the cache, then the
5973
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.8"
111 #define SQLITE_VERSION_NUMBER 3007008
112 #define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -308,11 +308,11 @@
308 ** semicolon-separate SQL statements passed into its 2nd argument,
309 ** in the context of the [database connection] passed in as its 1st
310 ** argument. ^If the callback function of the 3rd argument to
311 ** sqlite3_exec() is not NULL, then it is invoked for each result row
312 ** coming out of the evaluated SQL statements. ^The 4th argument to
313 ** sqlite3_exec() is relayed through to the 1st argument of each
314 ** callback invocation. ^If the callback pointer to sqlite3_exec()
315 ** is NULL, then no callback is ever invoked and result rows are
316 ** ignored.
317 **
318 ** ^If an error occurs while evaluating the SQL statements passed into
@@ -739,20 +739,52 @@
739 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
740 ** VFSes do not need this signal and should silently ignore this opcode.
741 ** Applications should not call [sqlite3_file_control()] with this
742 ** opcode as doing so may disrupt the operation of the specialized VFSes
743 ** that do require it.
744 **
745 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
746 ** retry counts and intervals for certain disk I/O operations for the
747 ** windows [VFS] in order to work to provide robustness against
748 ** anti-virus programs. By default, the windows VFS will retry file read,
749 ** file write, and file delete opertions up to 10 times, with a delay
750 ** of 25 milliseconds before the first retry and with the delay increasing
751 ** by an additional 25 milliseconds with each subsequent retry. This
752 ** opcode allows those to values (10 retries and 25 milliseconds of delay)
753 ** to be adjusted. The values are changed for all database connections
754 ** within the same process. The argument is a pointer to an array of two
755 ** integers where the first integer i the new retry count and the second
756 ** integer is the delay. If either integer is negative, then the setting
757 ** is not changed but instead the prior value of that setting is written
758 ** into the array entry, allowing the current retry settings to be
759 ** interrogated. The zDbName parameter is ignored.
760 **
761 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
762 ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
763 ** write ahead log and shared memory files used for transaction control
764 ** are automatically deleted when the latest connection to the database
765 ** closes. Setting persistent WAL mode causes those files to persist after
766 ** close. Persisting the files is useful when other processes that do not
767 ** have write permission on the directory containing the database file want
768 ** to read the database file, as the WAL and shared memory files must exist
769 ** in order for the database to be readable. The fourth parameter to
770 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
771 ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
772 ** WAL mode. If the integer is -1, then it is overwritten with the current
773 ** WAL persistence setting.
774 **
775 */
776 #define SQLITE_FCNTL_LOCKSTATE 1
777 #define SQLITE_GET_LOCKPROXYFILE 2
778 #define SQLITE_SET_LOCKPROXYFILE 3
779 #define SQLITE_LAST_ERRNO 4
780 #define SQLITE_FCNTL_SIZE_HINT 5
781 #define SQLITE_FCNTL_CHUNK_SIZE 6
782 #define SQLITE_FCNTL_FILE_POINTER 7
783 #define SQLITE_FCNTL_SYNC_OMITTED 8
784 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
785 #define SQLITE_FCNTL_PERSIST_WAL 10
786
787 /*
788 ** CAPI3REF: Mutex Handle
789 **
790 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -900,11 +932,11 @@
932 ** The xSleep() method causes the calling thread to sleep for at
933 ** least the number of microseconds given. ^The xCurrentTime()
934 ** method returns a Julian Day Number for the current date and time as
935 ** a floating point value.
936 ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
937 ** Day Number multiplied by 86400000 (the number of milliseconds in
938 ** a 24-hour day).
939 ** ^SQLite will use the xCurrentTimeInt64() method to get the current
940 ** date and time if that method is available (if iVersion is 2 or
941 ** greater and the function pointer is not NULL) and will fall back
942 ** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
@@ -1176,20 +1208,14 @@
1208 ** also used during testing of SQLite in order to specify an alternative
1209 ** memory allocator that simulates memory out-of-memory conditions in
1210 ** order to verify that SQLite recovers gracefully from such
1211 ** conditions.
1212 **
1213 ** The xMalloc, xRealloc, and xFree methods must work like the
1214 ** malloc(), realloc() and free() functions from the standard C library.
1215 ** ^SQLite guarantees that the second argument to
 
 
 
1216 ** xRealloc is always a value returned by a prior call to xRoundup.
 
 
 
1217 **
1218 ** xSize should return the allocated size of a memory allocation
1219 ** previously obtained from xMalloc or xRealloc. The allocated size
1220 ** is always at least as big as the requested size but may be larger.
1221 **
@@ -1338,11 +1364,11 @@
1364 ** scratch memory beyond what is provided by this configuration option, then
1365 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1366 **
1367 ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
1368 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1369 ** the database page cache with the default page cache implementation.
1370 ** This configuration should not be used if an application-define page
1371 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1372 ** There are three arguments to this option: A pointer to 8-byte aligned
1373 ** memory, the size of each page buffer (sz), and the number of pages (N).
1374 ** The sz argument should be the size of the largest database page
@@ -2436,16 +2462,16 @@
2462 ** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
2463 **
2464 ** ^If [URI filename] interpretation is enabled, and the filename argument
2465 ** begins with "file:", then the filename is interpreted as a URI. ^URI
2466 ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2467 ** set in the fourth argument to sqlite3_open_v2(), or if it has
2468 ** been enabled globally using the [SQLITE_CONFIG_URI] option with the
2469 ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
2470 ** As of SQLite version 3.7.7, URI filename interpretation is turned off
2471 ** by default, but future releases of SQLite might enable URI filename
2472 ** interpretation by default. See "[URI filenames]" for additional
2473 ** information.
2474 **
2475 ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
2476 ** authority, then it must be either an empty string or the string
2477 ** "localhost". ^If the authority is not an empty string or "localhost", an
@@ -3260,11 +3286,11 @@
3286 ** [extended result codes] might be returned as well.
3287 **
3288 ** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
3289 ** database locks it needs to do its job. ^If the statement is a [COMMIT]
3290 ** or occurs outside of an explicit transaction, then you can retry the
3291 ** statement. If the statement is not a [COMMIT] and occurs within an
3292 ** explicit transaction then you should rollback the transaction before
3293 ** continuing.
3294 **
3295 ** ^[SQLITE_DONE] means that the statement has finished executing
3296 ** successfully. sqlite3_step() should not be called again on this virtual
@@ -3539,11 +3565,11 @@
3565
3566 /*
3567 ** CAPI3REF: Destroy A Prepared Statement Object
3568 **
3569 ** ^The sqlite3_finalize() function is called to delete a [prepared statement].
3570 ** ^If the most recent evaluation of the statement encountered no errors
3571 ** or if the statement is never been evaluated, then sqlite3_finalize() returns
3572 ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
3573 ** sqlite3_finalize(S) returns the appropriate [error code] or
3574 ** [extended error code].
3575 **
@@ -5453,11 +5479,11 @@
5479 ** versions of these routines, it should at least provide stubs that always
5480 ** return true so that one does not get spurious assertion failures.
5481 **
5482 ** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
5483 ** the routine should return 1. This seems counter-intuitive since
5484 ** clearly the mutex cannot be held if it does not exist. But
5485 ** the reason the mutex does not exist is because the build is not
5486 ** using mutexes. And we do not want the assert() containing the
5487 ** call to sqlite3_mutex_held() to fail, so a non-zero return is
5488 ** the appropriate thing to do. ^The sqlite3_mutex_notheld()
5489 ** interface should also return 1 when given a NULL pointer.
@@ -5576,11 +5602,12 @@
5602 #define SQLITE_TESTCTRL_RESERVE 14
5603 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15
5604 #define SQLITE_TESTCTRL_ISKEYWORD 16
5605 #define SQLITE_TESTCTRL_PGHDRSZ 17
5606 #define SQLITE_TESTCTRL_SCRATCHMALLOC 18
5607 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 19
5608 #define SQLITE_TESTCTRL_LAST 19
5609
5610 /*
5611 ** CAPI3REF: SQLite Runtime Status
5612 **
5613 ** ^This interface is used to retrieve runtime status information
@@ -5962,11 +5989,11 @@
5989 ** [[the xFetch() page cache methods]]
5990 ** The xFetch() method locates a page in the cache and returns a pointer to
5991 ** the page, or a NULL pointer.
5992 ** A "page", in this context, means a buffer of szPage bytes aligned at an
5993 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
5994 ** minimum key value is 1. After it has been retrieved using xFetch, the page
5995 ** is considered to be "pinned".
5996 **
5997 ** If the requested page is already in the page cache, then the page cache
5998 ** implementation must return a pointer to the page buffer with its content
5999 ** intact. If the requested page is not already in the cache, then the
6000
+4 -2
--- src/stash.c
+++ src/stash.c
@@ -100,10 +100,11 @@
100100
if( rid==0 ){
101101
/* A new file */
102102
blob_read_from_file(&content, zPath);
103103
db_bind_blob(&ins, ":content", &content);
104104
}else if( deleted ){
105
+ blob_zero(&content);
105106
db_bind_null(&ins, ":content");
106107
}else{
107108
/* A modified file */
108109
Blob orig;
109110
Blob disk;
@@ -274,11 +275,11 @@
274275
}
275276
db_finalize(&q);
276277
}
277278
278279
/*
279
-** Drop the indicates stash
280
+** Drop the indicated stash
280281
*/
281282
static void stash_drop(int stashid){
282283
db_multi_exec(
283284
"DELETE FROM stash WHERE stashid=%d;"
284285
"DELETE FROM stashfile WHERE stashid=%d;",
@@ -344,10 +345,11 @@
344345
** Update to the baseline checkout for STASHID then apply the
345346
** changes of STASHID. Keep STASHID so that it can be reused
346347
** This command is undoable.
347348
**
348349
** fossil stash drop ?STASHID? ?--all?
350
+** fossil stash rm ?STASHID? ?--all?
349351
**
350352
** Forget everything about STASHID. Forget the whole stash if the
351353
** --all flag is used. Individual drops are undoable but --all is not.
352354
**
353355
** fossil stash snapshot ?-m COMMENT? ?FILES...?
@@ -427,11 +429,11 @@
427429
}
428430
}
429431
db_finalize(&q);
430432
if( n==0 ) fossil_print("empty stash\n");
431433
}else
432
- if( memcmp(zCmd, "drop", nCmd)==0 ){
434
+ if( memcmp(zCmd, "drop", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){
433435
int allFlag = find_option("all", 0, 0)!=0;
434436
if( g.argc>4 ) usage("stash apply STASHID");
435437
if( allFlag ){
436438
db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;");
437439
}else{
438440
--- src/stash.c
+++ src/stash.c
@@ -100,10 +100,11 @@
100 if( rid==0 ){
101 /* A new file */
102 blob_read_from_file(&content, zPath);
103 db_bind_blob(&ins, ":content", &content);
104 }else if( deleted ){
 
105 db_bind_null(&ins, ":content");
106 }else{
107 /* A modified file */
108 Blob orig;
109 Blob disk;
@@ -274,11 +275,11 @@
274 }
275 db_finalize(&q);
276 }
277
278 /*
279 ** Drop the indicates stash
280 */
281 static void stash_drop(int stashid){
282 db_multi_exec(
283 "DELETE FROM stash WHERE stashid=%d;"
284 "DELETE FROM stashfile WHERE stashid=%d;",
@@ -344,10 +345,11 @@
344 ** Update to the baseline checkout for STASHID then apply the
345 ** changes of STASHID. Keep STASHID so that it can be reused
346 ** This command is undoable.
347 **
348 ** fossil stash drop ?STASHID? ?--all?
 
349 **
350 ** Forget everything about STASHID. Forget the whole stash if the
351 ** --all flag is used. Individual drops are undoable but --all is not.
352 **
353 ** fossil stash snapshot ?-m COMMENT? ?FILES...?
@@ -427,11 +429,11 @@
427 }
428 }
429 db_finalize(&q);
430 if( n==0 ) fossil_print("empty stash\n");
431 }else
432 if( memcmp(zCmd, "drop", nCmd)==0 ){
433 int allFlag = find_option("all", 0, 0)!=0;
434 if( g.argc>4 ) usage("stash apply STASHID");
435 if( allFlag ){
436 db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;");
437 }else{
438
--- src/stash.c
+++ src/stash.c
@@ -100,10 +100,11 @@
100 if( rid==0 ){
101 /* A new file */
102 blob_read_from_file(&content, zPath);
103 db_bind_blob(&ins, ":content", &content);
104 }else if( deleted ){
105 blob_zero(&content);
106 db_bind_null(&ins, ":content");
107 }else{
108 /* A modified file */
109 Blob orig;
110 Blob disk;
@@ -274,11 +275,11 @@
275 }
276 db_finalize(&q);
277 }
278
279 /*
280 ** Drop the indicated stash
281 */
282 static void stash_drop(int stashid){
283 db_multi_exec(
284 "DELETE FROM stash WHERE stashid=%d;"
285 "DELETE FROM stashfile WHERE stashid=%d;",
@@ -344,10 +345,11 @@
345 ** Update to the baseline checkout for STASHID then apply the
346 ** changes of STASHID. Keep STASHID so that it can be reused
347 ** This command is undoable.
348 **
349 ** fossil stash drop ?STASHID? ?--all?
350 ** fossil stash rm ?STASHID? ?--all?
351 **
352 ** Forget everything about STASHID. Forget the whole stash if the
353 ** --all flag is used. Individual drops are undoable but --all is not.
354 **
355 ** fossil stash snapshot ?-m COMMENT? ?FILES...?
@@ -427,11 +429,11 @@
429 }
430 }
431 db_finalize(&q);
432 if( n==0 ) fossil_print("empty stash\n");
433 }else
434 if( memcmp(zCmd, "drop", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){
435 int allFlag = find_option("all", 0, 0)!=0;
436 if( g.argc>4 ) usage("stash apply STASHID");
437 if( allFlag ){
438 db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;");
439 }else{
440
+2 -1
--- src/stat.c
+++ src/stat.c
@@ -104,11 +104,12 @@
104104
@ <tr><th>Server&nbsp;ID:</th><td>
105105
@ %h(db_get("server-code",""))
106106
@ </td></tr>
107107
108108
@ <tr><th>Fossil&nbsp;Version:</th><td>
109
- @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION) (%h(COMPILER_NAME))
109
+ @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
110
+ @ (%h(COMPILER_NAME))
110111
@ </td></tr>
111112
@ <tr><th>SQLite&nbsp;Version:</th><td>
112113
sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
113114
SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
114115
zDb = db_name("repository");
115116
--- src/stat.c
+++ src/stat.c
@@ -104,11 +104,12 @@
104 @ <tr><th>Server&nbsp;ID:</th><td>
105 @ %h(db_get("server-code",""))
106 @ </td></tr>
107
108 @ <tr><th>Fossil&nbsp;Version:</th><td>
109 @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION) (%h(COMPILER_NAME))
 
110 @ </td></tr>
111 @ <tr><th>SQLite&nbsp;Version:</th><td>
112 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
113 SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
114 zDb = db_name("repository");
115
--- src/stat.c
+++ src/stat.c
@@ -104,11 +104,12 @@
104 @ <tr><th>Server&nbsp;ID:</th><td>
105 @ %h(db_get("server-code",""))
106 @ </td></tr>
107
108 @ <tr><th>Fossil&nbsp;Version:</th><td>
109 @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
110 @ (%h(COMPILER_NAME))
111 @ </td></tr>
112 @ <tr><th>SQLite&nbsp;Version:</th><td>
113 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
114 SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
115 zDb = db_name("repository");
116
+2 -1
--- src/style.c
+++ src/style.c
@@ -98,10 +98,11 @@
9898
Th_Store("title", zTitle);
9999
Th_Store("baseurl", g.zBaseURL);
100100
Th_Store("home", g.zTop);
101101
Th_Store("index_page", db_get("index-page","/home"));
102102
Th_Store("current_page", g.zPath);
103
+ Th_Store("release_version", RELEASE_VERSION);
103104
Th_Store("manifest_version", MANIFEST_VERSION);
104105
Th_Store("manifest_date", MANIFEST_DATE);
105106
Th_Store("compiler_name", COMPILER_NAME);
106107
if( g.zLogin ){
107108
Th_Store("login", g.zLogin);
@@ -245,11 +246,11 @@
245246
/*
246247
** The default page footer
247248
*/
248249
const char zDefaultFooter[] =
249250
@ <div class="footer">
250
-@ Fossil version $manifest_version $manifest_date
251
+@ Fossil version $release_version $manifest_version $manifest_date
251252
@ </div>
252253
@ </body></html>
253254
;
254255
255256
/*
256257
--- src/style.c
+++ src/style.c
@@ -98,10 +98,11 @@
98 Th_Store("title", zTitle);
99 Th_Store("baseurl", g.zBaseURL);
100 Th_Store("home", g.zTop);
101 Th_Store("index_page", db_get("index-page","/home"));
102 Th_Store("current_page", g.zPath);
 
103 Th_Store("manifest_version", MANIFEST_VERSION);
104 Th_Store("manifest_date", MANIFEST_DATE);
105 Th_Store("compiler_name", COMPILER_NAME);
106 if( g.zLogin ){
107 Th_Store("login", g.zLogin);
@@ -245,11 +246,11 @@
245 /*
246 ** The default page footer
247 */
248 const char zDefaultFooter[] =
249 @ <div class="footer">
250 @ Fossil version $manifest_version $manifest_date
251 @ </div>
252 @ </body></html>
253 ;
254
255 /*
256
--- src/style.c
+++ src/style.c
@@ -98,10 +98,11 @@
98 Th_Store("title", zTitle);
99 Th_Store("baseurl", g.zBaseURL);
100 Th_Store("home", g.zTop);
101 Th_Store("index_page", db_get("index-page","/home"));
102 Th_Store("current_page", g.zPath);
103 Th_Store("release_version", RELEASE_VERSION);
104 Th_Store("manifest_version", MANIFEST_VERSION);
105 Th_Store("manifest_date", MANIFEST_DATE);
106 Th_Store("compiler_name", COMPILER_NAME);
107 if( g.zLogin ){
108 Th_Store("login", g.zLogin);
@@ -245,11 +246,11 @@
246 /*
247 ** The default page footer
248 */
249 const char zDefaultFooter[] =
250 @ <div class="footer">
251 @ Fossil version $release_version $manifest_version $manifest_date
252 @ </div>
253 @ </body></html>
254 ;
255
256 /*
257
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -458,11 +458,11 @@
458458
" WHERE tagtype>0 AND tagid=%d"
459459
")"
460460
" ORDER BY event.mtime DESC",
461461
timeline_query_for_tty(), zType, tagid
462462
);
463
- print_timeline(&q, 2000);
463
+ print_timeline(&q, 2000, 0);
464464
db_finalize(&q);
465465
}
466466
}
467467
}else
468468
469469
--- src/tag.c
+++ src/tag.c
@@ -458,11 +458,11 @@
458 " WHERE tagtype>0 AND tagid=%d"
459 ")"
460 " ORDER BY event.mtime DESC",
461 timeline_query_for_tty(), zType, tagid
462 );
463 print_timeline(&q, 2000);
464 db_finalize(&q);
465 }
466 }
467 }else
468
469
--- src/tag.c
+++ src/tag.c
@@ -458,11 +458,11 @@
458 " WHERE tagtype>0 AND tagid=%d"
459 ")"
460 " ORDER BY event.mtime DESC",
461 timeline_query_for_tty(), zType, tagid
462 );
463 print_timeline(&q, 2000, 0);
464 db_finalize(&q);
465 }
466 }
467 }else
468
469
+280 -29
--- src/tar.c
+++ src/tar.c
@@ -27,31 +27,252 @@
2727
*/
2828
static struct tarball_t {
2929
unsigned char *aHdr; /* Space for building headers */
3030
char *zSpaces; /* Spaces for padding */
3131
char *zPrevDir; /* Name of directory for previous entry */
32
+ int nPrevDirAlloc; /* size of zPrevDir */
33
+ Blob pax; /* PAX data */
3234
} tball;
35
+
36
+
37
+/*
38
+** field lengths of 'ustar' name and prefix fields.
39
+*/
40
+#define USTAR_NAME_LEN 100
41
+#define USTAR_PREFIX_LEN 155
42
+
3343
3444
/*
3545
** Begin the process of generating a tarball.
3646
**
3747
** Initialize the GZIP compressor and the table of directory names.
3848
*/
3949
static void tar_begin(void){
4050
assert( tball.aHdr==0 );
41
- tball.aHdr = fossil_malloc(512+512+256);
42
- memset(tball.aHdr, 0, 512+512+256);
51
+ tball.aHdr = fossil_malloc(512+512);
52
+ memset(tball.aHdr, 0, 512+512);
4353
tball.zSpaces = (char*)&tball.aHdr[512];
44
- tball.zPrevDir = (char*)&tball.zSpaces[512];
54
+ /* zPrevDir init */
55
+ tball.zPrevDir = NULL;
56
+ tball.nPrevDirAlloc = 0;
57
+ /* scratch buffer init */
58
+ blob_zero(&tball.pax);
59
+
4560
memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */
4661
memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */
47
- memcpy(&tball.aHdr[257], "ustar ", 7); /* Format */
62
+ memcpy(&tball.aHdr[257], "ustar\00000", 8); /* POSIX.1 format */
63
+ memcpy(&tball.aHdr[265], "nobody", 7); /* Owner name */
64
+ memcpy(&tball.aHdr[297], "nobody", 7); /* Group name */
4865
gzip_begin();
4966
db_multi_exec(
5067
"CREATE TEMP TABLE dir(name UNIQUE);"
5168
);
5269
}
70
+
71
+
72
+/*
73
+** verify that lla characters in 'zName' are in the
74
+** ISO646 (=ASCII) character set.
75
+*/
76
+static int is_iso646_name(
77
+ const char *zName, /* file path */
78
+ int nName /* path length */
79
+){
80
+ int i;
81
+ for(i = 0; i < nName; i++){
82
+ unsigned char c = (unsigned char)zName[i];
83
+ if( c>0x7e ) return 0;
84
+ }
85
+ return 1;
86
+}
87
+
88
+
89
+/*
90
+** copy string pSrc into pDst, truncating or padding with 0 if necessary
91
+*/
92
+static void padded_copy(
93
+ char *pDest,
94
+ int nDest,
95
+ const char *pSrc,
96
+ int nSrc
97
+){
98
+ if(nSrc >= nDest){
99
+ memcpy(pDest, pSrc, nDest);
100
+ }else{
101
+ memcpy(pDest, pSrc, nSrc);
102
+ memset(&pDest[nSrc], 0, nDest - nSrc);
103
+ }
104
+}
105
+
106
+
107
+
108
+/******************************************************************************
109
+**
110
+** The 'tar' format has evolved over time. Initially the name was stored
111
+** in a 100 byte null-terminated field 'name'. File path names were
112
+** limited to 99 bytes.
113
+**
114
+** The Posix.1 'ustar' format added a 155 byte field 'prefix', allowing
115
+** for up to 255 characters to be stored. The full file path is formed by
116
+** concatenating the field 'prefix', a slash, and the field 'name'. This
117
+** gives some measure of compatibility with programs that only understand
118
+** the oldest format.
119
+**
120
+** The latest Posix extension is called the 'pax Interchange Format'.
121
+** It removes all the limitations of the previous two formats by allowing
122
+** the storage of arbitrary-length attributes in a separate object that looks
123
+** like a file to programs that do not understand this extension. So the
124
+** contents of the 'name' and 'prefix' fields should contain values that allow
125
+** versions of tar that do not understand this extension to still do
126
+** something useful.
127
+**
128
+******************************************************************************/
129
+
130
+/*
131
+** The position we use to split a file path into the 'name' and 'prefix'
132
+** fields needs to meet the following criteria:
133
+**
134
+** - not at the beginning or end of the string
135
+** - the position must contain a slash
136
+** - no more than 100 characters follow the slash
137
+** - no more than 155 characters precede it
138
+**
139
+** The routine 'find_split_pos' finds a split position. It will meet the
140
+** criteria of listed above if such a position exists. If no such
141
+** position exists it generates one that useful for generating the
142
+** values used for backward compatibility.
143
+*/
144
+static int find_split_pos(
145
+ const char *zName, /* file path */
146
+ int nName /* path length */
147
+){
148
+ int i, split = 0;
149
+ /* only search if the string needs splitting */
150
+ if(nName > USTAR_NAME_LEN){
151
+ for(i = 1; i+1 < nName; i++)
152
+ if(zName[i] == '/'){
153
+ split = i+1;
154
+ /* if the split position is within USTAR_NAME_LEN bytes from
155
+ * the end we can quit */
156
+ if(nName - split <= USTAR_NAME_LEN) break;
157
+ }
158
+ }
159
+ return split;
160
+}
161
+
162
+
163
+/*
164
+** attempt to split the file name path to meet 'ustar' header
165
+** criteria.
166
+*/
167
+static int tar_split_path(
168
+ const char *zName, /* path */
169
+ int nName, /* path length */
170
+ char *pName, /* name field */
171
+ char *pPrefix /* prefix field */
172
+){
173
+ int split = find_split_pos(zName, nName);
174
+ /* check whether both pieces fit */
175
+ if(nName - split > USTAR_NAME_LEN || split > USTAR_PREFIX_LEN+1){
176
+ return 0; /* no */
177
+ }
178
+
179
+ /* extract name */
180
+ padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
181
+
182
+ /* extract prefix */
183
+ padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split - 1 : 0));
184
+
185
+ return 1; /* success */
186
+}
187
+
188
+
189
+/*
190
+** When using an extension header we still need to put something
191
+** reasonable in the name and prefix fields. This is probably as
192
+** good as it gets.
193
+*/
194
+static void approximate_split_path(
195
+ const char *zName, /* path */
196
+ int nName, /* path length */
197
+ char *pName, /* name field */
198
+ char *pPrefix, /* prefix field */
199
+ int bHeader /* is this a 'x' type tar header? */
200
+){
201
+ int split;
202
+
203
+ /* if this is a Pax Interchange header prepend "PaxHeader/"
204
+ ** so we can tell files apart from metadata */
205
+ if( bHeader ){
206
+ blob_reset(&tball.pax);
207
+ blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
208
+ zName = blob_buffer(&tball.pax);
209
+ nName = blob_size(&tball.pax);
210
+ }
211
+
212
+ /* find the split position */
213
+ split = find_split_pos(zName, nName);
214
+
215
+ /* extract a name, truncate if needed */
216
+ padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
217
+
218
+ /* extract a prefix field, truncate when needed */
219
+ padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split-1 : 0));
220
+}
221
+
222
+
223
+/*
224
+** add a Pax Interchange header to the scratch buffer
225
+**
226
+** format: <length> <key>=<value>\n
227
+** the tricky part is that each header contains its own
228
+** size in decimal, counting that length.
229
+*/
230
+static void add_pax_header(
231
+ const char *zField,
232
+ const char *zValue,
233
+ int nValue
234
+){
235
+ /* calculate length without length field */
236
+ int blen = strlen(zField) + nValue + 3;
237
+ /* calculate the length of the length field */
238
+ int next10 = 1;
239
+ int n;
240
+ for(n = blen; n > 0; ){
241
+ blen++; next10 *= 10;
242
+ n /= 10;
243
+ }
244
+ /* adding the length extended the length field? */
245
+ if(blen > next10){
246
+ blen++;
247
+ }
248
+ /* build the string */
249
+ blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
250
+ /* this _must_ be right */
251
+ if(blob_size(&tball.pax) != blen){
252
+ fossil_fatal("internal error: PAX tar header has bad length");
253
+ }
254
+}
255
+
256
+
257
+/*
258
+** set the header type, calculate the checksum and output
259
+** the header
260
+*/
261
+static void cksum_and_write_header(
262
+ char cType
263
+){
264
+ unsigned int cksum = 0;
265
+ int i;
266
+ memset(&tball.aHdr[148], ' ', 8);
267
+ tball.aHdr[156] = cType;
268
+ for(i=0; i<512; i++) cksum += tball.aHdr[i];
269
+ sqlite3_snprintf(8, (char*)&tball.aHdr[148], "%07o", cksum);
270
+ tball.aHdr[155] = 0;
271
+ gzip_step((char*)tball.aHdr, 512);
272
+}
273
+
53274
54275
/*
55276
** Build a header for a file or directory and write that header
56277
** into the growing tarball.
57278
*/
@@ -59,33 +280,52 @@
59280
const char *zName, /* Name of the object */
60281
int nName, /* Number of characters in zName */
61282
int iMode, /* Mode. 0644 or 0755 */
62283
unsigned int mTime, /* File modification time */
63284
int iSize, /* Size of the object in bytes */
64
- int iType /* Type of object. 0==file. 5==directory */
285
+ char cType /* Type of object. '0'==file. '5'==directory */
65286
){
66
- unsigned int cksum = 0;
67
- int i;
68
- if( nName>100 ){
69
- memcpy(&tball.aHdr[345], zName, nName-100);
70
- memcpy(tball.aHdr, &zName[nName-100], 100);
71
- memset(&tball.aHdr[245+nName], 0, 267-nName);
72
- }else{
73
- memcpy(tball.aHdr, zName, nName);
74
- memset(&tball.aHdr[nName], 0, 100-nName);
75
- memset(&tball.aHdr[345], 0, 167);
76
- }
287
+ /* set mode and modification time */
77288
sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode);
78
- sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
79289
sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime);
80
- memset(&tball.aHdr[148], ' ', 8);
81
- tball.aHdr[156] = iType + '0';
82
- for(i=0; i<512; i++) cksum += tball.aHdr[i];
83
- sqlite3_snprintf(7, (char*)&tball.aHdr[148], "%06o", cksum);
84
- tball.aHdr[154] = 0;
85
- gzip_step((char*)tball.aHdr, 512);
290
+
291
+ /* see if we need to output a Pax Interchange Header */
292
+ if( !is_iso646_name(zName, nName)
293
+ || !tar_split_path(zName, nName, (char*)tball.aHdr, (char*)&tball.aHdr[345])
294
+ ){
295
+ int lastPage;
296
+ /* add a file name for interoperability with older programs */
297
+ approximate_split_path(zName, nName, (char*)tball.aHdr,
298
+ (char*)&tball.aHdr[345], 1);
299
+
300
+ /* generate the Pax Interchange path header */
301
+ blob_reset(&tball.pax);
302
+ add_pax_header("path", zName, nName);
303
+
304
+ /* set the header length, and write the header */
305
+ sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
306
+ blob_size(&tball.pax));
307
+ cksum_and_write_header('x');
308
+
309
+ /* write the Pax Interchange data */
310
+ gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
311
+ lastPage = blob_size(&tball.pax) % 512;
312
+ if( lastPage!=0 ){
313
+ gzip_step(tball.zSpaces, 512 - lastPage);
314
+ }
315
+
316
+ /* generate an approximate path for the regular header */
317
+ approximate_split_path(zName, nName, (char*)tball.aHdr,
318
+ (char*)&tball.aHdr[345], 0);
319
+ }
320
+ /* set the size */
321
+ sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
322
+
323
+ /* write the regular header */
324
+ cksum_and_write_header(cType);
86325
}
326
+
87327
88328
/*
89329
** Recursively add an directory entry for the given file if those
90330
** directories have not previously been seen.
91331
*/
@@ -95,18 +335,27 @@
95335
unsigned int mTime /* Modification time */
96336
){
97337
int i;
98338
for(i=nName-1; i>0 && zName[i]!='/'; i--){}
99339
if( i<=0 ) return;
100
- if( tball.zPrevDir[i]==0 && memcmp(tball.zPrevDir, zName, i)==0 ) return;
340
+ if( i < tball.nPrevDirAlloc && tball.zPrevDir[i]==0 &&
341
+ memcmp(tball.zPrevDir, zName, i)==0 ) return;
101342
db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%#q')", i, zName);
102343
if( sqlite3_changes(g.db)==0 ) return;
103344
tar_add_directory_of(zName, i-1, mTime);
104
- tar_add_header(zName, i, 0755, mTime, 0, 5);
345
+ tar_add_header(zName, i, 0755, mTime, 0, '5');
346
+ if( i >= tball.nPrevDirAlloc ){
347
+ int nsize = tball.nPrevDirAlloc * 2;
348
+ if(i+1 > nsize)
349
+ nsize = i+1;
350
+ tball.zPrevDir = fossil_realloc(tball.zPrevDir, nsize);
351
+ tball.nPrevDirAlloc = nsize;
352
+ }
105353
memcpy(tball.zPrevDir, zName, i);
106354
tball.zPrevDir[i] = 0;
107355
}
356
+
108357
109358
/*
110359
** Add a single file to the growing tarball.
111360
*/
112361
static void tar_add_file(
@@ -117,15 +366,13 @@
117366
){
118367
int nName = strlen(zName);
119368
int n = blob_size(pContent);
120369
int lastPage;
121370
122
- if( nName>=250 ){
123
- fossil_fatal("name too long for ustar format: \"%s\"", zName);
124
- }
371
+ /* length check moved to tar_split_path */
125372
tar_add_directory_of(zName, nName, mTime);
126
- tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, 0);
373
+ tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, '0');
127374
if( n ){
128375
gzip_step(blob_buffer(pContent), n);
129376
lastPage = n % 512;
130377
if( lastPage!=0 ){
131378
gzip_step(tball.zSpaces, 512 - lastPage);
@@ -142,10 +389,14 @@
142389
gzip_step(tball.zSpaces, 512);
143390
gzip_step(tball.zSpaces, 512);
144391
gzip_finish(pOut);
145392
fossil_free(tball.aHdr);
146393
tball.aHdr = 0;
394
+ fossil_free(tball.zPrevDir);
395
+ tball.zPrevDir = NULL;
396
+ tball.nPrevDirAlloc = 0;
397
+ blob_reset(&tball.pax);
147398
}
148399
149400
150401
/*
151402
** COMMAND: test-tarball
152403
--- src/tar.c
+++ src/tar.c
@@ -27,31 +27,252 @@
27 */
28 static struct tarball_t {
29 unsigned char *aHdr; /* Space for building headers */
30 char *zSpaces; /* Spaces for padding */
31 char *zPrevDir; /* Name of directory for previous entry */
 
 
32 } tball;
 
 
 
 
 
 
 
 
33
34 /*
35 ** Begin the process of generating a tarball.
36 **
37 ** Initialize the GZIP compressor and the table of directory names.
38 */
39 static void tar_begin(void){
40 assert( tball.aHdr==0 );
41 tball.aHdr = fossil_malloc(512+512+256);
42 memset(tball.aHdr, 0, 512+512+256);
43 tball.zSpaces = (char*)&tball.aHdr[512];
44 tball.zPrevDir = (char*)&tball.zSpaces[512];
 
 
 
 
 
45 memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */
46 memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */
47 memcpy(&tball.aHdr[257], "ustar ", 7); /* Format */
 
 
48 gzip_begin();
49 db_multi_exec(
50 "CREATE TEMP TABLE dir(name UNIQUE);"
51 );
52 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
54 /*
55 ** Build a header for a file or directory and write that header
56 ** into the growing tarball.
57 */
@@ -59,33 +280,52 @@
59 const char *zName, /* Name of the object */
60 int nName, /* Number of characters in zName */
61 int iMode, /* Mode. 0644 or 0755 */
62 unsigned int mTime, /* File modification time */
63 int iSize, /* Size of the object in bytes */
64 int iType /* Type of object. 0==file. 5==directory */
65 ){
66 unsigned int cksum = 0;
67 int i;
68 if( nName>100 ){
69 memcpy(&tball.aHdr[345], zName, nName-100);
70 memcpy(tball.aHdr, &zName[nName-100], 100);
71 memset(&tball.aHdr[245+nName], 0, 267-nName);
72 }else{
73 memcpy(tball.aHdr, zName, nName);
74 memset(&tball.aHdr[nName], 0, 100-nName);
75 memset(&tball.aHdr[345], 0, 167);
76 }
77 sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode);
78 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
79 sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime);
80 memset(&tball.aHdr[148], ' ', 8);
81 tball.aHdr[156] = iType + '0';
82 for(i=0; i<512; i++) cksum += tball.aHdr[i];
83 sqlite3_snprintf(7, (char*)&tball.aHdr[148], "%06o", cksum);
84 tball.aHdr[154] = 0;
85 gzip_step((char*)tball.aHdr, 512);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86 }
 
87
88 /*
89 ** Recursively add an directory entry for the given file if those
90 ** directories have not previously been seen.
91 */
@@ -95,18 +335,27 @@
95 unsigned int mTime /* Modification time */
96 ){
97 int i;
98 for(i=nName-1; i>0 && zName[i]!='/'; i--){}
99 if( i<=0 ) return;
100 if( tball.zPrevDir[i]==0 && memcmp(tball.zPrevDir, zName, i)==0 ) return;
 
101 db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%#q')", i, zName);
102 if( sqlite3_changes(g.db)==0 ) return;
103 tar_add_directory_of(zName, i-1, mTime);
104 tar_add_header(zName, i, 0755, mTime, 0, 5);
 
 
 
 
 
 
 
105 memcpy(tball.zPrevDir, zName, i);
106 tball.zPrevDir[i] = 0;
107 }
 
108
109 /*
110 ** Add a single file to the growing tarball.
111 */
112 static void tar_add_file(
@@ -117,15 +366,13 @@
117 ){
118 int nName = strlen(zName);
119 int n = blob_size(pContent);
120 int lastPage;
121
122 if( nName>=250 ){
123 fossil_fatal("name too long for ustar format: \"%s\"", zName);
124 }
125 tar_add_directory_of(zName, nName, mTime);
126 tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, 0);
127 if( n ){
128 gzip_step(blob_buffer(pContent), n);
129 lastPage = n % 512;
130 if( lastPage!=0 ){
131 gzip_step(tball.zSpaces, 512 - lastPage);
@@ -142,10 +389,14 @@
142 gzip_step(tball.zSpaces, 512);
143 gzip_step(tball.zSpaces, 512);
144 gzip_finish(pOut);
145 fossil_free(tball.aHdr);
146 tball.aHdr = 0;
 
 
 
 
147 }
148
149
150 /*
151 ** COMMAND: test-tarball
152
--- src/tar.c
+++ src/tar.c
@@ -27,31 +27,252 @@
27 */
28 static struct tarball_t {
29 unsigned char *aHdr; /* Space for building headers */
30 char *zSpaces; /* Spaces for padding */
31 char *zPrevDir; /* Name of directory for previous entry */
32 int nPrevDirAlloc; /* size of zPrevDir */
33 Blob pax; /* PAX data */
34 } tball;
35
36
37 /*
38 ** field lengths of 'ustar' name and prefix fields.
39 */
40 #define USTAR_NAME_LEN 100
41 #define USTAR_PREFIX_LEN 155
42
43
44 /*
45 ** Begin the process of generating a tarball.
46 **
47 ** Initialize the GZIP compressor and the table of directory names.
48 */
49 static void tar_begin(void){
50 assert( tball.aHdr==0 );
51 tball.aHdr = fossil_malloc(512+512);
52 memset(tball.aHdr, 0, 512+512);
53 tball.zSpaces = (char*)&tball.aHdr[512];
54 /* zPrevDir init */
55 tball.zPrevDir = NULL;
56 tball.nPrevDirAlloc = 0;
57 /* scratch buffer init */
58 blob_zero(&tball.pax);
59
60 memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */
61 memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */
62 memcpy(&tball.aHdr[257], "ustar\00000", 8); /* POSIX.1 format */
63 memcpy(&tball.aHdr[265], "nobody", 7); /* Owner name */
64 memcpy(&tball.aHdr[297], "nobody", 7); /* Group name */
65 gzip_begin();
66 db_multi_exec(
67 "CREATE TEMP TABLE dir(name UNIQUE);"
68 );
69 }
70
71
72 /*
73 ** verify that lla characters in 'zName' are in the
74 ** ISO646 (=ASCII) character set.
75 */
76 static int is_iso646_name(
77 const char *zName, /* file path */
78 int nName /* path length */
79 ){
80 int i;
81 for(i = 0; i < nName; i++){
82 unsigned char c = (unsigned char)zName[i];
83 if( c>0x7e ) return 0;
84 }
85 return 1;
86 }
87
88
89 /*
90 ** copy string pSrc into pDst, truncating or padding with 0 if necessary
91 */
92 static void padded_copy(
93 char *pDest,
94 int nDest,
95 const char *pSrc,
96 int nSrc
97 ){
98 if(nSrc >= nDest){
99 memcpy(pDest, pSrc, nDest);
100 }else{
101 memcpy(pDest, pSrc, nSrc);
102 memset(&pDest[nSrc], 0, nDest - nSrc);
103 }
104 }
105
106
107
108 /******************************************************************************
109 **
110 ** The 'tar' format has evolved over time. Initially the name was stored
111 ** in a 100 byte null-terminated field 'name'. File path names were
112 ** limited to 99 bytes.
113 **
114 ** The Posix.1 'ustar' format added a 155 byte field 'prefix', allowing
115 ** for up to 255 characters to be stored. The full file path is formed by
116 ** concatenating the field 'prefix', a slash, and the field 'name'. This
117 ** gives some measure of compatibility with programs that only understand
118 ** the oldest format.
119 **
120 ** The latest Posix extension is called the 'pax Interchange Format'.
121 ** It removes all the limitations of the previous two formats by allowing
122 ** the storage of arbitrary-length attributes in a separate object that looks
123 ** like a file to programs that do not understand this extension. So the
124 ** contents of the 'name' and 'prefix' fields should contain values that allow
125 ** versions of tar that do not understand this extension to still do
126 ** something useful.
127 **
128 ******************************************************************************/
129
130 /*
131 ** The position we use to split a file path into the 'name' and 'prefix'
132 ** fields needs to meet the following criteria:
133 **
134 ** - not at the beginning or end of the string
135 ** - the position must contain a slash
136 ** - no more than 100 characters follow the slash
137 ** - no more than 155 characters precede it
138 **
139 ** The routine 'find_split_pos' finds a split position. It will meet the
140 ** criteria of listed above if such a position exists. If no such
141 ** position exists it generates one that useful for generating the
142 ** values used for backward compatibility.
143 */
144 static int find_split_pos(
145 const char *zName, /* file path */
146 int nName /* path length */
147 ){
148 int i, split = 0;
149 /* only search if the string needs splitting */
150 if(nName > USTAR_NAME_LEN){
151 for(i = 1; i+1 < nName; i++)
152 if(zName[i] == '/'){
153 split = i+1;
154 /* if the split position is within USTAR_NAME_LEN bytes from
155 * the end we can quit */
156 if(nName - split <= USTAR_NAME_LEN) break;
157 }
158 }
159 return split;
160 }
161
162
163 /*
164 ** attempt to split the file name path to meet 'ustar' header
165 ** criteria.
166 */
167 static int tar_split_path(
168 const char *zName, /* path */
169 int nName, /* path length */
170 char *pName, /* name field */
171 char *pPrefix /* prefix field */
172 ){
173 int split = find_split_pos(zName, nName);
174 /* check whether both pieces fit */
175 if(nName - split > USTAR_NAME_LEN || split > USTAR_PREFIX_LEN+1){
176 return 0; /* no */
177 }
178
179 /* extract name */
180 padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
181
182 /* extract prefix */
183 padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split - 1 : 0));
184
185 return 1; /* success */
186 }
187
188
189 /*
190 ** When using an extension header we still need to put something
191 ** reasonable in the name and prefix fields. This is probably as
192 ** good as it gets.
193 */
194 static void approximate_split_path(
195 const char *zName, /* path */
196 int nName, /* path length */
197 char *pName, /* name field */
198 char *pPrefix, /* prefix field */
199 int bHeader /* is this a 'x' type tar header? */
200 ){
201 int split;
202
203 /* if this is a Pax Interchange header prepend "PaxHeader/"
204 ** so we can tell files apart from metadata */
205 if( bHeader ){
206 blob_reset(&tball.pax);
207 blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
208 zName = blob_buffer(&tball.pax);
209 nName = blob_size(&tball.pax);
210 }
211
212 /* find the split position */
213 split = find_split_pos(zName, nName);
214
215 /* extract a name, truncate if needed */
216 padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
217
218 /* extract a prefix field, truncate when needed */
219 padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split-1 : 0));
220 }
221
222
223 /*
224 ** add a Pax Interchange header to the scratch buffer
225 **
226 ** format: <length> <key>=<value>\n
227 ** the tricky part is that each header contains its own
228 ** size in decimal, counting that length.
229 */
230 static void add_pax_header(
231 const char *zField,
232 const char *zValue,
233 int nValue
234 ){
235 /* calculate length without length field */
236 int blen = strlen(zField) + nValue + 3;
237 /* calculate the length of the length field */
238 int next10 = 1;
239 int n;
240 for(n = blen; n > 0; ){
241 blen++; next10 *= 10;
242 n /= 10;
243 }
244 /* adding the length extended the length field? */
245 if(blen > next10){
246 blen++;
247 }
248 /* build the string */
249 blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
250 /* this _must_ be right */
251 if(blob_size(&tball.pax) != blen){
252 fossil_fatal("internal error: PAX tar header has bad length");
253 }
254 }
255
256
257 /*
258 ** set the header type, calculate the checksum and output
259 ** the header
260 */
261 static void cksum_and_write_header(
262 char cType
263 ){
264 unsigned int cksum = 0;
265 int i;
266 memset(&tball.aHdr[148], ' ', 8);
267 tball.aHdr[156] = cType;
268 for(i=0; i<512; i++) cksum += tball.aHdr[i];
269 sqlite3_snprintf(8, (char*)&tball.aHdr[148], "%07o", cksum);
270 tball.aHdr[155] = 0;
271 gzip_step((char*)tball.aHdr, 512);
272 }
273
274
275 /*
276 ** Build a header for a file or directory and write that header
277 ** into the growing tarball.
278 */
@@ -59,33 +280,52 @@
280 const char *zName, /* Name of the object */
281 int nName, /* Number of characters in zName */
282 int iMode, /* Mode. 0644 or 0755 */
283 unsigned int mTime, /* File modification time */
284 int iSize, /* Size of the object in bytes */
285 char cType /* Type of object. '0'==file. '5'==directory */
286 ){
287 /* set mode and modification time */
 
 
 
 
 
 
 
 
 
 
288 sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode);
 
289 sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime);
290
291 /* see if we need to output a Pax Interchange Header */
292 if( !is_iso646_name(zName, nName)
293 || !tar_split_path(zName, nName, (char*)tball.aHdr, (char*)&tball.aHdr[345])
294 ){
295 int lastPage;
296 /* add a file name for interoperability with older programs */
297 approximate_split_path(zName, nName, (char*)tball.aHdr,
298 (char*)&tball.aHdr[345], 1);
299
300 /* generate the Pax Interchange path header */
301 blob_reset(&tball.pax);
302 add_pax_header("path", zName, nName);
303
304 /* set the header length, and write the header */
305 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
306 blob_size(&tball.pax));
307 cksum_and_write_header('x');
308
309 /* write the Pax Interchange data */
310 gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
311 lastPage = blob_size(&tball.pax) % 512;
312 if( lastPage!=0 ){
313 gzip_step(tball.zSpaces, 512 - lastPage);
314 }
315
316 /* generate an approximate path for the regular header */
317 approximate_split_path(zName, nName, (char*)tball.aHdr,
318 (char*)&tball.aHdr[345], 0);
319 }
320 /* set the size */
321 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
322
323 /* write the regular header */
324 cksum_and_write_header(cType);
325 }
326
327
328 /*
329 ** Recursively add an directory entry for the given file if those
330 ** directories have not previously been seen.
331 */
@@ -95,18 +335,27 @@
335 unsigned int mTime /* Modification time */
336 ){
337 int i;
338 for(i=nName-1; i>0 && zName[i]!='/'; i--){}
339 if( i<=0 ) return;
340 if( i < tball.nPrevDirAlloc && tball.zPrevDir[i]==0 &&
341 memcmp(tball.zPrevDir, zName, i)==0 ) return;
342 db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%#q')", i, zName);
343 if( sqlite3_changes(g.db)==0 ) return;
344 tar_add_directory_of(zName, i-1, mTime);
345 tar_add_header(zName, i, 0755, mTime, 0, '5');
346 if( i >= tball.nPrevDirAlloc ){
347 int nsize = tball.nPrevDirAlloc * 2;
348 if(i+1 > nsize)
349 nsize = i+1;
350 tball.zPrevDir = fossil_realloc(tball.zPrevDir, nsize);
351 tball.nPrevDirAlloc = nsize;
352 }
353 memcpy(tball.zPrevDir, zName, i);
354 tball.zPrevDir[i] = 0;
355 }
356
357
358 /*
359 ** Add a single file to the growing tarball.
360 */
361 static void tar_add_file(
@@ -117,15 +366,13 @@
366 ){
367 int nName = strlen(zName);
368 int n = blob_size(pContent);
369 int lastPage;
370
371 /* length check moved to tar_split_path */
 
 
372 tar_add_directory_of(zName, nName, mTime);
373 tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, '0');
374 if( n ){
375 gzip_step(blob_buffer(pContent), n);
376 lastPage = n % 512;
377 if( lastPage!=0 ){
378 gzip_step(tball.zSpaces, 512 - lastPage);
@@ -142,10 +389,14 @@
389 gzip_step(tball.zSpaces, 512);
390 gzip_step(tball.zSpaces, 512);
391 gzip_finish(pOut);
392 fossil_free(tball.aHdr);
393 tball.aHdr = 0;
394 fossil_free(tball.zPrevDir);
395 tball.zPrevDir = NULL;
396 tball.nPrevDirAlloc = 0;
397 blob_reset(&tball.pax);
398 }
399
400
401 /*
402 ** COMMAND: test-tarball
403
+136 -20
--- src/timeline.c
+++ src/timeline.c
@@ -107,11 +107,70 @@
107107
#define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */
108108
#define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */
109109
#define TIMELINE_GRAPH 0x0008 /* Compute a graph */
110110
#define TIMELINE_DISJOINT 0x0010 /* Elements are not contiguous */
111111
#define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
112
+#define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */
113
+#define TIMELINE_UCOLOR 0x0080 /* Background color by user */
112114
#endif
115
+
116
+/*
117
+** Hash a string and use the hash to determine a background color.
118
+*/
119
+char *hash_color(const char *z){
120
+ int i; /* Loop counter */
121
+ unsigned int h = 0; /* Hash on the branch name */
122
+ int r, g, b; /* Values for red, green, and blue */
123
+ int h1, h2, h3, h4; /* Elements of the hash value */
124
+ int mx, mn; /* Components of HSV */
125
+ static char zColor[10]; /* The resulting color */
126
+ static int ix[2] = {0,0}; /* Color chooser parameters */
127
+
128
+ if( ix[0]==0 ){
129
+ if( db_get_boolean("white-foreground", 0) ){
130
+ ix[0] = 140;
131
+ ix[1] = 40;
132
+ }else{
133
+ ix[0] = 216;
134
+ ix[1] = 16;
135
+ }
136
+ }
137
+ for(i=0; z[i]; i++ ){
138
+ h = (h<<11) ^ (h<<1) ^ (h>>3) ^ z[i];
139
+ }
140
+ h1 = h % 6; h /= 6;
141
+ h3 = h % 30; h /= 30;
142
+ h4 = h % 40; h /= 40;
143
+ mx = ix[0] - h3;
144
+ mn = mx - h4 - ix[1];
145
+ h2 = (h%(mx - mn)) + mn;
146
+ switch( h1 ){
147
+ case 0: r = mx; g = h2, b = mn; break;
148
+ case 1: r = h2; g = mx, b = mn; break;
149
+ case 2: r = mn; g = mx, b = h2; break;
150
+ case 3: r = mn; g = h2, b = mx; break;
151
+ case 4: r = h2; g = mn, b = mx; break;
152
+ default: r = mx; g = mn, b = h2; break;
153
+ }
154
+ sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b);
155
+ return zColor;
156
+}
157
+
158
+/*
159
+** COMMAND: test-hash-color
160
+**
161
+** Usage: %fossil test-hash-color TAG ...
162
+**
163
+** Print out the color names associated with each tag. Used for
164
+** testing the hash_color() function.
165
+*/
166
+void test_hash_color(void){
167
+ int i;
168
+ for(i=2; i<g.argc; i++){
169
+ fossil_print("%20s: %s\n", g.argv[i], hash_color(g.argv[i]));
170
+ }
171
+}
113172
114173
/*
115174
** Output a timeline in the web format given a query. The query
116175
** should return these columns:
117176
**
@@ -142,10 +201,11 @@
142201
char zPrevDate[20];
143202
GraphContext *pGraph = 0;
144203
int prevWasDivider = 0; /* True if previous output row was <hr> */
145204
int fchngQueryInit = 0; /* True if fchngQuery is initialized */
146205
Stmt fchngQuery; /* Query for file changes on check-ins */
206
+ static Stmt qbranch;
147207
148208
zPrevDate[0] = 0;
149209
mxWikiLen = db_get_int("timeline-max-comment", 0);
150210
if( db_get_boolean("timeline-block-markup", 0) ){
151211
wikiFlags = WIKI_INLINE;
@@ -157,10 +217,14 @@
157217
/* style is not moved to css, because this is
158218
** a technical div for the timeline graph
159219
*/
160220
@ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
161221
}
222
+ db_static_prepare(&qbranch,
223
+ "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
224
+ TAG_BRANCH
225
+ );
162226
163227
@ <table id="timelineTable" class="timelineTable">
164228
blob_zero(&comment);
165229
while( db_step(pQuery)==SQLITE_ROW ){
166230
int rid = db_column_int(pQuery, 0);
@@ -170,10 +234,11 @@
170234
const char *zDate = db_column_text(pQuery, 2);
171235
const char *zType = db_column_text(pQuery, 7);
172236
const char *zUser = db_column_text(pQuery, 4);
173237
const char *zTagList = db_column_text(pQuery, 8);
174238
int tagid = db_column_int(pQuery, 9);
239
+ const char *zBr = 0; /* Branch */
175240
int commentColumn = 3; /* Column containing comment text */
176241
char zTime[8];
177242
if( tagid ){
178243
if( tagid==prevTagid ){
179244
if( tmFlags & TIMELINE_BRIEF ){
@@ -208,37 +273,44 @@
208273
memcpy(zTime, &zDate[11], 5);
209274
zTime[5] = 0;
210275
@ <tr>
211276
@ <td class="timelineTime">%s(zTime)</td>
212277
@ <td class="timelineGraph">
213
- if( pGraph && zType[0]=='c' ){
278
+ if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0;
279
+ if( zType[0]=='c'
280
+ && (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0)
281
+ ){
282
+ db_reset(&qbranch);
283
+ db_bind_int(&qbranch, ":rid", rid);
284
+ if( db_step(&qbranch)==SQLITE_ROW ){
285
+ zBr = db_column_text(&qbranch, 0);
286
+ }else{
287
+ zBr = "trunk";
288
+ }
289
+ if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
290
+ if( zBr==0 || strcmp(zBr,"trunk")==0 ){
291
+ zBgClr = 0;
292
+ }else{
293
+ zBgClr = hash_color(zBr);
294
+ }
295
+ }
296
+ }
297
+ if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
214298
int nParent = 0;
215299
int aParent[32];
216
- const char *zBr;
217300
int gidx;
218301
static Stmt qparent;
219
- static Stmt qbranch;
220302
db_static_prepare(&qparent,
221303
"SELECT pid FROM plink"
222304
" WHERE cid=:rid AND pid NOT IN phantom"
223305
" ORDER BY isprim DESC /*sort*/"
224306
);
225
- db_static_prepare(&qbranch,
226
- "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
227
- TAG_BRANCH
228
- );
229307
db_bind_int(&qparent, ":rid", rid);
230308
while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){
231309
aParent[nParent++] = db_column_int(&qparent, 0);
232310
}
233311
db_reset(&qparent);
234
- db_bind_int(&qbranch, ":rid", rid);
235
- if( db_step(&qbranch)==SQLITE_ROW ){
236
- zBr = db_column_text(&qbranch, 0);
237
- }else{
238
- zBr = "trunk";
239
- }
240312
gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf);
241313
db_reset(&qbranch);
242314
@ <div id="m%d(gidx)"></div>
243315
}
244316
@</td>
@@ -397,11 +469,11 @@
397469
/*
398470
** Generate all of the necessary javascript to generate a timeline
399471
** graph.
400472
*/
401473
void timeline_output_graph_javascript(GraphContext *pGraph, int omitDescenders){
402
- if( pGraph && pGraph->nErr==0 ){
474
+ if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){
403475
GraphRow *pRow;
404476
int i;
405477
char cSep;
406478
@ <script type="text/JavaScript">
407479
@ /* <![CDATA[ */
@@ -768,10 +840,12 @@
768840
** fc Show details of files changed
769841
** f=RID Show family (immediate parents and children) of RID
770842
** from=RID Path from...
771843
** to=RID ... to this
772844
** nomerge ... avoid merge links on the path
845
+** brbg Background color from branch name
846
+** ubg Background color from user
773847
**
774848
** p= and d= can appear individually or together. If either p= or d=
775849
** appear, then u=, y=, a=, and b= are ignored.
776850
**
777851
** If a= and b= appear, only a= is used. If neither appear, the most
@@ -826,10 +900,12 @@
826900
tmFlags = TIMELINE_GRAPH;
827901
}
828902
if( P("ng")!=0 || zSearch!=0 ){
829903
tmFlags &= ~TIMELINE_GRAPH;
830904
}
905
+ if( P("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
906
+ if( P("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
831907
832908
style_header("Timeline");
833909
login_anonymous_available();
834910
timeline_temp_table();
835911
blob_zero(&sql);
@@ -1020,11 +1096,12 @@
10201096
}else if( zType[0]=='e' ){
10211097
zEType = "event";
10221098
}
10231099
}
10241100
if( zUser ){
1025
- blob_appendf(&sql, " AND event.user=%Q", zUser);
1101
+ blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1102
+ zUser, zUser);
10261103
url_add_parameter(&url, "u", zUser);
10271104
zThisUser = zUser;
10281105
}
10291106
if ( zSearch ){
10301107
blob_appendf(&sql,
@@ -1178,14 +1255,16 @@
11781255
** 2. Date/Time
11791256
** 3. Comment string and user
11801257
** 4. Number of non-merge children
11811258
** 5. Number of parents
11821259
*/
1183
-void print_timeline(Stmt *q, int mxLine){
1260
+void print_timeline(Stmt *q, int mxLine, int showfiles){
11841261
int nLine = 0;
11851262
char zPrevDate[20];
11861263
const char *zCurrentUuid=0;
1264
+ int fchngQueryInit = 0; /* True if fchngQuery is initialized */
1265
+ Stmt fchngQuery; /* Query for file changes on check-ins */
11871266
zPrevDate[0] = 0;
11881267
11891268
if( g.localOpen ){
11901269
int rid = db_lget_int("checkout", 0);
11911270
zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1231,11 +1310,42 @@
12311310
n += strlen(zPrefix);
12321311
}
12331312
zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
12341313
nLine += comment_print(zFree, 9, 79);
12351314
sqlite3_free(zFree);
1315
+
1316
+ if(showfiles){
1317
+ if( !fchngQueryInit ){
1318
+ db_prepare(&fchngQuery,
1319
+ "SELECT (pid==0) AS isnew,"
1320
+ " (fid==0) AS isdel,"
1321
+ " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
1322
+ " (SELECT uuid FROM blob WHERE rid=fid),"
1323
+ " (SELECT uuid FROM blob WHERE rid=pid)"
1324
+ " FROM mlink"
1325
+ " WHERE mid=:mid AND pid!=fid"
1326
+ " ORDER BY 3 /*sort*/"
1327
+ );
1328
+ fchngQueryInit = 1;
1329
+ }
1330
+ db_bind_int(&fchngQuery, ":mid", rid);
1331
+ while( db_step(&fchngQuery)==SQLITE_ROW ){
1332
+ const char *zFilename = db_column_text(&fchngQuery, 2);
1333
+ int isNew = db_column_int(&fchngQuery, 0);
1334
+ int isDel = db_column_int(&fchngQuery, 1);
1335
+ if( isNew ){
1336
+ fossil_print(" ADDED %s\n",zFilename);
1337
+ }else if( isDel ){
1338
+ fossil_print(" DELETED %s\n",zFilename);
1339
+ }else{
1340
+ fossil_print(" EDITED %s\n", zFilename);
1341
+ }
1342
+ }
1343
+ db_reset(&fchngQuery);
1344
+ }
12361345
}
1346
+ if( fchngQueryInit ) db_finalize(&fchngQuery);
12371347
}
12381348
12391349
/*
12401350
** Return a pointer to a static string that forms the basis for
12411351
** a timeline query for display on a TTY.
@@ -1276,11 +1386,11 @@
12761386
}
12771387
12781388
/*
12791389
** COMMAND: timeline
12801390
**
1281
-** Usage: %fossil timeline ?WHEN? ?BASELINE|DATETIME? ?-n N? ?-t TYPE?
1391
+** Usage: %fossil timeline ?WHEN? ?BASELINE|DATETIME? ?-n N? ?-t TYPE? ?-showfiles?
12821392
**
12831393
** Print a summary of activity going backwards in date and time
12841394
** specified or from the current date and time if no arguments
12851395
** are given. Show as many as N (default 20) check-ins. The
12861396
** WHEN argument can be any unique abbreviation of one of these
@@ -1300,10 +1410,14 @@
13001410
** page. For example:
13011411
**
13021412
** w = wiki commits only
13031413
** ci = file commits only
13041414
** t = tickets only
1415
+**
1416
+** The optional showfiles argument if specified prints the list of
1417
+** files changed in a checkin after the checkin comment
1418
+**
13051419
*/
13061420
void timeline_cmd(void){
13071421
Stmt q;
13081422
int n, k;
13091423
const char *zCount;
@@ -1312,10 +1426,12 @@
13121426
char *zDate;
13131427
Blob sql;
13141428
int objid = 0;
13151429
Blob uuid;
13161430
int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */
1431
+ int showfilesFlag = 0 ;
1432
+ showfilesFlag = find_option("showfiles","f", 0)!=0;
13171433
db_find_and_open_repository(0, 0);
13181434
zCount = find_option("count","n",1);
13191435
zType = find_option("type","t",1);
13201436
if( zCount ){
13211437
n = atoi(zCount);
@@ -1338,13 +1454,13 @@
13381454
mode = 4;
13391455
}else if(!zType && !zCount){
13401456
usage("?WHEN? ?BASELINE|DATETIME? ?-n|--count N? ?-t TYPE?");
13411457
}
13421458
if( '-' != *g.argv[3] ){
1343
- zOrigin = g.argv[3];
1459
+ zOrigin = g.argv[3];
13441460
}else{
1345
- zOrigin = "now";
1461
+ zOrigin = "now";
13461462
}
13471463
}else if( g.argc==3 ){
13481464
zOrigin = g.argv[2];
13491465
}else{
13501466
zOrigin = "now";
@@ -1398,11 +1514,11 @@
13981514
}
13991515
14001516
blob_appendf(&sql, " ORDER BY event.mtime DESC");
14011517
db_prepare(&q, blob_str(&sql));
14021518
blob_reset(&sql);
1403
- print_timeline(&q, n);
1519
+ print_timeline(&q, n, showfilesFlag);
14041520
db_finalize(&q);
14051521
}
14061522
14071523
/*
14081524
** This is a version of the "localtime()" function from the standard
14091525
--- src/timeline.c
+++ src/timeline.c
@@ -107,11 +107,70 @@
107 #define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */
108 #define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */
109 #define TIMELINE_GRAPH 0x0008 /* Compute a graph */
110 #define TIMELINE_DISJOINT 0x0010 /* Elements are not contiguous */
111 #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
 
 
112 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
114 /*
115 ** Output a timeline in the web format given a query. The query
116 ** should return these columns:
117 **
@@ -142,10 +201,11 @@
142 char zPrevDate[20];
143 GraphContext *pGraph = 0;
144 int prevWasDivider = 0; /* True if previous output row was <hr> */
145 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
146 Stmt fchngQuery; /* Query for file changes on check-ins */
 
147
148 zPrevDate[0] = 0;
149 mxWikiLen = db_get_int("timeline-max-comment", 0);
150 if( db_get_boolean("timeline-block-markup", 0) ){
151 wikiFlags = WIKI_INLINE;
@@ -157,10 +217,14 @@
157 /* style is not moved to css, because this is
158 ** a technical div for the timeline graph
159 */
160 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
161 }
 
 
 
 
162
163 @ <table id="timelineTable" class="timelineTable">
164 blob_zero(&comment);
165 while( db_step(pQuery)==SQLITE_ROW ){
166 int rid = db_column_int(pQuery, 0);
@@ -170,10 +234,11 @@
170 const char *zDate = db_column_text(pQuery, 2);
171 const char *zType = db_column_text(pQuery, 7);
172 const char *zUser = db_column_text(pQuery, 4);
173 const char *zTagList = db_column_text(pQuery, 8);
174 int tagid = db_column_int(pQuery, 9);
 
175 int commentColumn = 3; /* Column containing comment text */
176 char zTime[8];
177 if( tagid ){
178 if( tagid==prevTagid ){
179 if( tmFlags & TIMELINE_BRIEF ){
@@ -208,37 +273,44 @@
208 memcpy(zTime, &zDate[11], 5);
209 zTime[5] = 0;
210 @ <tr>
211 @ <td class="timelineTime">%s(zTime)</td>
212 @ <td class="timelineGraph">
213 if( pGraph && zType[0]=='c' ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214 int nParent = 0;
215 int aParent[32];
216 const char *zBr;
217 int gidx;
218 static Stmt qparent;
219 static Stmt qbranch;
220 db_static_prepare(&qparent,
221 "SELECT pid FROM plink"
222 " WHERE cid=:rid AND pid NOT IN phantom"
223 " ORDER BY isprim DESC /*sort*/"
224 );
225 db_static_prepare(&qbranch,
226 "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
227 TAG_BRANCH
228 );
229 db_bind_int(&qparent, ":rid", rid);
230 while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){
231 aParent[nParent++] = db_column_int(&qparent, 0);
232 }
233 db_reset(&qparent);
234 db_bind_int(&qbranch, ":rid", rid);
235 if( db_step(&qbranch)==SQLITE_ROW ){
236 zBr = db_column_text(&qbranch, 0);
237 }else{
238 zBr = "trunk";
239 }
240 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf);
241 db_reset(&qbranch);
242 @ <div id="m%d(gidx)"></div>
243 }
244 @</td>
@@ -397,11 +469,11 @@
397 /*
398 ** Generate all of the necessary javascript to generate a timeline
399 ** graph.
400 */
401 void timeline_output_graph_javascript(GraphContext *pGraph, int omitDescenders){
402 if( pGraph && pGraph->nErr==0 ){
403 GraphRow *pRow;
404 int i;
405 char cSep;
406 @ <script type="text/JavaScript">
407 @ /* <![CDATA[ */
@@ -768,10 +840,12 @@
768 ** fc Show details of files changed
769 ** f=RID Show family (immediate parents and children) of RID
770 ** from=RID Path from...
771 ** to=RID ... to this
772 ** nomerge ... avoid merge links on the path
 
 
773 **
774 ** p= and d= can appear individually or together. If either p= or d=
775 ** appear, then u=, y=, a=, and b= are ignored.
776 **
777 ** If a= and b= appear, only a= is used. If neither appear, the most
@@ -826,10 +900,12 @@
826 tmFlags = TIMELINE_GRAPH;
827 }
828 if( P("ng")!=0 || zSearch!=0 ){
829 tmFlags &= ~TIMELINE_GRAPH;
830 }
 
 
831
832 style_header("Timeline");
833 login_anonymous_available();
834 timeline_temp_table();
835 blob_zero(&sql);
@@ -1020,11 +1096,12 @@
1020 }else if( zType[0]=='e' ){
1021 zEType = "event";
1022 }
1023 }
1024 if( zUser ){
1025 blob_appendf(&sql, " AND event.user=%Q", zUser);
 
1026 url_add_parameter(&url, "u", zUser);
1027 zThisUser = zUser;
1028 }
1029 if ( zSearch ){
1030 blob_appendf(&sql,
@@ -1178,14 +1255,16 @@
1178 ** 2. Date/Time
1179 ** 3. Comment string and user
1180 ** 4. Number of non-merge children
1181 ** 5. Number of parents
1182 */
1183 void print_timeline(Stmt *q, int mxLine){
1184 int nLine = 0;
1185 char zPrevDate[20];
1186 const char *zCurrentUuid=0;
 
 
1187 zPrevDate[0] = 0;
1188
1189 if( g.localOpen ){
1190 int rid = db_lget_int("checkout", 0);
1191 zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1231,11 +1310,42 @@
1231 n += strlen(zPrefix);
1232 }
1233 zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
1234 nLine += comment_print(zFree, 9, 79);
1235 sqlite3_free(zFree);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1236 }
 
1237 }
1238
1239 /*
1240 ** Return a pointer to a static string that forms the basis for
1241 ** a timeline query for display on a TTY.
@@ -1276,11 +1386,11 @@
1276 }
1277
1278 /*
1279 ** COMMAND: timeline
1280 **
1281 ** Usage: %fossil timeline ?WHEN? ?BASELINE|DATETIME? ?-n N? ?-t TYPE?
1282 **
1283 ** Print a summary of activity going backwards in date and time
1284 ** specified or from the current date and time if no arguments
1285 ** are given. Show as many as N (default 20) check-ins. The
1286 ** WHEN argument can be any unique abbreviation of one of these
@@ -1300,10 +1410,14 @@
1300 ** page. For example:
1301 **
1302 ** w = wiki commits only
1303 ** ci = file commits only
1304 ** t = tickets only
 
 
 
 
1305 */
1306 void timeline_cmd(void){
1307 Stmt q;
1308 int n, k;
1309 const char *zCount;
@@ -1312,10 +1426,12 @@
1312 char *zDate;
1313 Blob sql;
1314 int objid = 0;
1315 Blob uuid;
1316 int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */
 
 
1317 db_find_and_open_repository(0, 0);
1318 zCount = find_option("count","n",1);
1319 zType = find_option("type","t",1);
1320 if( zCount ){
1321 n = atoi(zCount);
@@ -1338,13 +1454,13 @@
1338 mode = 4;
1339 }else if(!zType && !zCount){
1340 usage("?WHEN? ?BASELINE|DATETIME? ?-n|--count N? ?-t TYPE?");
1341 }
1342 if( '-' != *g.argv[3] ){
1343 zOrigin = g.argv[3];
1344 }else{
1345 zOrigin = "now";
1346 }
1347 }else if( g.argc==3 ){
1348 zOrigin = g.argv[2];
1349 }else{
1350 zOrigin = "now";
@@ -1398,11 +1514,11 @@
1398 }
1399
1400 blob_appendf(&sql, " ORDER BY event.mtime DESC");
1401 db_prepare(&q, blob_str(&sql));
1402 blob_reset(&sql);
1403 print_timeline(&q, n);
1404 db_finalize(&q);
1405 }
1406
1407 /*
1408 ** This is a version of the "localtime()" function from the standard
1409
--- src/timeline.c
+++ src/timeline.c
@@ -107,11 +107,70 @@
107 #define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */
108 #define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */
109 #define TIMELINE_GRAPH 0x0008 /* Compute a graph */
110 #define TIMELINE_DISJOINT 0x0010 /* Elements are not contiguous */
111 #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
112 #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */
113 #define TIMELINE_UCOLOR 0x0080 /* Background color by user */
114 #endif
115
116 /*
117 ** Hash a string and use the hash to determine a background color.
118 */
119 char *hash_color(const char *z){
120 int i; /* Loop counter */
121 unsigned int h = 0; /* Hash on the branch name */
122 int r, g, b; /* Values for red, green, and blue */
123 int h1, h2, h3, h4; /* Elements of the hash value */
124 int mx, mn; /* Components of HSV */
125 static char zColor[10]; /* The resulting color */
126 static int ix[2] = {0,0}; /* Color chooser parameters */
127
128 if( ix[0]==0 ){
129 if( db_get_boolean("white-foreground", 0) ){
130 ix[0] = 140;
131 ix[1] = 40;
132 }else{
133 ix[0] = 216;
134 ix[1] = 16;
135 }
136 }
137 for(i=0; z[i]; i++ ){
138 h = (h<<11) ^ (h<<1) ^ (h>>3) ^ z[i];
139 }
140 h1 = h % 6; h /= 6;
141 h3 = h % 30; h /= 30;
142 h4 = h % 40; h /= 40;
143 mx = ix[0] - h3;
144 mn = mx - h4 - ix[1];
145 h2 = (h%(mx - mn)) + mn;
146 switch( h1 ){
147 case 0: r = mx; g = h2, b = mn; break;
148 case 1: r = h2; g = mx, b = mn; break;
149 case 2: r = mn; g = mx, b = h2; break;
150 case 3: r = mn; g = h2, b = mx; break;
151 case 4: r = h2; g = mn, b = mx; break;
152 default: r = mx; g = mn, b = h2; break;
153 }
154 sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b);
155 return zColor;
156 }
157
158 /*
159 ** COMMAND: test-hash-color
160 **
161 ** Usage: %fossil test-hash-color TAG ...
162 **
163 ** Print out the color names associated with each tag. Used for
164 ** testing the hash_color() function.
165 */
166 void test_hash_color(void){
167 int i;
168 for(i=2; i<g.argc; i++){
169 fossil_print("%20s: %s\n", g.argv[i], hash_color(g.argv[i]));
170 }
171 }
172
173 /*
174 ** Output a timeline in the web format given a query. The query
175 ** should return these columns:
176 **
@@ -142,10 +201,11 @@
201 char zPrevDate[20];
202 GraphContext *pGraph = 0;
203 int prevWasDivider = 0; /* True if previous output row was <hr> */
204 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
205 Stmt fchngQuery; /* Query for file changes on check-ins */
206 static Stmt qbranch;
207
208 zPrevDate[0] = 0;
209 mxWikiLen = db_get_int("timeline-max-comment", 0);
210 if( db_get_boolean("timeline-block-markup", 0) ){
211 wikiFlags = WIKI_INLINE;
@@ -157,10 +217,14 @@
217 /* style is not moved to css, because this is
218 ** a technical div for the timeline graph
219 */
220 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
221 }
222 db_static_prepare(&qbranch,
223 "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
224 TAG_BRANCH
225 );
226
227 @ <table id="timelineTable" class="timelineTable">
228 blob_zero(&comment);
229 while( db_step(pQuery)==SQLITE_ROW ){
230 int rid = db_column_int(pQuery, 0);
@@ -170,10 +234,11 @@
234 const char *zDate = db_column_text(pQuery, 2);
235 const char *zType = db_column_text(pQuery, 7);
236 const char *zUser = db_column_text(pQuery, 4);
237 const char *zTagList = db_column_text(pQuery, 8);
238 int tagid = db_column_int(pQuery, 9);
239 const char *zBr = 0; /* Branch */
240 int commentColumn = 3; /* Column containing comment text */
241 char zTime[8];
242 if( tagid ){
243 if( tagid==prevTagid ){
244 if( tmFlags & TIMELINE_BRIEF ){
@@ -208,37 +273,44 @@
273 memcpy(zTime, &zDate[11], 5);
274 zTime[5] = 0;
275 @ <tr>
276 @ <td class="timelineTime">%s(zTime)</td>
277 @ <td class="timelineGraph">
278 if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0;
279 if( zType[0]=='c'
280 && (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0)
281 ){
282 db_reset(&qbranch);
283 db_bind_int(&qbranch, ":rid", rid);
284 if( db_step(&qbranch)==SQLITE_ROW ){
285 zBr = db_column_text(&qbranch, 0);
286 }else{
287 zBr = "trunk";
288 }
289 if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
290 if( zBr==0 || strcmp(zBr,"trunk")==0 ){
291 zBgClr = 0;
292 }else{
293 zBgClr = hash_color(zBr);
294 }
295 }
296 }
297 if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
298 int nParent = 0;
299 int aParent[32];
 
300 int gidx;
301 static Stmt qparent;
 
302 db_static_prepare(&qparent,
303 "SELECT pid FROM plink"
304 " WHERE cid=:rid AND pid NOT IN phantom"
305 " ORDER BY isprim DESC /*sort*/"
306 );
 
 
 
 
307 db_bind_int(&qparent, ":rid", rid);
308 while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){
309 aParent[nParent++] = db_column_int(&qparent, 0);
310 }
311 db_reset(&qparent);
 
 
 
 
 
 
312 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf);
313 db_reset(&qbranch);
314 @ <div id="m%d(gidx)"></div>
315 }
316 @</td>
@@ -397,11 +469,11 @@
469 /*
470 ** Generate all of the necessary javascript to generate a timeline
471 ** graph.
472 */
473 void timeline_output_graph_javascript(GraphContext *pGraph, int omitDescenders){
474 if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){
475 GraphRow *pRow;
476 int i;
477 char cSep;
478 @ <script type="text/JavaScript">
479 @ /* <![CDATA[ */
@@ -768,10 +840,12 @@
840 ** fc Show details of files changed
841 ** f=RID Show family (immediate parents and children) of RID
842 ** from=RID Path from...
843 ** to=RID ... to this
844 ** nomerge ... avoid merge links on the path
845 ** brbg Background color from branch name
846 ** ubg Background color from user
847 **
848 ** p= and d= can appear individually or together. If either p= or d=
849 ** appear, then u=, y=, a=, and b= are ignored.
850 **
851 ** If a= and b= appear, only a= is used. If neither appear, the most
@@ -826,10 +900,12 @@
900 tmFlags = TIMELINE_GRAPH;
901 }
902 if( P("ng")!=0 || zSearch!=0 ){
903 tmFlags &= ~TIMELINE_GRAPH;
904 }
905 if( P("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
906 if( P("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
907
908 style_header("Timeline");
909 login_anonymous_available();
910 timeline_temp_table();
911 blob_zero(&sql);
@@ -1020,11 +1096,12 @@
1096 }else if( zType[0]=='e' ){
1097 zEType = "event";
1098 }
1099 }
1100 if( zUser ){
1101 blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1102 zUser, zUser);
1103 url_add_parameter(&url, "u", zUser);
1104 zThisUser = zUser;
1105 }
1106 if ( zSearch ){
1107 blob_appendf(&sql,
@@ -1178,14 +1255,16 @@
1255 ** 2. Date/Time
1256 ** 3. Comment string and user
1257 ** 4. Number of non-merge children
1258 ** 5. Number of parents
1259 */
1260 void print_timeline(Stmt *q, int mxLine, int showfiles){
1261 int nLine = 0;
1262 char zPrevDate[20];
1263 const char *zCurrentUuid=0;
1264 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
1265 Stmt fchngQuery; /* Query for file changes on check-ins */
1266 zPrevDate[0] = 0;
1267
1268 if( g.localOpen ){
1269 int rid = db_lget_int("checkout", 0);
1270 zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1231,11 +1310,42 @@
1310 n += strlen(zPrefix);
1311 }
1312 zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
1313 nLine += comment_print(zFree, 9, 79);
1314 sqlite3_free(zFree);
1315
1316 if(showfiles){
1317 if( !fchngQueryInit ){
1318 db_prepare(&fchngQuery,
1319 "SELECT (pid==0) AS isnew,"
1320 " (fid==0) AS isdel,"
1321 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
1322 " (SELECT uuid FROM blob WHERE rid=fid),"
1323 " (SELECT uuid FROM blob WHERE rid=pid)"
1324 " FROM mlink"
1325 " WHERE mid=:mid AND pid!=fid"
1326 " ORDER BY 3 /*sort*/"
1327 );
1328 fchngQueryInit = 1;
1329 }
1330 db_bind_int(&fchngQuery, ":mid", rid);
1331 while( db_step(&fchngQuery)==SQLITE_ROW ){
1332 const char *zFilename = db_column_text(&fchngQuery, 2);
1333 int isNew = db_column_int(&fchngQuery, 0);
1334 int isDel = db_column_int(&fchngQuery, 1);
1335 if( isNew ){
1336 fossil_print(" ADDED %s\n",zFilename);
1337 }else if( isDel ){
1338 fossil_print(" DELETED %s\n",zFilename);
1339 }else{
1340 fossil_print(" EDITED %s\n", zFilename);
1341 }
1342 }
1343 db_reset(&fchngQuery);
1344 }
1345 }
1346 if( fchngQueryInit ) db_finalize(&fchngQuery);
1347 }
1348
1349 /*
1350 ** Return a pointer to a static string that forms the basis for
1351 ** a timeline query for display on a TTY.
@@ -1276,11 +1386,11 @@
1386 }
1387
1388 /*
1389 ** COMMAND: timeline
1390 **
1391 ** Usage: %fossil timeline ?WHEN? ?BASELINE|DATETIME? ?-n N? ?-t TYPE? ?-showfiles?
1392 **
1393 ** Print a summary of activity going backwards in date and time
1394 ** specified or from the current date and time if no arguments
1395 ** are given. Show as many as N (default 20) check-ins. The
1396 ** WHEN argument can be any unique abbreviation of one of these
@@ -1300,10 +1410,14 @@
1410 ** page. For example:
1411 **
1412 ** w = wiki commits only
1413 ** ci = file commits only
1414 ** t = tickets only
1415 **
1416 ** The optional showfiles argument if specified prints the list of
1417 ** files changed in a checkin after the checkin comment
1418 **
1419 */
1420 void timeline_cmd(void){
1421 Stmt q;
1422 int n, k;
1423 const char *zCount;
@@ -1312,10 +1426,12 @@
1426 char *zDate;
1427 Blob sql;
1428 int objid = 0;
1429 Blob uuid;
1430 int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */
1431 int showfilesFlag = 0 ;
1432 showfilesFlag = find_option("showfiles","f", 0)!=0;
1433 db_find_and_open_repository(0, 0);
1434 zCount = find_option("count","n",1);
1435 zType = find_option("type","t",1);
1436 if( zCount ){
1437 n = atoi(zCount);
@@ -1338,13 +1454,13 @@
1454 mode = 4;
1455 }else if(!zType && !zCount){
1456 usage("?WHEN? ?BASELINE|DATETIME? ?-n|--count N? ?-t TYPE?");
1457 }
1458 if( '-' != *g.argv[3] ){
1459 zOrigin = g.argv[3];
1460 }else{
1461 zOrigin = "now";
1462 }
1463 }else if( g.argc==3 ){
1464 zOrigin = g.argv[2];
1465 }else{
1466 zOrigin = "now";
@@ -1398,11 +1514,11 @@
1514 }
1515
1516 blob_appendf(&sql, " ORDER BY event.mtime DESC");
1517 db_prepare(&q, blob_str(&sql));
1518 blob_reset(&sql);
1519 print_timeline(&q, n, showfilesFlag);
1520 db_finalize(&q);
1521 }
1522
1523 /*
1524 ** This is a version of the "localtime()" function from the standard
1525
+1 -1
--- src/tkt.c
+++ src/tkt.c
@@ -731,11 +731,11 @@
731731
zUuid = PD("name","");
732732
zTitle = mprintf("History Of Ticket %h", zUuid);
733733
style_submenu_element("Status", "Status",
734734
"%s/info/%s", g.zTop, zUuid);
735735
style_submenu_element("Check-ins", "Check-ins",
736
- "%s/tkttimeline?name=%s?y=ci", g.zTop, zUuid);
736
+ "%s/tkttimeline?name=%s&amp;y=ci", g.zTop, zUuid);
737737
style_submenu_element("Timeline", "Timeline",
738738
"%s/tkttimeline?name=%s", g.zTop, zUuid);
739739
style_header(zTitle);
740740
free(zTitle);
741741
742742
--- src/tkt.c
+++ src/tkt.c
@@ -731,11 +731,11 @@
731 zUuid = PD("name","");
732 zTitle = mprintf("History Of Ticket %h", zUuid);
733 style_submenu_element("Status", "Status",
734 "%s/info/%s", g.zTop, zUuid);
735 style_submenu_element("Check-ins", "Check-ins",
736 "%s/tkttimeline?name=%s?y=ci", g.zTop, zUuid);
737 style_submenu_element("Timeline", "Timeline",
738 "%s/tkttimeline?name=%s", g.zTop, zUuid);
739 style_header(zTitle);
740 free(zTitle);
741
742
--- src/tkt.c
+++ src/tkt.c
@@ -731,11 +731,11 @@
731 zUuid = PD("name","");
732 zTitle = mprintf("History Of Ticket %h", zUuid);
733 style_submenu_element("Status", "Status",
734 "%s/info/%s", g.zTop, zUuid);
735 style_submenu_element("Check-ins", "Check-ins",
736 "%s/tkttimeline?name=%s&amp;y=ci", g.zTop, zUuid);
737 style_submenu_element("Timeline", "Timeline",
738 "%s/tkttimeline?name=%s", g.zTop, zUuid);
739 style_header(zTitle);
740 free(zTitle);
741
742
+58 -2
--- src/update.c
+++ src/update.c
@@ -115,10 +115,13 @@
115115
}
116116
if( !nochangeFlag && db_exists("SELECT 1 FROM vmerge") ){
117117
fossil_fatal("cannot update an uncommitted merge");
118118
}
119119
if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
120
+
121
+ /* Create any empty directories now, as well as after the update, so changes in settings are reflected now */
122
+ ensure_empty_dirs_created();
120123
121124
if( internalUpdate ){
122125
tid = internalUpdate;
123126
}else if( g.argc>=3 ){
124127
if( fossil_strcmp(g.argv[2], "current")==0 ){
@@ -167,11 +170,11 @@
167170
"%s "
168171
" AND event.objid IN leaves"
169172
" ORDER BY event.mtime DESC",
170173
timeline_query_for_tty()
171174
);
172
- print_timeline(&q, 100);
175
+ print_timeline(&q, 100, 0);
173176
db_finalize(&q);
174177
fossil_fatal("Multiple descendants");
175178
}
176179
}
177180
tid = db_int(0, "SELECT rid FROM leaves, event"
@@ -182,11 +185,10 @@
182185
183186
if( tid==0 ){
184187
fossil_panic("Internal Error: unable to find a version to update to.");
185188
}
186189
187
- if( tid==vid && !verboseFlag ) return; /* Nothing to update */
188190
db_begin_transaction();
189191
vfile_check_signature(vid, 1, 0);
190192
if( !nochangeFlag && !internalUpdate ) undo_begin();
191193
load_vfile_from_rid(tid);
192194
@@ -441,10 +443,11 @@
441443
** Clean up the mid and pid VFILE entries. Then commit the changes.
442444
*/
443445
if( nochangeFlag ){
444446
db_end_transaction(1); /* With --nochange, rollback changes */
445447
}else{
448
+ ensure_empty_dirs_created();
446449
if( g.argc<=3 ){
447450
/* All files updated. Shift the current checkout to the target. */
448451
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
449452
checkout_set_all_exe(tid);
450453
manifest_to_disk(tid);
@@ -456,10 +459,63 @@
456459
}
457460
if( !internalUpdate ) undo_finish();
458461
db_end_transaction(0);
459462
}
460463
}
464
+
465
+/*
466
+** Make sure empty directories are created
467
+*/
468
+void ensure_empty_dirs_created(void){
469
+ /* Make empty directories? */
470
+ char *zEmptyDirs = db_get("empty-dirs", 0);
471
+ if( zEmptyDirs!=0 ){
472
+ char *bc;
473
+ Blob dirName;
474
+ Blob dirsList;
475
+
476
+ blob_zero(&dirsList);
477
+ blob_init(&dirsList, zEmptyDirs, strlen(zEmptyDirs));
478
+ /* Replace commas by spaces */
479
+ bc = blob_str(&dirsList);
480
+ while( (*bc)!='\0' ){
481
+ if( (*bc)==',' ) { *bc = ' '; }
482
+ ++bc;
483
+ }
484
+ /* Make directories */
485
+ blob_zero(&dirName);
486
+ while( blob_token(&dirsList, &dirName) ){
487
+ const char *zDir = blob_str(&dirName);
488
+ /* Make full pathname of the directory */
489
+ Blob path;
490
+ const char *zPath;
491
+
492
+ blob_zero(&path);
493
+ blob_appendf(&path, "%s/%s", g.zLocalRoot, zDir);
494
+ zPath = blob_str(&path);
495
+ /* Handle various cases of existence of the directory */
496
+ switch( file_isdir(zPath) ){
497
+ case 0: { /* doesn't exist */
498
+ if( file_mkdir(zPath, 0)!=0 ) {
499
+ fossil_warning("couldn't create directory %s as "
500
+ "required by empty-dirs setting", zDir);
501
+ }
502
+ break;
503
+ }
504
+ case 1: { /* exists, and is a directory */
505
+ /* do nothing - required directory exists already */
506
+ break;
507
+ }
508
+ case 2: { /* exists, but isn't a directory */
509
+ fossil_warning("file %s found, but a directory is required "
510
+ "by empty-dirs setting", zDir);
511
+ }
512
+ }
513
+ blob_reset(&path);
514
+ }
515
+ }
516
+}
461517
462518
463519
/*
464520
** Get the contents of a file within the checking "revision". If
465521
** revision==NULL then get the file content for the current checkout.
466522
--- src/update.c
+++ src/update.c
@@ -115,10 +115,13 @@
115 }
116 if( !nochangeFlag && db_exists("SELECT 1 FROM vmerge") ){
117 fossil_fatal("cannot update an uncommitted merge");
118 }
119 if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
 
 
 
120
121 if( internalUpdate ){
122 tid = internalUpdate;
123 }else if( g.argc>=3 ){
124 if( fossil_strcmp(g.argv[2], "current")==0 ){
@@ -167,11 +170,11 @@
167 "%s "
168 " AND event.objid IN leaves"
169 " ORDER BY event.mtime DESC",
170 timeline_query_for_tty()
171 );
172 print_timeline(&q, 100);
173 db_finalize(&q);
174 fossil_fatal("Multiple descendants");
175 }
176 }
177 tid = db_int(0, "SELECT rid FROM leaves, event"
@@ -182,11 +185,10 @@
182
183 if( tid==0 ){
184 fossil_panic("Internal Error: unable to find a version to update to.");
185 }
186
187 if( tid==vid && !verboseFlag ) return; /* Nothing to update */
188 db_begin_transaction();
189 vfile_check_signature(vid, 1, 0);
190 if( !nochangeFlag && !internalUpdate ) undo_begin();
191 load_vfile_from_rid(tid);
192
@@ -441,10 +443,11 @@
441 ** Clean up the mid and pid VFILE entries. Then commit the changes.
442 */
443 if( nochangeFlag ){
444 db_end_transaction(1); /* With --nochange, rollback changes */
445 }else{
 
446 if( g.argc<=3 ){
447 /* All files updated. Shift the current checkout to the target. */
448 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
449 checkout_set_all_exe(tid);
450 manifest_to_disk(tid);
@@ -456,10 +459,63 @@
456 }
457 if( !internalUpdate ) undo_finish();
458 db_end_transaction(0);
459 }
460 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
462
463 /*
464 ** Get the contents of a file within the checking "revision". If
465 ** revision==NULL then get the file content for the current checkout.
466
--- src/update.c
+++ src/update.c
@@ -115,10 +115,13 @@
115 }
116 if( !nochangeFlag && db_exists("SELECT 1 FROM vmerge") ){
117 fossil_fatal("cannot update an uncommitted merge");
118 }
119 if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
120
121 /* Create any empty directories now, as well as after the update, so changes in settings are reflected now */
122 ensure_empty_dirs_created();
123
124 if( internalUpdate ){
125 tid = internalUpdate;
126 }else if( g.argc>=3 ){
127 if( fossil_strcmp(g.argv[2], "current")==0 ){
@@ -167,11 +170,11 @@
170 "%s "
171 " AND event.objid IN leaves"
172 " ORDER BY event.mtime DESC",
173 timeline_query_for_tty()
174 );
175 print_timeline(&q, 100, 0);
176 db_finalize(&q);
177 fossil_fatal("Multiple descendants");
178 }
179 }
180 tid = db_int(0, "SELECT rid FROM leaves, event"
@@ -182,11 +185,10 @@
185
186 if( tid==0 ){
187 fossil_panic("Internal Error: unable to find a version to update to.");
188 }
189
 
190 db_begin_transaction();
191 vfile_check_signature(vid, 1, 0);
192 if( !nochangeFlag && !internalUpdate ) undo_begin();
193 load_vfile_from_rid(tid);
194
@@ -441,10 +443,11 @@
443 ** Clean up the mid and pid VFILE entries. Then commit the changes.
444 */
445 if( nochangeFlag ){
446 db_end_transaction(1); /* With --nochange, rollback changes */
447 }else{
448 ensure_empty_dirs_created();
449 if( g.argc<=3 ){
450 /* All files updated. Shift the current checkout to the target. */
451 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
452 checkout_set_all_exe(tid);
453 manifest_to_disk(tid);
@@ -456,10 +459,63 @@
459 }
460 if( !internalUpdate ) undo_finish();
461 db_end_transaction(0);
462 }
463 }
464
465 /*
466 ** Make sure empty directories are created
467 */
468 void ensure_empty_dirs_created(void){
469 /* Make empty directories? */
470 char *zEmptyDirs = db_get("empty-dirs", 0);
471 if( zEmptyDirs!=0 ){
472 char *bc;
473 Blob dirName;
474 Blob dirsList;
475
476 blob_zero(&dirsList);
477 blob_init(&dirsList, zEmptyDirs, strlen(zEmptyDirs));
478 /* Replace commas by spaces */
479 bc = blob_str(&dirsList);
480 while( (*bc)!='\0' ){
481 if( (*bc)==',' ) { *bc = ' '; }
482 ++bc;
483 }
484 /* Make directories */
485 blob_zero(&dirName);
486 while( blob_token(&dirsList, &dirName) ){
487 const char *zDir = blob_str(&dirName);
488 /* Make full pathname of the directory */
489 Blob path;
490 const char *zPath;
491
492 blob_zero(&path);
493 blob_appendf(&path, "%s/%s", g.zLocalRoot, zDir);
494 zPath = blob_str(&path);
495 /* Handle various cases of existence of the directory */
496 switch( file_isdir(zPath) ){
497 case 0: { /* doesn't exist */
498 if( file_mkdir(zPath, 0)!=0 ) {
499 fossil_warning("couldn't create directory %s as "
500 "required by empty-dirs setting", zDir);
501 }
502 break;
503 }
504 case 1: { /* exists, and is a directory */
505 /* do nothing - required directory exists already */
506 break;
507 }
508 case 2: { /* exists, but isn't a directory */
509 fossil_warning("file %s found, but a directory is required "
510 "by empty-dirs setting", zDir);
511 }
512 }
513 blob_reset(&path);
514 }
515 }
516 }
517
518
519 /*
520 ** Get the contents of a file within the checking "revision". If
521 ** revision==NULL then get the file content for the current checkout.
522
+8 -20
--- src/wiki.c
+++ src/wiki.c
@@ -182,12 +182,11 @@
182182
" ORDER BY mtime DESC", zTag
183183
);
184184
free(zTag);
185185
pWiki = manifest_get(rid, CFTYPE_WIKI);
186186
if( pWiki ){
187
- while( fossil_isspace(pWiki->zWiki[0]) ) pWiki->zWiki++;
188
- if( pWiki->zWiki[0] ) zBody = pWiki->zWiki;
187
+ zBody = pWiki->zWiki;
189188
}
190189
}
191190
if( !g.isHome ){
192191
if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
193192
style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
@@ -891,10 +890,11 @@
891890
char const *zPageName; /* Name of the wiki page to export */
892891
char const *zFile; /* Name of the output file (0=stdout) */
893892
int rid; /* Artifact ID of the wiki page */
894893
int i; /* Loop counter */
895894
char *zBody = 0; /* Wiki page content */
895
+ Blob body; /* Wiki page content */
896896
Manifest *pWiki = 0; /* Parsed wiki page content */
897897
898898
if( (g.argc!=4) && (g.argc!=5) ){
899899
usage("export PAGENAME ?FILE?");
900900
}
@@ -909,28 +909,16 @@
909909
}
910910
if( zBody==0 ){
911911
fossil_fatal("wiki page [%s] not found",zPageName);
912912
}
913913
for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
914
- zFile = (g.argc==4) ? 0 : g.argv[4];
915
- if( zFile ){
916
- FILE * zF;
917
- short doClose = 0;
918
- if( (1 == strlen(zFile)) && ('-'==zFile[0]) ){
919
- zF = stdout;
920
- }else{
921
- zF = fossil_fopen( zFile, "w" );
922
- doClose = zF ? 1 : 0;
923
- }
924
- if( ! zF ){
925
- fossil_fatal("wiki export could not open output file for writing.");
926
- }
927
- fprintf(zF,"%.*s\n", i, zBody);
928
- if( doClose ) fclose(zF);
929
- }else{
930
- fossil_print("%.*s\n", i, zBody);
931
- }
914
+ zBody[i] = 0;
915
+ zFile = (g.argc==4) ? "-" : g.argv[4];
916
+ blob_init(&body, zBody, -1);
917
+ blob_append(&body, "\n", 1);
918
+ blob_write_to_file(&body, zFile);
919
+ blob_reset(&body);
932920
manifest_destroy(pWiki);
933921
return;
934922
}else
935923
if( strncmp(g.argv[2],"commit",n)==0
936924
|| strncmp(g.argv[2],"create",n)==0 ){
937925
--- src/wiki.c
+++ src/wiki.c
@@ -182,12 +182,11 @@
182 " ORDER BY mtime DESC", zTag
183 );
184 free(zTag);
185 pWiki = manifest_get(rid, CFTYPE_WIKI);
186 if( pWiki ){
187 while( fossil_isspace(pWiki->zWiki[0]) ) pWiki->zWiki++;
188 if( pWiki->zWiki[0] ) zBody = pWiki->zWiki;
189 }
190 }
191 if( !g.isHome ){
192 if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
193 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
@@ -891,10 +890,11 @@
891 char const *zPageName; /* Name of the wiki page to export */
892 char const *zFile; /* Name of the output file (0=stdout) */
893 int rid; /* Artifact ID of the wiki page */
894 int i; /* Loop counter */
895 char *zBody = 0; /* Wiki page content */
 
896 Manifest *pWiki = 0; /* Parsed wiki page content */
897
898 if( (g.argc!=4) && (g.argc!=5) ){
899 usage("export PAGENAME ?FILE?");
900 }
@@ -909,28 +909,16 @@
909 }
910 if( zBody==0 ){
911 fossil_fatal("wiki page [%s] not found",zPageName);
912 }
913 for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
914 zFile = (g.argc==4) ? 0 : g.argv[4];
915 if( zFile ){
916 FILE * zF;
917 short doClose = 0;
918 if( (1 == strlen(zFile)) && ('-'==zFile[0]) ){
919 zF = stdout;
920 }else{
921 zF = fossil_fopen( zFile, "w" );
922 doClose = zF ? 1 : 0;
923 }
924 if( ! zF ){
925 fossil_fatal("wiki export could not open output file for writing.");
926 }
927 fprintf(zF,"%.*s\n", i, zBody);
928 if( doClose ) fclose(zF);
929 }else{
930 fossil_print("%.*s\n", i, zBody);
931 }
932 manifest_destroy(pWiki);
933 return;
934 }else
935 if( strncmp(g.argv[2],"commit",n)==0
936 || strncmp(g.argv[2],"create",n)==0 ){
937
--- src/wiki.c
+++ src/wiki.c
@@ -182,12 +182,11 @@
182 " ORDER BY mtime DESC", zTag
183 );
184 free(zTag);
185 pWiki = manifest_get(rid, CFTYPE_WIKI);
186 if( pWiki ){
187 zBody = pWiki->zWiki;
 
188 }
189 }
190 if( !g.isHome ){
191 if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
192 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
@@ -891,10 +890,11 @@
890 char const *zPageName; /* Name of the wiki page to export */
891 char const *zFile; /* Name of the output file (0=stdout) */
892 int rid; /* Artifact ID of the wiki page */
893 int i; /* Loop counter */
894 char *zBody = 0; /* Wiki page content */
895 Blob body; /* Wiki page content */
896 Manifest *pWiki = 0; /* Parsed wiki page content */
897
898 if( (g.argc!=4) && (g.argc!=5) ){
899 usage("export PAGENAME ?FILE?");
900 }
@@ -909,28 +909,16 @@
909 }
910 if( zBody==0 ){
911 fossil_fatal("wiki page [%s] not found",zPageName);
912 }
913 for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
914 zBody[i] = 0;
915 zFile = (g.argc==4) ? "-" : g.argv[4];
916 blob_init(&body, zBody, -1);
917 blob_append(&body, "\n", 1);
918 blob_write_to_file(&body, zFile);
919 blob_reset(&body);
 
 
 
 
 
 
 
 
 
 
 
 
920 manifest_destroy(pWiki);
921 return;
922 }else
923 if( strncmp(g.argv[2],"commit",n)==0
924 || strncmp(g.argv[2],"create",n)==0 ){
925
+644 -9
--- src/winhttp.c
+++ src/winhttp.c
@@ -14,17 +14,18 @@
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
1818
** This file implements a very simple (and low-performance) HTTP server
19
-** for windows.
19
+** for windows. It also implements a Windows Service which allows the HTTP
20
+** server to be run without any user logged on.
2021
*/
2122
#include "config.h"
2223
#ifdef _WIN32
2324
/* This code is for win32 only */
24
-#include "winhttp.h"
2525
#include <windows.h>
26
+#include "winhttp.h"
2627
2728
/*
2829
** The HttpRequest structure holds information about each incoming
2930
** HTTP request.
3031
*/
@@ -60,11 +61,11 @@
6061
}
6162
6263
/*
6364
** Process a single incoming HTTP request.
6465
*/
65
-void win32_process_one_http_request(void *pAppData){
66
+static void win32_process_one_http_request(void *pAppData){
6667
HttpRequest *p = (HttpRequest*)pAppData;
6768
FILE *in = 0, *out = 0;
6869
int amt, got;
6970
int wanted = 0;
7071
char *z;
@@ -145,10 +146,11 @@
145146
SOCKET s = INVALID_SOCKET;
146147
SOCKADDR_IN addr;
147148
int idCnt = 0;
148149
int iPort = mnPort;
149150
Blob options;
151
+ char zTmpPath[MAX_PATH];
150152
151153
if( zStopper ) file_delete(zStopper);
152154
blob_zero(&options);
153155
if( zNotFound ){
154156
blob_appendf(&options, " --notfound %s", zNotFound);
@@ -189,31 +191,46 @@
189191
}else{
190192
fossil_fatal("unable to open listening socket on any"
191193
" port in the range %d..%d", mnPort, mxPort);
192194
}
193195
}
194
- zTempPrefix = mprintf("fossil_server_P%d_", iPort);
196
+ if( !GetTempPath(sizeof(zTmpPath), zTmpPath) ){
197
+ fossil_fatal("unable to get path to the temporary directory.");
198
+ }
199
+ zTempPrefix = mprintf("%sfossil_server_P%d_", zTmpPath, iPort);
195200
fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
196201
if( zBrowser ){
197202
zBrowser = mprintf(zBrowser, iPort);
198203
fossil_print("Launch webbrowser: %s\n", zBrowser);
199204
fossil_system(zBrowser);
200205
}
201206
fossil_print("Type Ctrl-C to stop the HTTP server\n");
207
+ /* Set the service status to running and pass the listener socket to the
208
+ ** service handling procedures. */
209
+ win32_http_service_running(s);
202210
for(;;){
203211
SOCKET client;
204212
SOCKADDR_IN client_addr;
205213
HttpRequest *p;
206214
int len = sizeof(client_addr);
215
+ int wsaError;
207216
208217
client = accept(s, (struct sockaddr*)&client_addr, &len);
209
- if( zStopper && file_size(zStopper)>=0 ){
210
- break;
211
- }
212218
if( client==INVALID_SOCKET ){
213
- closesocket(s);
214
- fossil_fatal("error from accept()");
219
+ /* If the service control handler has closed the listener socket,
220
+ ** cleanup and return, otherwise report a fatal error. */
221
+ wsaError = WSAGetLastError();
222
+ if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
223
+ WSACleanup();
224
+ return;
225
+ }else{
226
+ closesocket(s);
227
+ WSACleanup();
228
+ fossil_fatal("error from accept()");
229
+ }
230
+ }else if( zStopper && file_size(zStopper)>=0 ){
231
+ break;
215232
}
216233
p = fossil_malloc( sizeof(*p) );
217234
p->id = ++idCnt;
218235
p->s = client;
219236
p->addr = client_addr;
@@ -221,7 +238,625 @@
221238
_beginthread(win32_process_one_http_request, 0, (void*)p);
222239
}
223240
closesocket(s);
224241
WSACleanup();
225242
}
243
+
244
+/*
245
+** The HttpService structure is used to pass information to the service main
246
+** function and to the service control handler function.
247
+*/
248
+typedef struct HttpService HttpService;
249
+struct HttpService {
250
+ int port; /* Port on which the http server should run */
251
+ const char *zNotFound; /* The --notfound option, or NULL */
252
+ int flags; /* One or more HTTP_SERVER_ flags */
253
+ int isRunningAsService; /* Are we running as a service ? */
254
+ const char *zServiceName; /* Name of the service */
255
+ SOCKET s; /* Socket on which the http server listens */
256
+};
257
+
258
+/*
259
+** Variables used for running as windows service.
260
+*/
261
+static HttpService hsData = {8080, NULL, 0, 0, NULL, INVALID_SOCKET};
262
+static SERVICE_STATUS ssStatus;
263
+static SERVICE_STATUS_HANDLE sshStatusHandle;
264
+
265
+/*
266
+** Get message string of the last system error. Return a pointer to the
267
+** message string. Call fossil_mbcs_free() to deallocate any memory used
268
+** to store the message string when done.
269
+*/
270
+static char *win32_get_last_errmsg(void){
271
+ DWORD nMsg;
272
+ LPTSTR tmp = NULL;
273
+ char *zMsg = NULL;
274
+
275
+ nMsg = FormatMessage(
276
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
277
+ FORMAT_MESSAGE_FROM_SYSTEM |
278
+ FORMAT_MESSAGE_IGNORE_INSERTS,
279
+ NULL,
280
+ GetLastError(),
281
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
282
+ (LPTSTR) &tmp,
283
+ 0,
284
+ NULL
285
+ );
286
+ if( nMsg ){
287
+ zMsg = fossil_mbcs_to_utf8(tmp);
288
+ }else{
289
+ fossil_fatal("unable to get system error message.");
290
+ }
291
+ if( tmp ){
292
+ LocalFree((HLOCAL) tmp);
293
+ }
294
+ return zMsg;
295
+}
296
+
297
+/*
298
+** Report the current status of the service to the service control manager.
299
+** Make sure that during service startup no control codes are accepted.
300
+*/
301
+static void win32_report_service_status(
302
+ DWORD dwCurrentState, /* The current state of the service */
303
+ DWORD dwWin32ExitCode, /* The error code to report */
304
+ DWORD dwWaitHint /* The estimated time for a pending operation */
305
+){
306
+ if( dwCurrentState==SERVICE_START_PENDING) {
307
+ ssStatus.dwControlsAccepted = 0;
308
+ }else{
309
+ ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
310
+ }
311
+ ssStatus.dwCurrentState = dwCurrentState;
312
+ ssStatus.dwWin32ExitCode = dwWin32ExitCode;
313
+ ssStatus.dwWaitHint = dwWaitHint;
314
+
315
+ if( (dwCurrentState==SERVICE_RUNNING) ||
316
+ (dwCurrentState==SERVICE_STOPPED) ){
317
+ ssStatus.dwCheckPoint = 0;
318
+ }else{
319
+ ssStatus.dwCheckPoint++;
320
+ }
321
+ SetServiceStatus(sshStatusHandle, &ssStatus);
322
+ return ;
323
+}
324
+
325
+/*
326
+** Handle control codes sent from the service control manager.
327
+** The control dispatcher in the main thread of the service process invokes
328
+** this function whenever it receives a control request from the service
329
+** control manager.
330
+*/
331
+static void WINAPI win32_http_service_ctrl(
332
+ DWORD dwCtrlCode
333
+){
334
+ switch( dwCtrlCode ){
335
+ case SERVICE_CONTROL_STOP: {
336
+ win32_report_service_status(SERVICE_STOP_PENDING, NO_ERROR, 0);
337
+ if( hsData.s != INVALID_SOCKET ){
338
+ closesocket(hsData.s);
339
+ }
340
+ win32_report_service_status(ssStatus.dwCurrentState, NO_ERROR, 0);
341
+ break;
342
+ }
343
+ default: {
344
+ break;
345
+ }
346
+ }
347
+ return;
348
+}
349
+
350
+/*
351
+** This is the main entry point for the service.
352
+** When the service control manager receives a request to start the service,
353
+** it starts the service process (if it is not already running). The main
354
+** thread of the service process calls the StartServiceCtrlDispatcher
355
+** function with a pointer to an array of SERVICE_TABLE_ENTRY structures.
356
+** Then the service control manager sends a start request to the service
357
+** control dispatcher for this service process. The service control dispatcher
358
+** creates a new thread to execute the ServiceMain function (this function)
359
+** of the service being started.
360
+*/
361
+static void WINAPI win32_http_service_main(
362
+ DWORD argc, /* Number of arguments in argv */
363
+ LPTSTR *argv /* Arguments passed */
364
+){
365
+
366
+ /* Update the service information. */
367
+ hsData.isRunningAsService = 1;
368
+ if( argc>0 ){
369
+ hsData.zServiceName = argv[0];
370
+ }
371
+
372
+ /* Register the service control handler function */
373
+ sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl);
374
+ if( !sshStatusHandle ){
375
+ win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
376
+ return;
377
+ }
378
+
379
+ /* Set service specific data and report that the service is starting. */
380
+ ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
381
+ ssStatus.dwServiceSpecificExitCode = 0;
382
+ win32_report_service_status(SERVICE_START_PENDING, NO_ERROR, 3000);
383
+
384
+ /* Execute the http server */
385
+ win32_http_server(hsData.port, hsData.port,
386
+ NULL, NULL, hsData.zNotFound, hsData.flags);
387
+
388
+ /* Service has stopped now. */
389
+ win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
390
+ return;
391
+}
392
+
393
+/*
394
+** When running as service, update the HttpService structure with the
395
+** listener socket and update the service status. This procedure must be
396
+** called from the http server when he is ready to accept connections.
397
+*/
398
+LOCAL void win32_http_service_running(SOCKET s){
399
+ if( hsData.isRunningAsService ){
400
+ hsData.s = s;
401
+ win32_report_service_status(SERVICE_RUNNING, NO_ERROR, 0);
402
+ }
403
+}
404
+
405
+/*
406
+** Try to start the http server as a windows service. If we are running in
407
+** a interactive console session, this routine fails and returns a non zero
408
+** integer value. When running as service, this routine does not return until
409
+** the service is stopped. In this case, the return value is zero.
410
+*/
411
+int win32_http_service(
412
+ int nPort, /* TCP port number */
413
+ const char *zNotFound, /* The --notfound option, or NULL */
414
+ int flags /* One or more HTTP_SERVER_ flags */
415
+){
416
+ /* Define the service table. */
417
+ SERVICE_TABLE_ENTRY ServiceTable[] =
418
+ {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
419
+
420
+ /* Initialize the HttpService structure. */
421
+ hsData.port = nPort;
422
+ hsData.zNotFound = zNotFound;
423
+ hsData.flags = flags;
424
+
425
+ /* Try to start the control dispatcher thread for the service. */
426
+ if( !StartServiceCtrlDispatcher(ServiceTable) ){
427
+ if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
428
+ return 1;
429
+ }else{
430
+ fossil_fatal("error from StartServiceCtrlDispatcher()");
431
+ }
432
+ }
433
+ return 0;
434
+}
435
+
436
+/*
437
+** COMMAND: winsrv
438
+** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
439
+**
440
+** Where METHOD is one of: create delete show start stop.
441
+**
442
+** The winsrv command manages Fossil as a Windows service. This allows
443
+** (for example) Fossil to be running in the background when no user
444
+** is logged in.
445
+**
446
+** In the following description of the methods, "Fossil-DSCM" will be
447
+** used as the default SERVICE-NAME:
448
+**
449
+** fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
450
+**
451
+** Creates a service. Available options include:
452
+**
453
+** -D|--display DISPLAY-NAME
454
+**
455
+** Sets the display name of the service. This name is shown
456
+** by graphical interface programs. By default, the display name
457
+** equals to the service name.
458
+**
459
+** -S|--start TYPE
460
+**
461
+** Sets the start type of the service. TYPE can be "manual",
462
+** which means you need to start the service yourself with the
463
+** 'fossil winsrv start' command or with the "net start" command
464
+** from the operating system. If TYPE is set to "auto", the service
465
+** will be started automatically by the system during startup.
466
+**
467
+** -U|--username USERNAME
468
+**
469
+** Specifies the user account which will be used to run the
470
+** service. The account needs the "Logon as a service" right
471
+** enabled in its profile. Specify local accounts as follows:
472
+** ".\\USERNAME". By default, the "LocalSystem" account will be
473
+** used.
474
+**
475
+** -W|--password PASSWORD
476
+**
477
+** Password for the user account.
478
+**
479
+** The following options are more or less the same as for the "server"
480
+** command and influence the behaviour of the http server:
481
+**
482
+** -p|--port TCPPORT
483
+**
484
+** Specifies the TCP port (default port is 8080) on which the
485
+** server should listen.
486
+**
487
+** -R|--repository REPOSITORY
488
+**
489
+** Specifies the name of the repository to be served.
490
+** The repository option may be omitted if the working directory
491
+** is within an open checkout.
492
+** The REPOSITORY can be a directory (aka folder) that contains
493
+** one or more respositories with names ending in ".fossil".
494
+** In that case, the first element of the URL is used to select
495
+** among the various repositories.
496
+**
497
+** --notfound URL
498
+**
499
+** If REPOSITORY is a directory that contains one or more
500
+** respositories with names of the form "*.fossil" then the
501
+** first element of the URL pathname selects among the various
502
+** repositories. If the pathname does not select a valid
503
+** repository and the --notfound option is available,
504
+** then the server redirects (HTTP code 302) to the URL of
505
+** --notfound.
506
+**
507
+** --localauth
508
+**
509
+** Enables automatic login if the --localauth option is present
510
+** and the "localauth" setting is off and the connection is from
511
+** localhost.
512
+**
513
+**
514
+** fossil winsrv delete ?SERVICE-NAME?
515
+**
516
+** Deletes a service. If the service is currently running, it will be
517
+** stopped first and then deleted.
518
+**
519
+**
520
+** fossil winsrv show ?SERVICE-NAME?
521
+**
522
+** Shows how the service is configured and its current state.
523
+**
524
+**
525
+** fossil winsrv start ?SERVICE-NAME?
526
+**
527
+** Start the service.
528
+**
529
+**
530
+** fossil winsrv stop ?SERVICE-NAME?
531
+**
532
+** Stop the service.
533
+**
534
+**
535
+** NOTE: This command is available on Windows operating systems only and
536
+** requires administrative rights on the machine executed.
537
+**
538
+*/
539
+void cmd_win32_service(void){
540
+ int n;
541
+ const char *zMethod;
542
+ const char *zSvcName = "Fossil-DSCM"; /* Default service name */
543
+
544
+ if( g.argc<3 ){
545
+ usage("create|delete|show|start|stop ...");
546
+ }
547
+ zMethod = g.argv[2];
548
+ n = strlen(zMethod);
549
+ if( g.argc==4 ){
550
+ zSvcName = g.argv[3];
551
+ }
552
+
553
+ if( strncmp(zMethod, "create", n)==0 ){
554
+ SC_HANDLE hScm;
555
+ SC_HANDLE hSvc;
556
+ SERVICE_DESCRIPTION
557
+ svcDescr = {"Fossil - Distributed Software Configuration Management"};
558
+ char *zErrFmt = "unable to create service '%s': %s";
559
+ DWORD dwStartType = SERVICE_DEMAND_START;
560
+ const char *zDisplay;
561
+ const char *zStart;
562
+ const char *zUsername;
563
+ const char *zPassword;
564
+ const char *zPort;
565
+ const char *zNotFound;
566
+ const char *zLocalAuth;
567
+ const char *zRepository;
568
+ Blob binPath;
569
+
570
+ /* Process service creation specific options. */
571
+ zDisplay = find_option("display", "D", 1);
572
+ if( !zDisplay ){
573
+ zDisplay = zSvcName;
574
+ }
575
+ zStart = find_option("start", "S", 1);
576
+ if( zStart ){
577
+ if( strncmp(zStart, "auto", strlen(zStart))==0 ){
578
+ dwStartType = SERVICE_AUTO_START;
579
+ }else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
580
+ dwStartType = SERVICE_DEMAND_START;
581
+ }else{
582
+ fossil_fatal(zErrFmt, zSvcName,
583
+ "specify 'auto' or 'manual' for the '-S|--start' option");
584
+ }
585
+ }
586
+ zUsername = find_option("username", "U", 1);
587
+ zPassword = find_option("password", "W", 1);
588
+ /* Process options for Fossil running as server. */
589
+ zPort = find_option("port", "P", 1);
590
+ if( zPort && (atoi(zPort)<=0) ){
591
+ fossil_fatal(zErrFmt, zSvcName,
592
+ "port number must be in the range 1 - 65535.");
593
+ }
594
+ zNotFound = find_option("notfound", 0, 1);
595
+ zLocalAuth = find_option("localauth", 0, 0);
596
+ zRepository = find_option("repository", "R", 1);
597
+ if( !zRepository ){
598
+ db_must_be_within_tree();
599
+ }else if( file_isdir(zRepository)==1 ){
600
+ g.zRepositoryName = mprintf("%s", zRepository);
601
+ file_simplify_name(g.zRepositoryName, -1);
602
+ }else{
603
+ db_open_repository(zRepository);
604
+ }
605
+ db_close(0);
606
+ verify_all_options();
607
+ if( g.argc>4 ) fossil_fatal("to much arguments for create method.");
608
+ /* Build the fully-qualified path to the service binary file. */
609
+ blob_zero(&binPath);
610
+ blob_appendf(&binPath, "\"%s\" server", fossil_nameofexe());
611
+ if( zPort ) blob_appendf(&binPath, " --port %s", zPort);
612
+ if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound);
613
+ if( zLocalAuth ) blob_append(&binPath, " --localauth", -1);
614
+ blob_appendf(&binPath, " \"%s\"", g.zRepositoryName);
615
+ /* Create the service. */
616
+ hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
617
+ if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
618
+ hSvc = CreateService(
619
+ hScm, /* Handle to the SCM */
620
+ fossil_utf8_to_mbcs(zSvcName), /* Name of the service */
621
+ fossil_utf8_to_mbcs(zDisplay), /* Display name */
622
+ SERVICE_ALL_ACCESS, /* Desired access */
623
+ SERVICE_WIN32_OWN_PROCESS, /* Service type */
624
+ dwStartType, /* Start type */
625
+ SERVICE_ERROR_NORMAL, /* Error control */
626
+ fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */
627
+ NULL, /* Load ordering group */
628
+ NULL, /* Tag value */
629
+ NULL, /* Service dependencies */
630
+ fossil_utf8_to_mbcs(zUsername), /* Service account */
631
+ fossil_utf8_to_mbcs(zPassword) /* Account password */
632
+ );
633
+ if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
634
+ /* Set the service description. */
635
+ ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
636
+ fossil_print("Service '%s' successfully created.\n", zSvcName);
637
+ CloseServiceHandle(hSvc);
638
+ CloseServiceHandle(hScm);
639
+ }else
640
+ if( strncmp(zMethod, "delete", n)==0 ){
641
+ SC_HANDLE hScm;
642
+ SC_HANDLE hSvc;
643
+ SERVICE_STATUS sstat;
644
+ char *zErrFmt = "unable to delete service '%s': %s";
645
+
646
+ verify_all_options();
647
+ if( g.argc>4 ) fossil_fatal("to much arguments for delete method.");
648
+ hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
649
+ if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
650
+ hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
651
+ if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
652
+ QueryServiceStatus(hSvc, &sstat);
653
+ if( sstat.dwCurrentState!=SERVICE_STOPPED ){
654
+ fossil_print("Stopping service '%s'", zSvcName);
655
+ if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
656
+ if( !ControlService(hSvc, SERVICE_CONTROL_STOP, &sstat) ){
657
+ fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
658
+ }
659
+ }
660
+ while( sstat.dwCurrentState!=SERVICE_STOPPED ){
661
+ Sleep(100);
662
+ fossil_print(".");
663
+ QueryServiceStatus(hSvc, &sstat);
664
+ }
665
+ fossil_print("\nService '%s' stopped.\n", zSvcName);
666
+ }
667
+ if( !DeleteService(hSvc) ){
668
+ if( GetLastError()==ERROR_SERVICE_MARKED_FOR_DELETE ){
669
+ fossil_warning("Service '%s' already marked for delete.\n", zSvcName);
670
+ }else{
671
+ fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
672
+ }
673
+ }else{
674
+ fossil_print("Service '%s' successfully deleted.\n", zSvcName);
675
+ }
676
+ CloseServiceHandle(hSvc);
677
+ CloseServiceHandle(hScm);
678
+ }else
679
+ if( strncmp(zMethod, "show", n)==0 ){
680
+ SC_HANDLE hScm;
681
+ SC_HANDLE hSvc;
682
+ SERVICE_STATUS sstat;
683
+ LPQUERY_SERVICE_CONFIG pSvcConfig;
684
+ LPSERVICE_DESCRIPTION pSvcDescr;
685
+ BOOL bStatus;
686
+ DWORD nRequired;
687
+ char *zErrFmt = "unable to show service '%s': %s";
688
+ static const char *zSvcTypes[] = {
689
+ "Driver service",
690
+ "File system driver service",
691
+ "Service runs in its own process",
692
+ "Service shares a process with other services",
693
+ "Service can interact with the desktop"
694
+ };
695
+ const char *zSvcType = "";
696
+ static char *zSvcStartTypes[] = {
697
+ "Started by the system loader",
698
+ "Started by the IoInitSystem function",
699
+ "Started automatically by the service control manager",
700
+ "Started manually",
701
+ "Service cannot be started"
702
+ };
703
+ const char *zSvcStartType = "";
704
+ static const char *zSvcStates[] = {
705
+ "Stopped", "Starting", "Stopping", "Running",
706
+ "Continue pending", "Pause pending", "Paused"
707
+ };
708
+ const char *zSvcState = "";
709
+
710
+ verify_all_options();
711
+ if( g.argc>4 ) fossil_fatal("to much arguments for show method.");
712
+ hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
713
+ if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
714
+ hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ);
715
+ if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
716
+ /* Get the service configuration */
717
+ bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired);
718
+ if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
719
+ fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
720
+ }
721
+ pSvcConfig = fossil_malloc(nRequired);
722
+ bStatus = QueryServiceConfig(hSvc, pSvcConfig, nRequired, &nRequired);
723
+ if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
724
+ /* Translate the service type */
725
+ switch( pSvcConfig->dwServiceType ){
726
+ case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break;
727
+ case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break;
728
+ case SERVICE_WIN32_OWN_PROCESS: zSvcType = zSvcTypes[2]; break;
729
+ case SERVICE_WIN32_SHARE_PROCESS: zSvcType = zSvcTypes[3]; break;
730
+ case SERVICE_INTERACTIVE_PROCESS: zSvcType = zSvcTypes[4]; break;
731
+ }
732
+ /* Translate the service start type */
733
+ switch( pSvcConfig->dwStartType ){
734
+ case SERVICE_BOOT_START: zSvcStartType = zSvcStartTypes[0]; break;
735
+ case SERVICE_SYSTEM_START: zSvcStartType = zSvcStartTypes[1]; break;
736
+ case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break;
737
+ case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break;
738
+ case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break;
739
+ }
740
+ /* Get the service description. */
741
+ bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION,
742
+ NULL, 0, &nRequired);
743
+ if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
744
+ fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
745
+ }
746
+ pSvcDescr = fossil_malloc(nRequired);
747
+ bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION,
748
+ (LPBYTE)pSvcDescr, nRequired, &nRequired);
749
+ if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
750
+ /* Retrieves the current status of the specified service. */
751
+ bStatus = QueryServiceStatus(hSvc, &sstat);
752
+ if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
753
+ /* Translate the current state. */
754
+ switch( sstat.dwCurrentState ){
755
+ case SERVICE_STOPPED: zSvcState = zSvcStates[0]; break;
756
+ case SERVICE_START_PENDING: zSvcState = zSvcStates[1]; break;
757
+ case SERVICE_STOP_PENDING: zSvcState = zSvcStates[2]; break;
758
+ case SERVICE_RUNNING: zSvcState = zSvcStates[3]; break;
759
+ case SERVICE_CONTINUE_PENDING: zSvcState = zSvcStates[4]; break;
760
+ case SERVICE_PAUSE_PENDING: zSvcState = zSvcStates[5]; break;
761
+ case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break;
762
+ }
763
+ /* Print service information to terminal */
764
+ fossil_print("Service name .......: %s\n", zSvcName);
765
+ fossil_print("Display name .......: %s\n",
766
+ fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName));
767
+ fossil_print("Service description : %s\n",
768
+ fossil_mbcs_to_utf8(pSvcDescr->lpDescription));
769
+ fossil_print("Service type .......: %s.\n", zSvcType);
770
+ fossil_print("Service start type .: %s.\n", zSvcStartType);
771
+ fossil_print("Binary path name ...: %s\n",
772
+ fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName));
773
+ fossil_print("Service username ...: %s\n",
774
+ fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName));
775
+ fossil_print("Current state ......: %s.\n", zSvcState);
776
+ /* Cleanup */
777
+ fossil_free(pSvcConfig);
778
+ fossil_free(pSvcDescr);
779
+ CloseServiceHandle(hSvc);
780
+ CloseServiceHandle(hScm);
781
+ }else
782
+ if( strncmp(zMethod, "start", n)==0 ){
783
+ SC_HANDLE hScm;
784
+ SC_HANDLE hSvc;
785
+ SERVICE_STATUS sstat;
786
+ char *zErrFmt = "unable to start service '%s': %s";
787
+
788
+ verify_all_options();
789
+ if( g.argc>4 ) fossil_fatal("to much arguments for start method.");
790
+ hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
791
+ if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
792
+ hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
793
+ if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
794
+ QueryServiceStatus(hSvc, &sstat);
795
+ if( sstat.dwCurrentState!=SERVICE_RUNNING ){
796
+ fossil_print("Starting service '%s'", zSvcName);
797
+ if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
798
+ if( !StartService(hSvc, 0, NULL) ){
799
+ fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
800
+ }
801
+ }
802
+ while( sstat.dwCurrentState!=SERVICE_RUNNING ){
803
+ Sleep(100);
804
+ fossil_print(".");
805
+ QueryServiceStatus(hSvc, &sstat);
806
+ }
807
+ fossil_print("\nService '%s' started.\n", zSvcName);
808
+ }else{
809
+ fossil_print("Service '%s' is already started.\n", zSvcName);
810
+ }
811
+ CloseServiceHandle(hSvc);
812
+ CloseServiceHandle(hScm);
813
+ }else
814
+ if( strncmp(zMethod, "stop", n)==0 ){
815
+ SC_HANDLE hScm;
816
+ SC_HANDLE hSvc;
817
+ SERVICE_STATUS sstat;
818
+ char *zErrFmt = "unable to stop service '%s': %s";
819
+
820
+ verify_all_options();
821
+ if( g.argc>4 ) fossil_fatal("to much arguments for stop method.");
822
+ hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
823
+ if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
824
+ hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
825
+ if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
826
+ QueryServiceStatus(hSvc, &sstat);
827
+ if( sstat.dwCurrentState!=SERVICE_STOPPED ){
828
+ fossil_print("Stopping service '%s'", zSvcName);
829
+ if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
830
+ if( !ControlService(hSvc, SERVICE_CONTROL_STOP, &sstat) ){
831
+ fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
832
+ }
833
+ }
834
+ while( sstat.dwCurrentState!=SERVICE_STOPPED ){
835
+ Sleep(100);
836
+ fossil_print(".");
837
+ QueryServiceStatus(hSvc, &sstat);
838
+ }
839
+ fossil_print("\nService '%s' stopped.\n", zSvcName);
840
+ }else{
841
+ fossil_print("Service '%s' is already stopped.\n", zSvcName);
842
+ }
843
+ CloseServiceHandle(hSvc);
844
+ CloseServiceHandle(hScm);
845
+ }else
846
+ {
847
+ fossil_fatal("METHOD should be one of:"
848
+ " create delete show start stop");
849
+ }
850
+ return;
851
+}
852
+
853
+#else /* _WIN32 -- This code is for win32 only */
854
+#include "winhttp.h"
855
+
856
+void cmd_win32_service(void){
857
+ fossil_fatal("The winsrv command is platform specific "
858
+ "and not available on this platform.");
859
+ return;
860
+}
226861
227862
#endif /* _WIN32 -- This code is for win32 only */
228863
--- src/winhttp.c
+++ src/winhttp.c
@@ -14,17 +14,18 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file implements a very simple (and low-performance) HTTP server
19 ** for windows.
 
20 */
21 #include "config.h"
22 #ifdef _WIN32
23 /* This code is for win32 only */
24 #include "winhttp.h"
25 #include <windows.h>
 
26
27 /*
28 ** The HttpRequest structure holds information about each incoming
29 ** HTTP request.
30 */
@@ -60,11 +61,11 @@
60 }
61
62 /*
63 ** Process a single incoming HTTP request.
64 */
65 void win32_process_one_http_request(void *pAppData){
66 HttpRequest *p = (HttpRequest*)pAppData;
67 FILE *in = 0, *out = 0;
68 int amt, got;
69 int wanted = 0;
70 char *z;
@@ -145,10 +146,11 @@
145 SOCKET s = INVALID_SOCKET;
146 SOCKADDR_IN addr;
147 int idCnt = 0;
148 int iPort = mnPort;
149 Blob options;
 
150
151 if( zStopper ) file_delete(zStopper);
152 blob_zero(&options);
153 if( zNotFound ){
154 blob_appendf(&options, " --notfound %s", zNotFound);
@@ -189,31 +191,46 @@
189 }else{
190 fossil_fatal("unable to open listening socket on any"
191 " port in the range %d..%d", mnPort, mxPort);
192 }
193 }
194 zTempPrefix = mprintf("fossil_server_P%d_", iPort);
 
 
 
195 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
196 if( zBrowser ){
197 zBrowser = mprintf(zBrowser, iPort);
198 fossil_print("Launch webbrowser: %s\n", zBrowser);
199 fossil_system(zBrowser);
200 }
201 fossil_print("Type Ctrl-C to stop the HTTP server\n");
 
 
 
202 for(;;){
203 SOCKET client;
204 SOCKADDR_IN client_addr;
205 HttpRequest *p;
206 int len = sizeof(client_addr);
 
207
208 client = accept(s, (struct sockaddr*)&client_addr, &len);
209 if( zStopper && file_size(zStopper)>=0 ){
210 break;
211 }
212 if( client==INVALID_SOCKET ){
213 closesocket(s);
214 fossil_fatal("error from accept()");
 
 
 
 
 
 
 
 
 
 
 
215 }
216 p = fossil_malloc( sizeof(*p) );
217 p->id = ++idCnt;
218 p->s = client;
219 p->addr = client_addr;
@@ -221,7 +238,625 @@
221 _beginthread(win32_process_one_http_request, 0, (void*)p);
222 }
223 closesocket(s);
224 WSACleanup();
225 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
227 #endif /* _WIN32 -- This code is for win32 only */
228
--- src/winhttp.c
+++ src/winhttp.c
@@ -14,17 +14,18 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file implements a very simple (and low-performance) HTTP server
19 ** for windows. It also implements a Windows Service which allows the HTTP
20 ** server to be run without any user logged on.
21 */
22 #include "config.h"
23 #ifdef _WIN32
24 /* This code is for win32 only */
 
25 #include <windows.h>
26 #include "winhttp.h"
27
28 /*
29 ** The HttpRequest structure holds information about each incoming
30 ** HTTP request.
31 */
@@ -60,11 +61,11 @@
61 }
62
63 /*
64 ** Process a single incoming HTTP request.
65 */
66 static void win32_process_one_http_request(void *pAppData){
67 HttpRequest *p = (HttpRequest*)pAppData;
68 FILE *in = 0, *out = 0;
69 int amt, got;
70 int wanted = 0;
71 char *z;
@@ -145,10 +146,11 @@
146 SOCKET s = INVALID_SOCKET;
147 SOCKADDR_IN addr;
148 int idCnt = 0;
149 int iPort = mnPort;
150 Blob options;
151 char zTmpPath[MAX_PATH];
152
153 if( zStopper ) file_delete(zStopper);
154 blob_zero(&options);
155 if( zNotFound ){
156 blob_appendf(&options, " --notfound %s", zNotFound);
@@ -189,31 +191,46 @@
191 }else{
192 fossil_fatal("unable to open listening socket on any"
193 " port in the range %d..%d", mnPort, mxPort);
194 }
195 }
196 if( !GetTempPath(sizeof(zTmpPath), zTmpPath) ){
197 fossil_fatal("unable to get path to the temporary directory.");
198 }
199 zTempPrefix = mprintf("%sfossil_server_P%d_", zTmpPath, iPort);
200 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
201 if( zBrowser ){
202 zBrowser = mprintf(zBrowser, iPort);
203 fossil_print("Launch webbrowser: %s\n", zBrowser);
204 fossil_system(zBrowser);
205 }
206 fossil_print("Type Ctrl-C to stop the HTTP server\n");
207 /* Set the service status to running and pass the listener socket to the
208 ** service handling procedures. */
209 win32_http_service_running(s);
210 for(;;){
211 SOCKET client;
212 SOCKADDR_IN client_addr;
213 HttpRequest *p;
214 int len = sizeof(client_addr);
215 int wsaError;
216
217 client = accept(s, (struct sockaddr*)&client_addr, &len);
 
 
 
218 if( client==INVALID_SOCKET ){
219 /* If the service control handler has closed the listener socket,
220 ** cleanup and return, otherwise report a fatal error. */
221 wsaError = WSAGetLastError();
222 if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
223 WSACleanup();
224 return;
225 }else{
226 closesocket(s);
227 WSACleanup();
228 fossil_fatal("error from accept()");
229 }
230 }else if( zStopper && file_size(zStopper)>=0 ){
231 break;
232 }
233 p = fossil_malloc( sizeof(*p) );
234 p->id = ++idCnt;
235 p->s = client;
236 p->addr = client_addr;
@@ -221,7 +238,625 @@
238 _beginthread(win32_process_one_http_request, 0, (void*)p);
239 }
240 closesocket(s);
241 WSACleanup();
242 }
243
244 /*
245 ** The HttpService structure is used to pass information to the service main
246 ** function and to the service control handler function.
247 */
248 typedef struct HttpService HttpService;
249 struct HttpService {
250 int port; /* Port on which the http server should run */
251 const char *zNotFound; /* The --notfound option, or NULL */
252 int flags; /* One or more HTTP_SERVER_ flags */
253 int isRunningAsService; /* Are we running as a service ? */
254 const char *zServiceName; /* Name of the service */
255 SOCKET s; /* Socket on which the http server listens */
256 };
257
258 /*
259 ** Variables used for running as windows service.
260 */
261 static HttpService hsData = {8080, NULL, 0, 0, NULL, INVALID_SOCKET};
262 static SERVICE_STATUS ssStatus;
263 static SERVICE_STATUS_HANDLE sshStatusHandle;
264
265 /*
266 ** Get message string of the last system error. Return a pointer to the
267 ** message string. Call fossil_mbcs_free() to deallocate any memory used
268 ** to store the message string when done.
269 */
270 static char *win32_get_last_errmsg(void){
271 DWORD nMsg;
272 LPTSTR tmp = NULL;
273 char *zMsg = NULL;
274
275 nMsg = FormatMessage(
276 FORMAT_MESSAGE_ALLOCATE_BUFFER |
277 FORMAT_MESSAGE_FROM_SYSTEM |
278 FORMAT_MESSAGE_IGNORE_INSERTS,
279 NULL,
280 GetLastError(),
281 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
282 (LPTSTR) &tmp,
283 0,
284 NULL
285 );
286 if( nMsg ){
287 zMsg = fossil_mbcs_to_utf8(tmp);
288 }else{
289 fossil_fatal("unable to get system error message.");
290 }
291 if( tmp ){
292 LocalFree((HLOCAL) tmp);
293 }
294 return zMsg;
295 }
296
297 /*
298 ** Report the current status of the service to the service control manager.
299 ** Make sure that during service startup no control codes are accepted.
300 */
301 static void win32_report_service_status(
302 DWORD dwCurrentState, /* The current state of the service */
303 DWORD dwWin32ExitCode, /* The error code to report */
304 DWORD dwWaitHint /* The estimated time for a pending operation */
305 ){
306 if( dwCurrentState==SERVICE_START_PENDING) {
307 ssStatus.dwControlsAccepted = 0;
308 }else{
309 ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
310 }
311 ssStatus.dwCurrentState = dwCurrentState;
312 ssStatus.dwWin32ExitCode = dwWin32ExitCode;
313 ssStatus.dwWaitHint = dwWaitHint;
314
315 if( (dwCurrentState==SERVICE_RUNNING) ||
316 (dwCurrentState==SERVICE_STOPPED) ){
317 ssStatus.dwCheckPoint = 0;
318 }else{
319 ssStatus.dwCheckPoint++;
320 }
321 SetServiceStatus(sshStatusHandle, &ssStatus);
322 return ;
323 }
324
325 /*
326 ** Handle control codes sent from the service control manager.
327 ** The control dispatcher in the main thread of the service process invokes
328 ** this function whenever it receives a control request from the service
329 ** control manager.
330 */
331 static void WINAPI win32_http_service_ctrl(
332 DWORD dwCtrlCode
333 ){
334 switch( dwCtrlCode ){
335 case SERVICE_CONTROL_STOP: {
336 win32_report_service_status(SERVICE_STOP_PENDING, NO_ERROR, 0);
337 if( hsData.s != INVALID_SOCKET ){
338 closesocket(hsData.s);
339 }
340 win32_report_service_status(ssStatus.dwCurrentState, NO_ERROR, 0);
341 break;
342 }
343 default: {
344 break;
345 }
346 }
347 return;
348 }
349
350 /*
351 ** This is the main entry point for the service.
352 ** When the service control manager receives a request to start the service,
353 ** it starts the service process (if it is not already running). The main
354 ** thread of the service process calls the StartServiceCtrlDispatcher
355 ** function with a pointer to an array of SERVICE_TABLE_ENTRY structures.
356 ** Then the service control manager sends a start request to the service
357 ** control dispatcher for this service process. The service control dispatcher
358 ** creates a new thread to execute the ServiceMain function (this function)
359 ** of the service being started.
360 */
361 static void WINAPI win32_http_service_main(
362 DWORD argc, /* Number of arguments in argv */
363 LPTSTR *argv /* Arguments passed */
364 ){
365
366 /* Update the service information. */
367 hsData.isRunningAsService = 1;
368 if( argc>0 ){
369 hsData.zServiceName = argv[0];
370 }
371
372 /* Register the service control handler function */
373 sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl);
374 if( !sshStatusHandle ){
375 win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
376 return;
377 }
378
379 /* Set service specific data and report that the service is starting. */
380 ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
381 ssStatus.dwServiceSpecificExitCode = 0;
382 win32_report_service_status(SERVICE_START_PENDING, NO_ERROR, 3000);
383
384 /* Execute the http server */
385 win32_http_server(hsData.port, hsData.port,
386 NULL, NULL, hsData.zNotFound, hsData.flags);
387
388 /* Service has stopped now. */
389 win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
390 return;
391 }
392
393 /*
394 ** When running as service, update the HttpService structure with the
395 ** listener socket and update the service status. This procedure must be
396 ** called from the http server when he is ready to accept connections.
397 */
398 LOCAL void win32_http_service_running(SOCKET s){
399 if( hsData.isRunningAsService ){
400 hsData.s = s;
401 win32_report_service_status(SERVICE_RUNNING, NO_ERROR, 0);
402 }
403 }
404
405 /*
406 ** Try to start the http server as a windows service. If we are running in
407 ** a interactive console session, this routine fails and returns a non zero
408 ** integer value. When running as service, this routine does not return until
409 ** the service is stopped. In this case, the return value is zero.
410 */
411 int win32_http_service(
412 int nPort, /* TCP port number */
413 const char *zNotFound, /* The --notfound option, or NULL */
414 int flags /* One or more HTTP_SERVER_ flags */
415 ){
416 /* Define the service table. */
417 SERVICE_TABLE_ENTRY ServiceTable[] =
418 {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
419
420 /* Initialize the HttpService structure. */
421 hsData.port = nPort;
422 hsData.zNotFound = zNotFound;
423 hsData.flags = flags;
424
425 /* Try to start the control dispatcher thread for the service. */
426 if( !StartServiceCtrlDispatcher(ServiceTable) ){
427 if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
428 return 1;
429 }else{
430 fossil_fatal("error from StartServiceCtrlDispatcher()");
431 }
432 }
433 return 0;
434 }
435
436 /*
437 ** COMMAND: winsrv
438 ** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
439 **
440 ** Where METHOD is one of: create delete show start stop.
441 **
442 ** The winsrv command manages Fossil as a Windows service. This allows
443 ** (for example) Fossil to be running in the background when no user
444 ** is logged in.
445 **
446 ** In the following description of the methods, "Fossil-DSCM" will be
447 ** used as the default SERVICE-NAME:
448 **
449 ** fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
450 **
451 ** Creates a service. Available options include:
452 **
453 ** -D|--display DISPLAY-NAME
454 **
455 ** Sets the display name of the service. This name is shown
456 ** by graphical interface programs. By default, the display name
457 ** equals to the service name.
458 **
459 ** -S|--start TYPE
460 **
461 ** Sets the start type of the service. TYPE can be "manual",
462 ** which means you need to start the service yourself with the
463 ** 'fossil winsrv start' command or with the "net start" command
464 ** from the operating system. If TYPE is set to "auto", the service
465 ** will be started automatically by the system during startup.
466 **
467 ** -U|--username USERNAME
468 **
469 ** Specifies the user account which will be used to run the
470 ** service. The account needs the "Logon as a service" right
471 ** enabled in its profile. Specify local accounts as follows:
472 ** ".\\USERNAME". By default, the "LocalSystem" account will be
473 ** used.
474 **
475 ** -W|--password PASSWORD
476 **
477 ** Password for the user account.
478 **
479 ** The following options are more or less the same as for the "server"
480 ** command and influence the behaviour of the http server:
481 **
482 ** -p|--port TCPPORT
483 **
484 ** Specifies the TCP port (default port is 8080) on which the
485 ** server should listen.
486 **
487 ** -R|--repository REPOSITORY
488 **
489 ** Specifies the name of the repository to be served.
490 ** The repository option may be omitted if the working directory
491 ** is within an open checkout.
492 ** The REPOSITORY can be a directory (aka folder) that contains
493 ** one or more respositories with names ending in ".fossil".
494 ** In that case, the first element of the URL is used to select
495 ** among the various repositories.
496 **
497 ** --notfound URL
498 **
499 ** If REPOSITORY is a directory that contains one or more
500 ** respositories with names of the form "*.fossil" then the
501 ** first element of the URL pathname selects among the various
502 ** repositories. If the pathname does not select a valid
503 ** repository and the --notfound option is available,
504 ** then the server redirects (HTTP code 302) to the URL of
505 ** --notfound.
506 **
507 ** --localauth
508 **
509 ** Enables automatic login if the --localauth option is present
510 ** and the "localauth" setting is off and the connection is from
511 ** localhost.
512 **
513 **
514 ** fossil winsrv delete ?SERVICE-NAME?
515 **
516 ** Deletes a service. If the service is currently running, it will be
517 ** stopped first and then deleted.
518 **
519 **
520 ** fossil winsrv show ?SERVICE-NAME?
521 **
522 ** Shows how the service is configured and its current state.
523 **
524 **
525 ** fossil winsrv start ?SERVICE-NAME?
526 **
527 ** Start the service.
528 **
529 **
530 ** fossil winsrv stop ?SERVICE-NAME?
531 **
532 ** Stop the service.
533 **
534 **
535 ** NOTE: This command is available on Windows operating systems only and
536 ** requires administrative rights on the machine executed.
537 **
538 */
539 void cmd_win32_service(void){
540 int n;
541 const char *zMethod;
542 const char *zSvcName = "Fossil-DSCM"; /* Default service name */
543
544 if( g.argc<3 ){
545 usage("create|delete|show|start|stop ...");
546 }
547 zMethod = g.argv[2];
548 n = strlen(zMethod);
549 if( g.argc==4 ){
550 zSvcName = g.argv[3];
551 }
552
553 if( strncmp(zMethod, "create", n)==0 ){
554 SC_HANDLE hScm;
555 SC_HANDLE hSvc;
556 SERVICE_DESCRIPTION
557 svcDescr = {"Fossil - Distributed Software Configuration Management"};
558 char *zErrFmt = "unable to create service '%s': %s";
559 DWORD dwStartType = SERVICE_DEMAND_START;
560 const char *zDisplay;
561 const char *zStart;
562 const char *zUsername;
563 const char *zPassword;
564 const char *zPort;
565 const char *zNotFound;
566 const char *zLocalAuth;
567 const char *zRepository;
568 Blob binPath;
569
570 /* Process service creation specific options. */
571 zDisplay = find_option("display", "D", 1);
572 if( !zDisplay ){
573 zDisplay = zSvcName;
574 }
575 zStart = find_option("start", "S", 1);
576 if( zStart ){
577 if( strncmp(zStart, "auto", strlen(zStart))==0 ){
578 dwStartType = SERVICE_AUTO_START;
579 }else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
580 dwStartType = SERVICE_DEMAND_START;
581 }else{
582 fossil_fatal(zErrFmt, zSvcName,
583 "specify 'auto' or 'manual' for the '-S|--start' option");
584 }
585 }
586 zUsername = find_option("username", "U", 1);
587 zPassword = find_option("password", "W", 1);
588 /* Process options for Fossil running as server. */
589 zPort = find_option("port", "P", 1);
590 if( zPort && (atoi(zPort)<=0) ){
591 fossil_fatal(zErrFmt, zSvcName,
592 "port number must be in the range 1 - 65535.");
593 }
594 zNotFound = find_option("notfound", 0, 1);
595 zLocalAuth = find_option("localauth", 0, 0);
596 zRepository = find_option("repository", "R", 1);
597 if( !zRepository ){
598 db_must_be_within_tree();
599 }else if( file_isdir(zRepository)==1 ){
600 g.zRepositoryName = mprintf("%s", zRepository);
601 file_simplify_name(g.zRepositoryName, -1);
602 }else{
603 db_open_repository(zRepository);
604 }
605 db_close(0);
606 verify_all_options();
607 if( g.argc>4 ) fossil_fatal("to much arguments for create method.");
608 /* Build the fully-qualified path to the service binary file. */
609 blob_zero(&binPath);
610 blob_appendf(&binPath, "\"%s\" server", fossil_nameofexe());
611 if( zPort ) blob_appendf(&binPath, " --port %s", zPort);
612 if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound);
613 if( zLocalAuth ) blob_append(&binPath, " --localauth", -1);
614 blob_appendf(&binPath, " \"%s\"", g.zRepositoryName);
615 /* Create the service. */
616 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
617 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
618 hSvc = CreateService(
619 hScm, /* Handle to the SCM */
620 fossil_utf8_to_mbcs(zSvcName), /* Name of the service */
621 fossil_utf8_to_mbcs(zDisplay), /* Display name */
622 SERVICE_ALL_ACCESS, /* Desired access */
623 SERVICE_WIN32_OWN_PROCESS, /* Service type */
624 dwStartType, /* Start type */
625 SERVICE_ERROR_NORMAL, /* Error control */
626 fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */
627 NULL, /* Load ordering group */
628 NULL, /* Tag value */
629 NULL, /* Service dependencies */
630 fossil_utf8_to_mbcs(zUsername), /* Service account */
631 fossil_utf8_to_mbcs(zPassword) /* Account password */
632 );
633 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
634 /* Set the service description. */
635 ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
636 fossil_print("Service '%s' successfully created.\n", zSvcName);
637 CloseServiceHandle(hSvc);
638 CloseServiceHandle(hScm);
639 }else
640 if( strncmp(zMethod, "delete", n)==0 ){
641 SC_HANDLE hScm;
642 SC_HANDLE hSvc;
643 SERVICE_STATUS sstat;
644 char *zErrFmt = "unable to delete service '%s': %s";
645
646 verify_all_options();
647 if( g.argc>4 ) fossil_fatal("to much arguments for delete method.");
648 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
649 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
650 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
651 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
652 QueryServiceStatus(hSvc, &sstat);
653 if( sstat.dwCurrentState!=SERVICE_STOPPED ){
654 fossil_print("Stopping service '%s'", zSvcName);
655 if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
656 if( !ControlService(hSvc, SERVICE_CONTROL_STOP, &sstat) ){
657 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
658 }
659 }
660 while( sstat.dwCurrentState!=SERVICE_STOPPED ){
661 Sleep(100);
662 fossil_print(".");
663 QueryServiceStatus(hSvc, &sstat);
664 }
665 fossil_print("\nService '%s' stopped.\n", zSvcName);
666 }
667 if( !DeleteService(hSvc) ){
668 if( GetLastError()==ERROR_SERVICE_MARKED_FOR_DELETE ){
669 fossil_warning("Service '%s' already marked for delete.\n", zSvcName);
670 }else{
671 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
672 }
673 }else{
674 fossil_print("Service '%s' successfully deleted.\n", zSvcName);
675 }
676 CloseServiceHandle(hSvc);
677 CloseServiceHandle(hScm);
678 }else
679 if( strncmp(zMethod, "show", n)==0 ){
680 SC_HANDLE hScm;
681 SC_HANDLE hSvc;
682 SERVICE_STATUS sstat;
683 LPQUERY_SERVICE_CONFIG pSvcConfig;
684 LPSERVICE_DESCRIPTION pSvcDescr;
685 BOOL bStatus;
686 DWORD nRequired;
687 char *zErrFmt = "unable to show service '%s': %s";
688 static const char *zSvcTypes[] = {
689 "Driver service",
690 "File system driver service",
691 "Service runs in its own process",
692 "Service shares a process with other services",
693 "Service can interact with the desktop"
694 };
695 const char *zSvcType = "";
696 static char *zSvcStartTypes[] = {
697 "Started by the system loader",
698 "Started by the IoInitSystem function",
699 "Started automatically by the service control manager",
700 "Started manually",
701 "Service cannot be started"
702 };
703 const char *zSvcStartType = "";
704 static const char *zSvcStates[] = {
705 "Stopped", "Starting", "Stopping", "Running",
706 "Continue pending", "Pause pending", "Paused"
707 };
708 const char *zSvcState = "";
709
710 verify_all_options();
711 if( g.argc>4 ) fossil_fatal("to much arguments for show method.");
712 hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
713 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
714 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ);
715 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
716 /* Get the service configuration */
717 bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired);
718 if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
719 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
720 }
721 pSvcConfig = fossil_malloc(nRequired);
722 bStatus = QueryServiceConfig(hSvc, pSvcConfig, nRequired, &nRequired);
723 if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
724 /* Translate the service type */
725 switch( pSvcConfig->dwServiceType ){
726 case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break;
727 case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break;
728 case SERVICE_WIN32_OWN_PROCESS: zSvcType = zSvcTypes[2]; break;
729 case SERVICE_WIN32_SHARE_PROCESS: zSvcType = zSvcTypes[3]; break;
730 case SERVICE_INTERACTIVE_PROCESS: zSvcType = zSvcTypes[4]; break;
731 }
732 /* Translate the service start type */
733 switch( pSvcConfig->dwStartType ){
734 case SERVICE_BOOT_START: zSvcStartType = zSvcStartTypes[0]; break;
735 case SERVICE_SYSTEM_START: zSvcStartType = zSvcStartTypes[1]; break;
736 case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break;
737 case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break;
738 case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break;
739 }
740 /* Get the service description. */
741 bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION,
742 NULL, 0, &nRequired);
743 if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
744 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
745 }
746 pSvcDescr = fossil_malloc(nRequired);
747 bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION,
748 (LPBYTE)pSvcDescr, nRequired, &nRequired);
749 if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
750 /* Retrieves the current status of the specified service. */
751 bStatus = QueryServiceStatus(hSvc, &sstat);
752 if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
753 /* Translate the current state. */
754 switch( sstat.dwCurrentState ){
755 case SERVICE_STOPPED: zSvcState = zSvcStates[0]; break;
756 case SERVICE_START_PENDING: zSvcState = zSvcStates[1]; break;
757 case SERVICE_STOP_PENDING: zSvcState = zSvcStates[2]; break;
758 case SERVICE_RUNNING: zSvcState = zSvcStates[3]; break;
759 case SERVICE_CONTINUE_PENDING: zSvcState = zSvcStates[4]; break;
760 case SERVICE_PAUSE_PENDING: zSvcState = zSvcStates[5]; break;
761 case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break;
762 }
763 /* Print service information to terminal */
764 fossil_print("Service name .......: %s\n", zSvcName);
765 fossil_print("Display name .......: %s\n",
766 fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName));
767 fossil_print("Service description : %s\n",
768 fossil_mbcs_to_utf8(pSvcDescr->lpDescription));
769 fossil_print("Service type .......: %s.\n", zSvcType);
770 fossil_print("Service start type .: %s.\n", zSvcStartType);
771 fossil_print("Binary path name ...: %s\n",
772 fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName));
773 fossil_print("Service username ...: %s\n",
774 fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName));
775 fossil_print("Current state ......: %s.\n", zSvcState);
776 /* Cleanup */
777 fossil_free(pSvcConfig);
778 fossil_free(pSvcDescr);
779 CloseServiceHandle(hSvc);
780 CloseServiceHandle(hScm);
781 }else
782 if( strncmp(zMethod, "start", n)==0 ){
783 SC_HANDLE hScm;
784 SC_HANDLE hSvc;
785 SERVICE_STATUS sstat;
786 char *zErrFmt = "unable to start service '%s': %s";
787
788 verify_all_options();
789 if( g.argc>4 ) fossil_fatal("to much arguments for start method.");
790 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
791 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
792 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
793 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
794 QueryServiceStatus(hSvc, &sstat);
795 if( sstat.dwCurrentState!=SERVICE_RUNNING ){
796 fossil_print("Starting service '%s'", zSvcName);
797 if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
798 if( !StartService(hSvc, 0, NULL) ){
799 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
800 }
801 }
802 while( sstat.dwCurrentState!=SERVICE_RUNNING ){
803 Sleep(100);
804 fossil_print(".");
805 QueryServiceStatus(hSvc, &sstat);
806 }
807 fossil_print("\nService '%s' started.\n", zSvcName);
808 }else{
809 fossil_print("Service '%s' is already started.\n", zSvcName);
810 }
811 CloseServiceHandle(hSvc);
812 CloseServiceHandle(hScm);
813 }else
814 if( strncmp(zMethod, "stop", n)==0 ){
815 SC_HANDLE hScm;
816 SC_HANDLE hSvc;
817 SERVICE_STATUS sstat;
818 char *zErrFmt = "unable to stop service '%s': %s";
819
820 verify_all_options();
821 if( g.argc>4 ) fossil_fatal("to much arguments for stop method.");
822 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
823 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
824 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
825 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
826 QueryServiceStatus(hSvc, &sstat);
827 if( sstat.dwCurrentState!=SERVICE_STOPPED ){
828 fossil_print("Stopping service '%s'", zSvcName);
829 if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
830 if( !ControlService(hSvc, SERVICE_CONTROL_STOP, &sstat) ){
831 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
832 }
833 }
834 while( sstat.dwCurrentState!=SERVICE_STOPPED ){
835 Sleep(100);
836 fossil_print(".");
837 QueryServiceStatus(hSvc, &sstat);
838 }
839 fossil_print("\nService '%s' stopped.\n", zSvcName);
840 }else{
841 fossil_print("Service '%s' is already stopped.\n", zSvcName);
842 }
843 CloseServiceHandle(hSvc);
844 CloseServiceHandle(hScm);
845 }else
846 {
847 fossil_fatal("METHOD should be one of:"
848 " create delete show start stop");
849 }
850 return;
851 }
852
853 #else /* _WIN32 -- This code is for win32 only */
854 #include "winhttp.h"
855
856 void cmd_win32_service(void){
857 fossil_fatal("The winsrv command is platform specific "
858 "and not available on this platform.");
859 return;
860 }
861
862 #endif /* _WIN32 -- This code is for win32 only */
863
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -21,10 +21,11 @@
2121
<li> Linux x86
2222
<li> Linux x86_64
2323
<li> Mac x86
2424
<li> Mac x86_64
2525
<li> Windows (mingw)
26
+<li> Windows (vc++)
2627
<li> OpenBSD
2728
</ol>
2829
2930
<li><p>
3031
Run at least one occurrence of the the following commands on every
@@ -56,11 +57,16 @@
5657
5758
<li><p>
5859
Use the release candidate version of fossil in production on the
5960
[http://www.fossil-scm.org/] website for at least 48 hours (without
6061
incident) prior to making the release official.
62
+
63
+<li><p>
64
+Verify that the [../www/changes.wiki | Change Log] is correct and
65
+up-to-date.
6166
</ol>
6267
6368
<hr>
6469
6570
Upon successful completion of all tests above, tag the release candidate
66
-with the "release" tag and set its background color to "#d0c0ff".
71
+with the "release" tag and set its background color to "#d0c0ff". Update
72
+the www/changes.wiki file to show the date of the release.
6773
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -21,10 +21,11 @@
21 <li> Linux x86
22 <li> Linux x86_64
23 <li> Mac x86
24 <li> Mac x86_64
25 <li> Windows (mingw)
 
26 <li> OpenBSD
27 </ol>
28
29 <li><p>
30 Run at least one occurrence of the the following commands on every
@@ -56,11 +57,16 @@
56
57 <li><p>
58 Use the release candidate version of fossil in production on the
59 [http://www.fossil-scm.org/] website for at least 48 hours (without
60 incident) prior to making the release official.
 
 
 
 
61 </ol>
62
63 <hr>
64
65 Upon successful completion of all tests above, tag the release candidate
66 with the "release" tag and set its background color to "#d0c0ff".
 
67
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -21,10 +21,11 @@
21 <li> Linux x86
22 <li> Linux x86_64
23 <li> Mac x86
24 <li> Mac x86_64
25 <li> Windows (mingw)
26 <li> Windows (vc++)
27 <li> OpenBSD
28 </ol>
29
30 <li><p>
31 Run at least one occurrence of the the following commands on every
@@ -56,11 +57,16 @@
57
58 <li><p>
59 Use the release candidate version of fossil in production on the
60 [http://www.fossil-scm.org/] website for at least 48 hours (without
61 incident) prior to making the release official.
62
63 <li><p>
64 Verify that the [../www/changes.wiki | Change Log] is correct and
65 up-to-date.
66 </ol>
67
68 <hr>
69
70 Upon successful completion of all tests above, tag the release candidate
71 with the "release" tag and set its background color to "#d0c0ff". Update
72 the www/changes.wiki file to show the date of the release.
73
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -126,11 +126,11 @@
126126
# compiling standard fossil utils
127127
$(UTILS_OBJ): %.obj: $(SRCDIR)%.c
128128
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
129129
130130
# compile special windows utils
131
-version.obj: $(WINDIR)version.c
131
+version.obj: $(SRCDIR)mkversion.c
132132
$(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
133133
134134
# generate the translated c-source files
135135
$(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
136136
translate.exe $< >$@
@@ -138,12 +138,12 @@
138138
# generate the index source, containing all web references,..
139139
page_index.h: $(TRANSLATEDSRC) mkindex.exe
140140
mkindex.exe $(TRANSLATEDSRC) >$@
141141
142142
# extracting version info from manifest
143
-VERSION.h: version.exe ..\manifest.uuid ..\manifest
144
- version.exe ..\manifest.uuid ..\manifest > $@
143
+VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
144
+ version.exe ..\manifest.uuid ..\manifest ..\VERSION > $@
145145
146146
# generate the simplified headers
147147
headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h
148148
makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h
149149
echo Done >$@
150150
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -126,11 +126,11 @@
126 # compiling standard fossil utils
127 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
128 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
129
130 # compile special windows utils
131 version.obj: $(WINDIR)version.c
132 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
133
134 # generate the translated c-source files
135 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
136 translate.exe $< >$@
@@ -138,12 +138,12 @@
138 # generate the index source, containing all web references,..
139 page_index.h: $(TRANSLATEDSRC) mkindex.exe
140 mkindex.exe $(TRANSLATEDSRC) >$@
141
142 # extracting version info from manifest
143 VERSION.h: version.exe ..\manifest.uuid ..\manifest
144 version.exe ..\manifest.uuid ..\manifest > $@
145
146 # generate the simplified headers
147 headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h
148 makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h
149 echo Done >$@
150
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -126,11 +126,11 @@
126 # compiling standard fossil utils
127 $(UTILS_OBJ): %.obj: $(SRCDIR)%.c
128 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
129
130 # compile special windows utils
131 version.obj: $(SRCDIR)mkversion.c
132 $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@"
133
134 # generate the translated c-source files
135 $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe
136 translate.exe $< >$@
@@ -138,12 +138,12 @@
138 # generate the index source, containing all web references,..
139 page_index.h: $(TRANSLATEDSRC) mkindex.exe
140 mkindex.exe $(TRANSLATEDSRC) >$@
141
142 # extracting version info from manifest
143 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
144 version.exe ..\manifest.uuid ..\manifest ..\VERSION > $@
145
146 # generate the simplified headers
147 headers: makeheaders.exe page_index.h VERSION.h ../src/sqlite3.h ../src/th.h VERSION.h
148 makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/sqlite3.h ../src/th.h VERSION.h
149 echo Done >$@
150
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -20,11 +20,11 @@
2020
CFLAGS = -o
2121
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
2222
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2323
LIBS = $(DMDIR)\extra\lib\ zlib wsock32
2424
25
-SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
25
+SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
2626
2727
SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
2828
2929
OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3030
@@ -58,11 +58,11 @@
5858
$(BCC) -o$@ $**
5959
6060
mkindex$E: $(SRCDIR)\mkindex.c
6161
$(BCC) -o$@ $**
6262
63
-version$E: $B\win\version.c
63
+version$E: $B\src\mkversion.c
6464
$(BCC) -o$@ $**
6565
6666
$(OBJDIR)\shell$O : $(SRCDIR)\shell.c
6767
$(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
6868
@@ -73,11 +73,11 @@
7373
$(TCC) -o$@ -c $**
7474
7575
$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
7676
$(TCC) -o$@ -c $**
7777
78
-VERSION.h : version$E $B\manifest.uuid $B\manifest
78
+VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
7979
+$** > $@
8080
8181
page_index.h: mkindex$E $(SRC)
8282
+$** > $@
8383
@@ -84,11 +84,11 @@
8484
clean:
8585
-del $(OBJDIR)\*.obj
8686
-del *.obj *_.c *.h *.map
8787
8888
realclean:
89
- -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
89
+ -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
9090
9191
9292
$(OBJDIR)\add$O : add_.c add.h
9393
$(TCC) -o$@ -c add_.c
9494
9595
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -20,11 +20,11 @@
20 CFLAGS = -o
21 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
22 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
23 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
24
25 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
26
27 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
28
29 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
30
@@ -58,11 +58,11 @@
58 $(BCC) -o$@ $**
59
60 mkindex$E: $(SRCDIR)\mkindex.c
61 $(BCC) -o$@ $**
62
63 version$E: $B\win\version.c
64 $(BCC) -o$@ $**
65
66 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
67 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
68
@@ -73,11 +73,11 @@
73 $(TCC) -o$@ -c $**
74
75 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
76 $(TCC) -o$@ -c $**
77
78 VERSION.h : version$E $B\manifest.uuid $B\manifest
79 +$** > $@
80
81 page_index.h: mkindex$E $(SRC)
82 +$** > $@
83
@@ -84,11 +84,11 @@
84 clean:
85 -del $(OBJDIR)\*.obj
86 -del *.obj *_.c *.h *.map
87
88 realclean:
89 -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
90
91
92 $(OBJDIR)\add$O : add_.c add.h
93 $(TCC) -o$@ -c add_.c
94
95
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -20,11 +20,11 @@
20 CFLAGS = -o
21 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
22 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
23 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
24
25 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
26
27 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
28
29 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
30
@@ -58,11 +58,11 @@
58 $(BCC) -o$@ $**
59
60 mkindex$E: $(SRCDIR)\mkindex.c
61 $(BCC) -o$@ $**
62
63 version$E: $B\src\mkversion.c
64 $(BCC) -o$@ $**
65
66 $(OBJDIR)\shell$O : $(SRCDIR)\shell.c
67 $(TCC) -o$@ -c -Dmain=sqlite3_shell $(SQLITE_OPTIONS) $**
68
@@ -73,11 +73,11 @@
73 $(TCC) -o$@ -c $**
74
75 $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
76 $(TCC) -o$@ -c $**
77
78 VERSION.h : version$E $B\manifest.uuid $B\manifest $B\VERSION
79 +$** > $@
80
81 page_index.h: mkindex$E $(SRC)
82 +$** > $@
83
@@ -84,11 +84,11 @@
84 clean:
85 -del $(OBJDIR)\*.obj
86 -del *.obj *_.c *.h *.map
87
88 realclean:
89 -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
90
91
92 $(OBJDIR)\add$O : add_.c add.h
93 $(TCC) -o$@ -c add_.c
94
95
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -351,21 +351,21 @@
351351
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
352352
353353
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
354354
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
355355
356
-$(VERSION): $(SRCDIR)/../win/version.c
357
- $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
356
+$(VERSION): $(SRCDIR)/mkversion.c
357
+ $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
358358
359359
# WARNING. DANGER. Running the testsuite modifies the repository the
360360
# build is done from, i.e. the checkout belongs to. Do not sync/push
361361
# the repository after running the tests.
362362
test: $(APPNAME)
363363
$(TCLSH) test/tester.tcl $(APPNAME)
364364
365365
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
366
- $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest >$(OBJDIR)/VERSION.h
366
+ $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
367367
368368
EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
369369
370370
$(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
371371
$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.o
@@ -968,16 +968,16 @@
968968
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
969969
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
970970
971971
zip.h: $(OBJDIR)/headers
972972
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
973
- $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
973
+ $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
974974
975
-$(OBJDIR)/shell.o: $(SRCDIR)/shell.c
975
+$(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
976976
$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
977977
978978
$(OBJDIR)/th.o: $(SRCDIR)/th.c
979979
$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
980980
981981
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
982982
$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
983983
984984
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -351,21 +351,21 @@
351 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
352
353 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
354 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
355
356 $(VERSION): $(SRCDIR)/../win/version.c
357 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/../win/version.c
358
359 # WARNING. DANGER. Running the testsuite modifies the repository the
360 # build is done from, i.e. the checkout belongs to. Do not sync/push
361 # the repository after running the tests.
362 test: $(APPNAME)
363 $(TCLSH) test/tester.tcl $(APPNAME)
364
365 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
366 $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest >$(OBJDIR)/VERSION.h
367
368 EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
369
370 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
371 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.o
@@ -968,16 +968,16 @@
968 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
969 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
970
971 zip.h: $(OBJDIR)/headers
972 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
973 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
974
975 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c
976 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
977
978 $(OBJDIR)/th.o: $(SRCDIR)/th.c
979 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
980
981 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
982 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
983
984
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -351,21 +351,21 @@
351 $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
352
353 $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
354 $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
355
356 $(VERSION): $(SRCDIR)/mkversion.c
357 $(BCC) -o $(OBJDIR)/version $(SRCDIR)/mkversion.c
358
359 # WARNING. DANGER. Running the testsuite modifies the repository the
360 # build is done from, i.e. the checkout belongs to. Do not sync/push
361 # the repository after running the tests.
362 test: $(APPNAME)
363 $(TCLSH) test/tester.tcl $(APPNAME)
364
365 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
366 $(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
367
368 EXTRAOBJ = $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o
369
370 $(APPNAME): $(OBJDIR)/headers $(OBJ) $(EXTRAOBJ) $(OBJDIR)/icon.o
371 $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/icon.o
@@ -968,16 +968,16 @@
968 $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
969 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
970
971 zip.h: $(OBJDIR)/headers
972 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
973 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
974
975 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
976 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
977
978 $(OBJDIR)/th.o: $(SRCDIR)/th.c
979 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
980
981 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
982 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
983
984
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -31,14 +31,14 @@
3131
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
3232
3333
CFLAGS = -nologo -MT -O2
3434
BCC = $(CC) $(CFLAGS)
3535
TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
36
-LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
36
+LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
3737
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
3838
39
-SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT2 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
39
+SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT3 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
4040
4141
SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
4242
4343
OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
4444
@@ -153,11 +153,11 @@
153153
$(BCC) $**
154154
155155
mkindex$E: $(SRCDIR)\mkindex.c
156156
$(BCC) $**
157157
158
-version$E: $B\win\version.c
158
+mkversion$E: $B\src\mkversion.c
159159
$(BCC) $**
160160
161161
$(OX)\shell$O : $(SRCDIR)\shell.c
162162
$(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
163163
@@ -168,11 +168,11 @@
168168
$(TCC) /Fo$@ -c $**
169169
170170
$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
171171
$(TCC) /Fo$@ -c $**
172172
173
-VERSION.h : version$E $B\manifest.uuid $B\manifest
173
+VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
174174
$** > $@
175175
176176
page_index.h: mkindex$E $(SRC)
177177
$** > $@
178178
@@ -180,11 +180,11 @@
180180
-del $(OX)\*.obj
181181
-del *.obj *_.c *.h *.map
182182
-del headers linkopts
183183
184184
realclean:
185
- -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
185
+ -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
186186
187187
188188
$(OX)\add$O : add_.c add.h
189189
$(TCC) /Fo$@ -c add_.c
190190
191191
192192
DELETED win/version.c
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -31,14 +31,14 @@
31 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
32
33 CFLAGS = -nologo -MT -O2
34 BCC = $(CC) $(CFLAGS)
35 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
36 LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
37 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
38
39 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT2 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
40
41 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
42
43 OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
44
@@ -153,11 +153,11 @@
153 $(BCC) $**
154
155 mkindex$E: $(SRCDIR)\mkindex.c
156 $(BCC) $**
157
158 version$E: $B\win\version.c
159 $(BCC) $**
160
161 $(OX)\shell$O : $(SRCDIR)\shell.c
162 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
163
@@ -168,11 +168,11 @@
168 $(TCC) /Fo$@ -c $**
169
170 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
171 $(TCC) /Fo$@ -c $**
172
173 VERSION.h : version$E $B\manifest.uuid $B\manifest
174 $** > $@
175
176 page_index.h: mkindex$E $(SRC)
177 $** > $@
178
@@ -180,11 +180,11 @@
180 -del $(OX)\*.obj
181 -del *.obj *_.c *.h *.map
182 -del headers linkopts
183
184 realclean:
185 -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
186
187
188 $(OX)\add$O : add_.c add.h
189 $(TCC) /Fo$@ -c add_.c
190
191
192 ELETED win/version.c
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -31,14 +31,14 @@
31 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
32
33 CFLAGS = -nologo -MT -O2
34 BCC = $(CC) $(CFLAGS)
35 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
36 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
37 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
38
39 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT3 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
40
41 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
42
43 OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
44
@@ -153,11 +153,11 @@
153 $(BCC) $**
154
155 mkindex$E: $(SRCDIR)\mkindex.c
156 $(BCC) $**
157
158 mkversion$E: $B\src\mkversion.c
159 $(BCC) $**
160
161 $(OX)\shell$O : $(SRCDIR)\shell.c
162 $(TCC) /Fo$@ /Dmain=sqlite3_shell $(SQLITE_OPTIONS) -c $(SRCDIR)\shell.c
163
@@ -168,11 +168,11 @@
168 $(TCC) /Fo$@ -c $**
169
170 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
171 $(TCC) /Fo$@ -c $**
172
173 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
174 $** > $@
175
176 page_index.h: mkindex$E $(SRC)
177 $** > $@
178
@@ -180,11 +180,11 @@
180 -del $(OX)\*.obj
181 -del *.obj *_.c *.h *.map
182 -del headers linkopts
183
184 realclean:
185 -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
186
187
188 $(OX)\add$O : add_.c add.h
189 $(TCC) /Fo$@ -c add_.c
190
191
192 ELETED win/version.c
D win/version.c
-10
--- a/win/version.c
+++ b/win/version.c
@@ -1,10 +0,0 @@
1
-fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2
-** makefile - to extract information from the "mainfest" and "manifest.uuid"
3
-** files for this p)
4
- d = _MSC_VER / 1 return 0;
5
-}
6
-b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
7
-}
8
-;
9
- char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10
- fopen(argv[1
--- a/win/version.c
+++ b/win/version.c
@@ -1,10 +0,0 @@
1 fopen(argv[1],"gv[1],exists to do the job that AWK would do for the unix
2 ** makefile - to extract information from the "mainfest" and "manifest.uuid"
3 ** files for this p)
4 d = _MSC_VER / 1 return 0;
5 }
6 b2b2,0,sizeof(b2)strcpy(b2b2b2vx[1000]return 0;
7 }
8 ;
9 char b[1024b[strlen(b)-1] =0; return 0"gv[1],"fMSC_VER)
10 fopen(argv[1
--- a/win/version.c
+++ b/win/version.c
@@ -1,10 +0,0 @@
 
 
 
 
 
 
 
 
 
 
+63 -26
--- www/build.wiki
+++ www/build.wiki
@@ -1,16 +1,29 @@
11
<title>Building and Installing Fossil</title>
22
3
-<p>This page describes how to build and install Fossil. The
4
-whole process is designed to be very easy.</p>
5
-
63
<h2>0.0 Using A Pre-compiled Binary</h2>
74
8
-<p>You can skip steps 1.0 and 2.0 below by downloading
5
+<p>You can skip all of the following by downloading
96
a <a href="http://www.fossil-scm.org/download.html">pre-compiled binary</a>
10
-appropriate for your platform. If you use a pre-compiled binary
11
-jump immediate to step 3.0.</p>
7
+appropriate for your platform and putting that self-contained binary
8
+someplace on your $PATH.
9
+To uninstall, simply delete the binary.
10
+To upgrade from an older release, just overwrite the older binary with
11
+the newer one.</p>
12
+
13
+<h2>0.1 Executive Summary</h2>
14
+
15
+<p>Building and installing is very simple. Three steps:</p>
16
+
17
+<ol>
18
+<li> Download and unpack a source tarball or ZIP.
19
+<li> <b>./configure; make</b>
20
+<li> Move or copy the resulting "fossil" executable to someplace
21
+ on your $PATH.
22
+</ol>
23
+
24
+<p><hr>
1225
1326
<h2>1.0 Obtaining The Source Code</h2>
1427
1528
<p>Fossil is self-hosting, so you can obtain a ZIP archive containing
1629
a snapshot of the latest version directly from fossil's own fossil
@@ -33,42 +46,66 @@
3346
3447
<li><p>Select a version of of fossil you want to download. Click on its
3548
link. Note that you must successfully log in as "anonymous" in step 1
3649
above in order to see the link to the detailed version information.</p></li>
3750
38
-<li><p>Finally, click on the
39
-"Zip Archive" link. This link will build a ZIP archive of the
51
+<li><p>Finally, click on one of the
52
+"Zip Archive" or "Tarball" links, according to your preference.
53
+These link will build a ZIP archive or a gzip-compressed tarball of the
4054
complete source code and download it to your browser.
4155
</ol>
4256
4357
<h2>2.0 Compiling</h2>
4458
45
-<p>Follow these steps to compile on a unix platform
46
-(Linux, *BSD, MacOS, etc):</p>
47
-
4859
<ol>
4960
<li value="6">
50
-<p>Create a directory to hold the source code. Then unzip the
51
-ZIP archive you downloaded into that directory. You should be
61
+<p>Create a directory to hold the source code. Then unarchive the
62
+ZIP or tarball you downloaded into that directory. You should be
5263
in the top-level folder of that directory</p></li>
5364
54
-<li><p><b>(Optional:)</b>
55
-Edit the Makefile to set it up like you want. You probably do not
56
-need to do anything. Do not be intimidated: There are less than 10
57
-variables in the makefile that can be changed. The whole Makefile
58
-is only a few dozen lines long and most of those lines are comments.</p>
65
+<li><i>(Optional, unix only)</i>
66
+Run <b>./configure</b> to construct a makefile.
67
+
68
+<ol type="a">
69
+<li><p>
70
+If you do not have the OpenSSL library installed on your system, then
71
+add <b>--with-openssl=none</b> to omit the https functionality.
72
+
73
+<li><p>
74
+To build a statically linked binary (suitable for use inside a chroot
75
+jail) add the <b>--static</b> option.
76
+
77
+<li><p>
78
+Other configuration options can be seen by running
79
+<b>./configure --help</b>
80
+</ol>
81
+
82
+<li><p>Run make to build the "fossil" or "fossil.exe" executable. The
83
+details depend on your platform and compiler.
84
+
85
+<ol type="a">
86
+<li><p><i>Unix</i> &rarr; the configure-generated Makefile should work on
87
+all unix and unix-like systems. Simply type "<b>make</b>".
88
+
89
+<li><p><i>Unix without running "configure"</i> &rarr; if you prefer to avoid running configure, you
90
+can also use: <b>make -f Makefile.classic</b>. You may want to make minor
91
+edits to Makefile.classic to configure the build for your system.
92
+
93
+<li><p><i>Msys/MinGW</i> &rarr; Use the
94
+mingw makefile: "<b>make -f win/Makefile.mingw</b>"
5995
60
-<li><p>Type "<b>make</b>"
96
+<li><p><i>VC++</i> &rarr; Use the msc makefile. First
97
+change to the "win/" subdirectory ("<b>cd win</b>") then run
98
+"<b>nmake /f Makefile.msc</b>".
99
+</ol>
61100
</ol>
62101
63
-<p>To build on windows, use an alternative makefile suitable for your
64
-particular build environment. The alternative windows makefiles are
65
-all found in the win/ subdirectory of the source tree. So, for example,
66
-if you want build using the
67
-[http://www.mingw.org/ | mingw/msys compiler package] for windows, then
68
-run "<b>make -f win/Makefile.mingw</b>" instead of just "<b>make</b>"
69
-in step 8 above.</p>
102
+<p>Note that Fossil requires the "zlib" compression library. This library
103
+is available by default on most unix systems, but it will typically have to
104
+be installed separately on windows systems. For windows builds, you may
105
+need to edit the makefile to tell it exactly where zlib is located on your
106
+system.</p>
70107
71108
<h2>3.0 Installing</h2>
72109
73110
<ol>
74111
<li value="9">
75112
76113
ADDED www/changes.wiki
--- www/build.wiki
+++ www/build.wiki
@@ -1,16 +1,29 @@
1 <title>Building and Installing Fossil</title>
2
3 <p>This page describes how to build and install Fossil. The
4 whole process is designed to be very easy.</p>
5
6 <h2>0.0 Using A Pre-compiled Binary</h2>
7
8 <p>You can skip steps 1.0 and 2.0 below by downloading
9 a <a href="http://www.fossil-scm.org/download.html">pre-compiled binary</a>
10 appropriate for your platform. If you use a pre-compiled binary
11 jump immediate to step 3.0.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
13 <h2>1.0 Obtaining The Source Code</h2>
14
15 <p>Fossil is self-hosting, so you can obtain a ZIP archive containing
16 a snapshot of the latest version directly from fossil's own fossil
@@ -33,42 +46,66 @@
33
34 <li><p>Select a version of of fossil you want to download. Click on its
35 link. Note that you must successfully log in as "anonymous" in step 1
36 above in order to see the link to the detailed version information.</p></li>
37
38 <li><p>Finally, click on the
39 "Zip Archive" link. This link will build a ZIP archive of the
 
40 complete source code and download it to your browser.
41 </ol>
42
43 <h2>2.0 Compiling</h2>
44
45 <p>Follow these steps to compile on a unix platform
46 (Linux, *BSD, MacOS, etc):</p>
47
48 <ol>
49 <li value="6">
50 <p>Create a directory to hold the source code. Then unzip the
51 ZIP archive you downloaded into that directory. You should be
52 in the top-level folder of that directory</p></li>
53
54 <li><p><b>(Optional:)</b>
55 Edit the Makefile to set it up like you want. You probably do not
56 need to do anything. Do not be intimidated: There are less than 10
57 variables in the makefile that can be changed. The whole Makefile
58 is only a few dozen lines long and most of those lines are comments.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
60 <li><p>Type "<b>make</b>"
 
 
 
61 </ol>
62
63 <p>To build on windows, use an alternative makefile suitable for your
64 particular build environment. The alternative windows makefiles are
65 all found in the win/ subdirectory of the source tree. So, for example,
66 if you want build using the
67 [http://www.mingw.org/ | mingw/msys compiler package] for windows, then
68 run "<b>make -f win/Makefile.mingw</b>" instead of just "<b>make</b>"
69 in step 8 above.</p>
70
71 <h2>3.0 Installing</h2>
72
73 <ol>
74 <li value="9">
75
76 DDED www/changes.wiki
--- www/build.wiki
+++ www/build.wiki
@@ -1,16 +1,29 @@
1 <title>Building and Installing Fossil</title>
2
 
 
 
3 <h2>0.0 Using A Pre-compiled Binary</h2>
4
5 <p>You can skip all of the following by downloading
6 a <a href="http://www.fossil-scm.org/download.html">pre-compiled binary</a>
7 appropriate for your platform and putting that self-contained binary
8 someplace on your $PATH.
9 To uninstall, simply delete the binary.
10 To upgrade from an older release, just overwrite the older binary with
11 the newer one.</p>
12
13 <h2>0.1 Executive Summary</h2>
14
15 <p>Building and installing is very simple. Three steps:</p>
16
17 <ol>
18 <li> Download and unpack a source tarball or ZIP.
19 <li> <b>./configure; make</b>
20 <li> Move or copy the resulting "fossil" executable to someplace
21 on your $PATH.
22 </ol>
23
24 <p><hr>
25
26 <h2>1.0 Obtaining The Source Code</h2>
27
28 <p>Fossil is self-hosting, so you can obtain a ZIP archive containing
29 a snapshot of the latest version directly from fossil's own fossil
@@ -33,42 +46,66 @@
46
47 <li><p>Select a version of of fossil you want to download. Click on its
48 link. Note that you must successfully log in as "anonymous" in step 1
49 above in order to see the link to the detailed version information.</p></li>
50
51 <li><p>Finally, click on one of the
52 "Zip Archive" or "Tarball" links, according to your preference.
53 These link will build a ZIP archive or a gzip-compressed tarball of the
54 complete source code and download it to your browser.
55 </ol>
56
57 <h2>2.0 Compiling</h2>
58
 
 
 
59 <ol>
60 <li value="6">
61 <p>Create a directory to hold the source code. Then unarchive the
62 ZIP or tarball you downloaded into that directory. You should be
63 in the top-level folder of that directory</p></li>
64
65 <li><i>(Optional, unix only)</i>
66 Run <b>./configure</b> to construct a makefile.
67
68 <ol type="a">
69 <li><p>
70 If you do not have the OpenSSL library installed on your system, then
71 add <b>--with-openssl=none</b> to omit the https functionality.
72
73 <li><p>
74 To build a statically linked binary (suitable for use inside a chroot
75 jail) add the <b>--static</b> option.
76
77 <li><p>
78 Other configuration options can be seen by running
79 <b>./configure --help</b>
80 </ol>
81
82 <li><p>Run make to build the "fossil" or "fossil.exe" executable. The
83 details depend on your platform and compiler.
84
85 <ol type="a">
86 <li><p><i>Unix</i> &rarr; the configure-generated Makefile should work on
87 all unix and unix-like systems. Simply type "<b>make</b>".
88
89 <li><p><i>Unix without running "configure"</i> &rarr; if you prefer to avoid running configure, you
90 can also use: <b>make -f Makefile.classic</b>. You may want to make minor
91 edits to Makefile.classic to configure the build for your system.
92
93 <li><p><i>Msys/MinGW</i> &rarr; Use the
94 mingw makefile: "<b>make -f win/Makefile.mingw</b>"
95
96 <li><p><i>VC++</i> &rarr; Use the msc makefile. First
97 change to the "win/" subdirectory ("<b>cd win</b>") then run
98 "<b>nmake /f Makefile.msc</b>".
99 </ol>
100 </ol>
101
102 <p>Note that Fossil requires the "zlib" compression library. This library
103 is available by default on most unix systems, but it will typically have to
104 be installed separately on windows systems. For windows builds, you may
105 need to edit the makefile to tell it exactly where zlib is located on your
106 system.</p>
 
 
107
108 <h2>3.0 Installing</h2>
109
110 <ol>
111 <li value="9">
112
113 DDED www/changes.wiki
--- a/www/changes.wiki
+++ b/www/changes.wiki
@@ -0,0 +1 @@
1
+2-xxVarious minor bug fixepending
--- a/www/changes.wiki
+++ b/www/changes.wiki
@@ -0,0 +1 @@
 
--- a/www/changes.wiki
+++ b/www/changes.wiki
@@ -0,0 +1 @@
1 2-xxVarious minor bug fixepending
+80 -16
--- www/checkin.wiki
+++ www/checkin.wiki
@@ -1,21 +1,85 @@
1
-<title>Checkin Checklist</title>
1
+<title>Check-in Checklist</title>
2
+
3
+<h2><u>Always</u> run the following checklist prior to <u>every</u>
4
+check-in or commit to the Fossil repository:</h2>
5
+
6
+Before every check-in:
27
3
-Before every checkins:
8
+ 0. <b>fossil user default</b> &rarr; your username is correct.
49
5
- 1. <b>fossil diff</b> &rarr; no stray changes
10
+ 1. <b>fossil diff</b> &rarr;
11
+ <ol type="a">
12
+ <li> No stray changes
13
+ <li> All changes comply with the license
14
+ <li> All inputs are scrubbed before use
15
+ <li> No injection attacks via %s formats
16
+ </ol>
617
718
2. <b>fossil extra</b> &rarr; no unmanaged files need to be added.
819
9
- 3. The checkin will go onto the desired branch.
10
-
11
- 4. "Autosync" is enabled &rarr;
12
- <ol>
13
- <li> The checkin will not cause a unintentional fork.
14
- <li> The local system clock is set correctly.
15
- </ol>
16
-
17
-Before every checkin to <b>trunk</b>:
18
-
19
- 5. No compiler warnings on the development machine.
20
-
21
- 6. Changes will not cause problems on a future <b>bisect</b>.
20
+ 3. The check-in will go onto the desired branch.
21
+ &rarr; Do <u>not</u> check into trunk without prior approval from
22
+ the lead programmer (drh)!
23
+
24
+ 4. auto-sync is on, or the system clock is verified
25
+
26
+ 5. If sources files have been added or removed, ensure all makefiles
27
+ and configure scripts have been updated accordingly.
28
+
29
+Before every check-in to <b>trunk</b>:
30
+
31
+ 6. No compiler warnings on the development machine.
32
+
33
+ 7. The fossil executable that results from a build actually works.
34
+
35
+
36
+<hr>
37
+<h2>Commentary</h2>
38
+
39
+Before you go ahead and push content back to the servers, make sure
40
+that the username you are using by default matches your username
41
+within the project. Also remember to enable the localauth setting
42
+if you intend to make changes via a locally served web UI.
43
+
44
+Item 1 is the most important step. Consider using <b>gdiff</b>
45
+instead of <b>diff</b> if you have a graphical differ configured. Or,
46
+pipe the output of "<b>fossil diff</b>" into "<b>open -f</b>" (on a mac) to
47
+get the diff output in a separate text window for easier viewing.
48
+Look carefully at every changed line in item 1.
49
+Make sure that you are not about to commit unrelated changes.
50
+If there are two or more unrelated changes present, consider
51
+breaking up the commit into two or more separate commits.
52
+Always make 100% sure that all changes are compatible with the
53
+BSD license, that you have the authority to commit the code in accordance
54
+with the [/doc/trunk/www/copyright-release.html | CLA] that you have
55
+signed and have on file, and that
56
+no NDAs, copyrights, patents, or trademarks are infringed by the check-in.
57
+Also check very carefully to make sure that
58
+you are not introducing security vulnerabilities. Pay particular attention
59
+to the possibility of SQL or HTML injection attacks.
60
+
61
+Item 2 verifies that you have not added source files but failed to
62
+do the necessary "<b>fossil add</b>" to manage them. If you commit
63
+without bringing the new file under source control, the check-in will
64
+be broken. That, in turn, can cause complications far in the future
65
+when we are bisecting for a bug.
66
+
67
+For item 3, Run "<b>fossil status</b>" or the equivalent to
68
+make sure your changes are going into the branch you think they are.
69
+Also double-check the branch name when entering change comments.
70
+Never check into trunk unless you are expressly authorized to do so.
71
+
72
+For Item 4, if you are on-network, make sure auto-sync is enabled. This
73
+will minimize the risk of an unintended fork. It will also give you a
74
+warning if you system clock is set incorrectly. If you are off-network,
75
+make sure that your system clock is correct or at least close to correct
76
+so that your check-in does not appear out-of-sequence on timelines.
77
+On-network commits are preferred, especially for trunk commits.
78
+
79
+Items 6 and 7 help to ensure that check-ins on the trunk always work.
80
+Knowing that the trunk always works makes bisecting much easier. Items
81
+6 and 7 are recommended for all check-ins, even those that are on a branch.
82
+But they are especially important for trunk check-ins. We desire that
83
+all trunk check-ins work at all times. Any experimental, unstable, or
84
+questionable changes should go on a branch and be merged into trunk after
85
+further testing.
2286
2387
ADDED www/foss-cklist.wiki
--- www/checkin.wiki
+++ www/checkin.wiki
@@ -1,21 +1,85 @@
1 <title>Checkin Checklist</title>
 
 
 
 
 
2
3 Before every checkins:
4
5 1. <b>fossil diff</b> &rarr; no stray changes
 
 
 
 
 
 
6
7 2. <b>fossil extra</b> &rarr; no unmanaged files need to be added.
8
9 3. The checkin will go onto the desired branch.
10
11 4. "Autosync" is enabled &rarr;
12 <ol>
13 <li> The checkin will not cause a unintentional fork.
14 <li> The local system clock is set correctly.
15 </ol>
16
17 Before every checkin to <b>trunk</b>:
18
19 5. No compiler warnings on the development machine.
20
21 6. Changes will not cause problems on a future <b>bisect</b>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
23 DDED www/foss-cklist.wiki
--- www/checkin.wiki
+++ www/checkin.wiki
@@ -1,21 +1,85 @@
1 <title>Check-in Checklist</title>
2
3 <h2><u>Always</u> run the following checklist prior to <u>every</u>
4 check-in or commit to the Fossil repository:</h2>
5
6 Before every check-in:
7
8 0. <b>fossil user default</b> &rarr; your username is correct.
9
10 1. <b>fossil diff</b> &rarr;
11 <ol type="a">
12 <li> No stray changes
13 <li> All changes comply with the license
14 <li> All inputs are scrubbed before use
15 <li> No injection attacks via %s formats
16 </ol>
17
18 2. <b>fossil extra</b> &rarr; no unmanaged files need to be added.
19
20 3. The check-in will go onto the desired branch.
21 &rarr; Do <u>not</u> check into trunk without prior approval from
22 the lead programmer (drh)!
23
24 4. auto-sync is on, or the system clock is verified
25
26 5. If sources files have been added or removed, ensure all makefiles
27 and configure scripts have been updated accordingly.
28
29 Before every check-in to <b>trunk</b>:
30
31 6. No compiler warnings on the development machine.
32
33 7. The fossil executable that results from a build actually works.
34
35
36 <hr>
37 <h2>Commentary</h2>
38
39 Before you go ahead and push content back to the servers, make sure
40 that the username you are using by default matches your username
41 within the project. Also remember to enable the localauth setting
42 if you intend to make changes via a locally served web UI.
43
44 Item 1 is the most important step. Consider using <b>gdiff</b>
45 instead of <b>diff</b> if you have a graphical differ configured. Or,
46 pipe the output of "<b>fossil diff</b>" into "<b>open -f</b>" (on a mac) to
47 get the diff output in a separate text window for easier viewing.
48 Look carefully at every changed line in item 1.
49 Make sure that you are not about to commit unrelated changes.
50 If there are two or more unrelated changes present, consider
51 breaking up the commit into two or more separate commits.
52 Always make 100% sure that all changes are compatible with the
53 BSD license, that you have the authority to commit the code in accordance
54 with the [/doc/trunk/www/copyright-release.html | CLA] that you have
55 signed and have on file, and that
56 no NDAs, copyrights, patents, or trademarks are infringed by the check-in.
57 Also check very carefully to make sure that
58 you are not introducing security vulnerabilities. Pay particular attention
59 to the possibility of SQL or HTML injection attacks.
60
61 Item 2 verifies that you have not added source files but failed to
62 do the necessary "<b>fossil add</b>" to manage them. If you commit
63 without bringing the new file under source control, the check-in will
64 be broken. That, in turn, can cause complications far in the future
65 when we are bisecting for a bug.
66
67 For item 3, Run "<b>fossil status</b>" or the equivalent to
68 make sure your changes are going into the branch you think they are.
69 Also double-check the branch name when entering change comments.
70 Never check into trunk unless you are expressly authorized to do so.
71
72 For Item 4, if you are on-network, make sure auto-sync is enabled. This
73 will minimize the risk of an unintended fork. It will also give you a
74 warning if you system clock is set incorrectly. If you are off-network,
75 make sure that your system clock is correct or at least close to correct
76 so that your check-in does not appear out-of-sequence on timelines.
77 On-network commits are preferred, especially for trunk commits.
78
79 Items 6 and 7 help to ensure that check-ins on the trunk always work.
80 Knowing that the trunk always works makes bisecting much easier. Items
81 6 and 7 are recommended for all check-ins, even those that are on a branch.
82 But they are especially important for trunk check-ins. We desire that
83 all trunk check-ins work at all times. Any experimental, unstable, or
84 questionable changes should go on a branch and be merged into trunk after
85 further testing.
86
87 DDED www/foss-cklist.wiki
--- a/www/foss-cklist.wiki
+++ b/www/foss-cklist.wiki
@@ -0,0 +1,60 @@
1
+<title>Checklist For Successful Open-Source Projects</title>
2
+<nowiki>
3
+
4
+<p>This checklist is loosely derived from Tom "Spot" Callaway's Fail Score
5
+blog post <a href="http://spot.livejournal.com/308370.html">
6
+http://spot.livejournal.com/308370.html</a> (see also
7
+<a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and
8
+<a href="https://wwwHow_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a>).
9
+Tom's original post assigned point scores to the various elements and
10
+by adding together the individual points, the reader is suposed to be able
11
+to judge the likelihood that the project will fail.
12
+The point scores, and the items on the list, clearly reflect Tom's
13
+biases and are not necessarily those of the larger open-source community.
14
+Nevertheless, the policy of the Fossil shall be to strive for a perfect
15
+score.</p>
16
+
17
+<p>rive for a perfect
18
+score.
19
+
20
+This checklist is an inversion of Tom's original post in that it strives to
21
+say what the project should do in order to succeed rather than what it
22
+should not do to avoid failure. Th</p>
23
+
24
+<p>point values are omitted.
25
+
26
+See also:
27
+<ul>
28
+<li><a href="http://offog.org/articles/packaging/">
29
+http://offog.org/articles/packaging/</a>
30
+<li>
31
+<a href="http://www.gnu.org/prep/standards/standards.html#Managing-Releases">
32
+http://www.gnu.org/prep/standards/standards.html#Managing-Releases<p>The source code size is less than <p>The project uses a Version Control System (VCS).
33
+<ol type="a">
34
+<li>The VCS has a working web interface.
35
+<li>There is documentation on how to use the VCS.
36
+<li>The VCS is general-purpose, not something hacked together for this
37
+ <p>The project comes with documentation on how to build from source
38
+and that documentation is lucid, correct, and up-to-date.
39
+
40
+<li><p>The project is configurable using an autoconf-generated configure
41
+script, or the equivalent, and does not require:
42
+<ol type="a">
43
+<li>Manually editing flat files
44
+<li>Editing code header files
45
+</ol>
46
+
47
+<li><pes a Version les
48
+</ol>
49
+
50
+<li>The project should be buildable using commonly available and
51
+ standa<p Open-Source Projects</title>
52
+<nowiki>
53
+
54
+This checklist is loosely derive<t>The project is configurable using an autoconf-generated configure
55
+script, or the equivalent, and does not requir essful Open-Source Projects</title>
56
+<nowiki>
57
+
58
+<p>This checklist is loosely derived from Tom "Spot" Callaway's Fail Score
59
+blog post <a href="http://spot.livejournal.com/308370.html">
60
+http://sp
--- a/www/foss-cklist.wiki
+++ b/www/foss-cklist.wiki
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/foss-cklist.wiki
+++ b/www/foss-cklist.wiki
@@ -0,0 +1,60 @@
1 <title>Checklist For Successful Open-Source Projects</title>
2 <nowiki>
3
4 <p>This checklist is loosely derived from Tom "Spot" Callaway's Fail Score
5 blog post <a href="http://spot.livejournal.com/308370.html">
6 http://spot.livejournal.com/308370.html</a> (see also
7 <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and
8 <a href="https://wwwHow_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a>).
9 Tom's original post assigned point scores to the various elements and
10 by adding together the individual points, the reader is suposed to be able
11 to judge the likelihood that the project will fail.
12 The point scores, and the items on the list, clearly reflect Tom's
13 biases and are not necessarily those of the larger open-source community.
14 Nevertheless, the policy of the Fossil shall be to strive for a perfect
15 score.</p>
16
17 <p>rive for a perfect
18 score.
19
20 This checklist is an inversion of Tom's original post in that it strives to
21 say what the project should do in order to succeed rather than what it
22 should not do to avoid failure. Th</p>
23
24 <p>point values are omitted.
25
26 See also:
27 <ul>
28 <li><a href="http://offog.org/articles/packaging/">
29 http://offog.org/articles/packaging/</a>
30 <li>
31 <a href="http://www.gnu.org/prep/standards/standards.html#Managing-Releases">
32 http://www.gnu.org/prep/standards/standards.html#Managing-Releases<p>The source code size is less than <p>The project uses a Version Control System (VCS).
33 <ol type="a">
34 <li>The VCS has a working web interface.
35 <li>There is documentation on how to use the VCS.
36 <li>The VCS is general-purpose, not something hacked together for this
37 <p>The project comes with documentation on how to build from source
38 and that documentation is lucid, correct, and up-to-date.
39
40 <li><p>The project is configurable using an autoconf-generated configure
41 script, or the equivalent, and does not require:
42 <ol type="a">
43 <li>Manually editing flat files
44 <li>Editing code header files
45 </ol>
46
47 <li><pes a Version les
48 </ol>
49
50 <li>The project should be buildable using commonly available and
51 standa<p Open-Source Projects</title>
52 <nowiki>
53
54 This checklist is loosely derive<t>The project is configurable using an autoconf-generated configure
55 script, or the equivalent, and does not requir essful Open-Source Projects</title>
56 <nowiki>
57
58 <p>This checklist is loosely derived from Tom "Spot" Callaway's Fail Score
59 blog post <a href="http://spot.livejournal.com/308370.html">
60 http://sp
--- www/index.wiki
+++ www/index.wiki
@@ -20,10 +20,12 @@
2020
<li> [./quickstart.wiki | Quick Start]
2121
<li> [./build.wiki | Install]
2222
<li> [../COPYRIGHT-BSD2.txt | License]
2323
<li> [/timeline | Recent changes]
2424
<li> [./faq.wiki | FAQ]
25
+<li> [./contribute.wiki | Contributing]
26
+<li> [./changes.wiki | Change Log]
2527
<li> [./permutedindex.wiki | Doc Index]
2628
<li> Mailing list
2729
<ul>
2830
<li> [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | sign-up]
2931
<li> [http://www.mail-archive.com/[email protected] | archives]
@@ -125,10 +127,12 @@
125127
* The [./selfcheck.wiki | automatic self-check] mechanism
126128
helps insure project integrity.
127129
* Fossil contains a [./wikitheory.wiki | built-in wiki].
128130
* An [./event.wiki | Event] is a special kind of wiki page associated
129131
with a point in time rather than a name.
132
+ * [./settings.wiki | Settings] control the behaviour of fossil.
133
+ * [./ssl.wiki | Use SSL] to encrypt communication with the server.
130134
* There is a
131135
[http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable
132136
[http://www.mail-archive.com/[email protected] | archives]
133137
available for discussing fossil issues.
134138
* [./stats.wiki | Performance statistics] taken from real-world projects
135139
--- www/index.wiki
+++ www/index.wiki
@@ -20,10 +20,12 @@
20 <li> [./quickstart.wiki | Quick Start]
21 <li> [./build.wiki | Install]
22 <li> [../COPYRIGHT-BSD2.txt | License]
23 <li> [/timeline | Recent changes]
24 <li> [./faq.wiki | FAQ]
 
 
25 <li> [./permutedindex.wiki | Doc Index]
26 <li> Mailing list
27 <ul>
28 <li> [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | sign-up]
29 <li> [http://www.mail-archive.com/[email protected] | archives]
@@ -125,10 +127,12 @@
125 * The [./selfcheck.wiki | automatic self-check] mechanism
126 helps insure project integrity.
127 * Fossil contains a [./wikitheory.wiki | built-in wiki].
128 * An [./event.wiki | Event] is a special kind of wiki page associated
129 with a point in time rather than a name.
 
 
130 * There is a
131 [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable
132 [http://www.mail-archive.com/[email protected] | archives]
133 available for discussing fossil issues.
134 * [./stats.wiki | Performance statistics] taken from real-world projects
135
--- www/index.wiki
+++ www/index.wiki
@@ -20,10 +20,12 @@
20 <li> [./quickstart.wiki | Quick Start]
21 <li> [./build.wiki | Install]
22 <li> [../COPYRIGHT-BSD2.txt | License]
23 <li> [/timeline | Recent changes]
24 <li> [./faq.wiki | FAQ]
25 <li> [./contribute.wiki | Contributing]
26 <li> [./changes.wiki | Change Log]
27 <li> [./permutedindex.wiki | Doc Index]
28 <li> Mailing list
29 <ul>
30 <li> [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | sign-up]
31 <li> [http://www.mail-archive.com/[email protected] | archives]
@@ -125,10 +127,12 @@
127 * The [./selfcheck.wiki | automatic self-check] mechanism
128 helps insure project integrity.
129 * Fossil contains a [./wikitheory.wiki | built-in wiki].
130 * An [./event.wiki | Event] is a special kind of wiki page associated
131 with a point in time rather than a name.
132 * [./settings.wiki | Settings] control the behaviour of fossil.
133 * [./ssl.wiki | Use SSL] to encrypt communication with the server.
134 * There is a
135 [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable
136 [http://www.mail-archive.com/[email protected] | archives]
137 available for discussing fossil issues.
138 * [./stats.wiki | Performance statistics] taken from real-world projects
139
+21 -15
--- www/makefile.wiki
+++ www/makefile.wiki
@@ -52,29 +52,34 @@
5252
7. th.c
5353
8. th.h
5454
5555
These two files are imports like the SQLite source files,
5656
and so are not preprocessed.
57
+
58
+The VERSION.h header file is generated from other information sources
59
+using a small program called:
60
+
61
+ 9. mkversion.c
5762
5863
The src/ subdirectory also contains documentation about the
5964
makeheaders preprocessor program:
6065
61
- 9. [../src/makeheaders.html | makeheaders.html]
66
+ 10. [../src/makeheaders.html | makeheaders.html]
6267
6368
Click on the link to read this documentation. In addition there is
6469
a [http://www.tcl.tk/ | Tcl] script used to build the various makefiles:
6570
66
- 10. makemake.tcl
71
+ 11. makemake.tcl
6772
6873
Running this Tcl script will automatically regenerate all makefiles.
6974
In order to add a new source file to the Fossil implementation, simply
7075
edit makemake.tcl to add the new filename, then rerun the script, and
7176
all of the makefiles for all targets will be rebuild.
7277
7378
Finally, there is one of the makefiles generated by makemake.tcl:
7479
75
- 11. main.mk
80
+ 12. main.mk
7681
7782
The main.mk makefile is invoked from the Makefile in the top-level
7883
directory. The main.mk is generated by makemake.tcl and should not
7984
be hand edited. Other makefiles generated by makemake.tcl are in
8085
other subdirectories (currently all in the win/ subdirectory).
@@ -89,31 +94,32 @@
8994
9095
<h1>3.0 Automatically generated files</h1>
9196
9297
The "VERSION.h" header file contains some C preprocessor macros that
9398
identify the version of Fossil that is to be build. The VERSION.h file is
94
-generated automatically from information extracted from the "manifest"
95
-and "manifest.uuid" source files in the root directory of the source tree.
99
+generated automatically from information extracted from the "manifest",
100
+"manifest.uuid", and "VERSION" source files in the root directory of the
101
+source tree.
96102
(The "manifest" and "manifest.uuid" files are automatically generated and
97103
updated by Fossil itself. See the [/help/setting | fossil set manifest]
98104
command for additional information.)
99105
100
-Under unix, there is an AWK script that converts manifest and manifest.uuid
101
-into VERSION.h. For windows, there is a C program: win/version.c.
102
-(Unix builds could also used the version.c convert, if desired, but AWK
103
-seems easier there.) To run the VERSION.h generator, first compile
104
-the win/version.c source file into a command-line program (named "version.exe")
106
+The VERSION.h header file is generated by
107
+a C program: src/mkversion.c.
108
+To run the VERSION.h generator, first compile the src/mkversion.c
109
+ source file into a command-line program (named "mkversion.exe")
105110
than run:
106111
107112
<blockquote><pre>
108
-version.exe manifest.uuid manifest VERSION.h
113
+mkversion.exe manifest.uuid manifest VERSION &gt;VERSION.h
109114
</pre></blockquote>
110115
111116
The pathnames in the above command might need to be adjusted to get the
112
-directories right. The point is that the manifest.uuid and manifest files
113
-in the root of the source tree are the first two arguments and the name of
114
-the generated VERSION.h file is the third and final argument.
117
+directories right. The point is that the manifest.uuid, manifest, and
118
+VERSION files
119
+in the root of the source tree are the three arguments and
120
+the generated VERSION.h file appears on standard output.
115121
116122
<h1>4.0 Preprocessing</h1>
117123
118124
There are three preprocessors for the Fossil sources. The mkindex
119125
and translate preprocessors can be run in any order. The makeheaders
@@ -120,11 +126,11 @@
120126
preprocessor must be run after translate.
121127
122128
<h2>4.1 The mkindex preprocessor</h2>
123129
124130
The mkindex program scans the "src.c" source files looking for special
125
-comments that identify routines that implement of various Fossil commands,
131
+comments that identify routines that implement various Fossil commands,
126132
web interface methods, and help text comments. The mkindex program
127133
generates some C code that Fossil uses in order to dispatch commands and
128134
HTTP requests and to show on-line help. Compile the mkindex program
129135
from the mkindex.c source file. Then run:
130136
131137
--- www/makefile.wiki
+++ www/makefile.wiki
@@ -52,29 +52,34 @@
52 7. th.c
53 8. th.h
54
55 These two files are imports like the SQLite source files,
56 and so are not preprocessed.
 
 
 
 
 
57
58 The src/ subdirectory also contains documentation about the
59 makeheaders preprocessor program:
60
61 9. [../src/makeheaders.html | makeheaders.html]
62
63 Click on the link to read this documentation. In addition there is
64 a [http://www.tcl.tk/ | Tcl] script used to build the various makefiles:
65
66 10. makemake.tcl
67
68 Running this Tcl script will automatically regenerate all makefiles.
69 In order to add a new source file to the Fossil implementation, simply
70 edit makemake.tcl to add the new filename, then rerun the script, and
71 all of the makefiles for all targets will be rebuild.
72
73 Finally, there is one of the makefiles generated by makemake.tcl:
74
75 11. main.mk
76
77 The main.mk makefile is invoked from the Makefile in the top-level
78 directory. The main.mk is generated by makemake.tcl and should not
79 be hand edited. Other makefiles generated by makemake.tcl are in
80 other subdirectories (currently all in the win/ subdirectory).
@@ -89,31 +94,32 @@
89
90 <h1>3.0 Automatically generated files</h1>
91
92 The "VERSION.h" header file contains some C preprocessor macros that
93 identify the version of Fossil that is to be build. The VERSION.h file is
94 generated automatically from information extracted from the "manifest"
95 and "manifest.uuid" source files in the root directory of the source tree.
 
96 (The "manifest" and "manifest.uuid" files are automatically generated and
97 updated by Fossil itself. See the [/help/setting | fossil set manifest]
98 command for additional information.)
99
100 Under unix, there is an AWK script that converts manifest and manifest.uuid
101 into VERSION.h. For windows, there is a C program: win/version.c.
102 (Unix builds could also used the version.c convert, if desired, but AWK
103 seems easier there.) To run the VERSION.h generator, first compile
104 the win/version.c source file into a command-line program (named "version.exe")
105 than run:
106
107 <blockquote><pre>
108 version.exe manifest.uuid manifest VERSION.h
109 </pre></blockquote>
110
111 The pathnames in the above command might need to be adjusted to get the
112 directories right. The point is that the manifest.uuid and manifest files
113 in the root of the source tree are the first two arguments and the name of
114 the generated VERSION.h file is the third and final argument.
 
115
116 <h1>4.0 Preprocessing</h1>
117
118 There are three preprocessors for the Fossil sources. The mkindex
119 and translate preprocessors can be run in any order. The makeheaders
@@ -120,11 +126,11 @@
120 preprocessor must be run after translate.
121
122 <h2>4.1 The mkindex preprocessor</h2>
123
124 The mkindex program scans the "src.c" source files looking for special
125 comments that identify routines that implement of various Fossil commands,
126 web interface methods, and help text comments. The mkindex program
127 generates some C code that Fossil uses in order to dispatch commands and
128 HTTP requests and to show on-line help. Compile the mkindex program
129 from the mkindex.c source file. Then run:
130
131
--- www/makefile.wiki
+++ www/makefile.wiki
@@ -52,29 +52,34 @@
52 7. th.c
53 8. th.h
54
55 These two files are imports like the SQLite source files,
56 and so are not preprocessed.
57
58 The VERSION.h header file is generated from other information sources
59 using a small program called:
60
61 9. mkversion.c
62
63 The src/ subdirectory also contains documentation about the
64 makeheaders preprocessor program:
65
66 10. [../src/makeheaders.html | makeheaders.html]
67
68 Click on the link to read this documentation. In addition there is
69 a [http://www.tcl.tk/ | Tcl] script used to build the various makefiles:
70
71 11. makemake.tcl
72
73 Running this Tcl script will automatically regenerate all makefiles.
74 In order to add a new source file to the Fossil implementation, simply
75 edit makemake.tcl to add the new filename, then rerun the script, and
76 all of the makefiles for all targets will be rebuild.
77
78 Finally, there is one of the makefiles generated by makemake.tcl:
79
80 12. main.mk
81
82 The main.mk makefile is invoked from the Makefile in the top-level
83 directory. The main.mk is generated by makemake.tcl and should not
84 be hand edited. Other makefiles generated by makemake.tcl are in
85 other subdirectories (currently all in the win/ subdirectory).
@@ -89,31 +94,32 @@
94
95 <h1>3.0 Automatically generated files</h1>
96
97 The "VERSION.h" header file contains some C preprocessor macros that
98 identify the version of Fossil that is to be build. The VERSION.h file is
99 generated automatically from information extracted from the "manifest",
100 "manifest.uuid", and "VERSION" source files in the root directory of the
101 source tree.
102 (The "manifest" and "manifest.uuid" files are automatically generated and
103 updated by Fossil itself. See the [/help/setting | fossil set manifest]
104 command for additional information.)
105
106 The VERSION.h header file is generated by
107 a C program: src/mkversion.c.
108 To run the VERSION.h generator, first compile the src/mkversion.c
109 source file into a command-line program (named "mkversion.exe")
 
110 than run:
111
112 <blockquote><pre>
113 mkversion.exe manifest.uuid manifest VERSION &gt;VERSION.h
114 </pre></blockquote>
115
116 The pathnames in the above command might need to be adjusted to get the
117 directories right. The point is that the manifest.uuid, manifest, and
118 VERSION files
119 in the root of the source tree are the three arguments and
120 the generated VERSION.h file appears on standard output.
121
122 <h1>4.0 Preprocessing</h1>
123
124 There are three preprocessors for the Fossil sources. The mkindex
125 and translate preprocessors can be run in any order. The makeheaders
@@ -120,11 +126,11 @@
126 preprocessor must be run after translate.
127
128 <h2>4.1 The mkindex preprocessor</h2>
129
130 The mkindex program scans the "src.c" source files looking for special
131 comments that identify routines that implement various Fossil commands,
132 web interface methods, and help text comments. The mkindex program
133 generates some C code that Fossil uses in order to dispatch commands and
134 HTTP requests and to show on-line help. Compile the mkindex program
135 from the mkindex.c source file. Then run:
136
137
+11 -6
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -9,10 +9,11 @@
99
set doclist {
1010
bugtheory.wiki {Bug Tracking In Fossil}
1111
branching.wiki {Branching, Forking, Merging, and Tagging}
1212
build.wiki {Building and Installing Fossil}
1313
checkin_names.wiki {Checkin And Version Names}
14
+ changes.wiki {Fossil Changelog}
1415
copyright-release.html {Contributor License Agreement}
1516
concepts.wiki {Fossil Core Concepts}
1617
contribute.wiki {Contributing Code or Documentation To The Fossil Project}
1718
custom_ticket.wiki {Customizing The Ticket System}
1819
delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
@@ -19,10 +20,11 @@
1920
delta_format.wiki {Fossil Delta Format}
2021
embeddeddoc.wiki {Embedded Project Documentation}
2122
event.wiki {Events}
2223
faq.wiki {Frequently Asked Questions}
2324
fileformat.wiki {Fossil File Format}
25
+ foss-cklist.wiki {Checklist For Successful Open-Source Projects}
2426
fossil-v-git.wiki {Fossil Versus Git}
2527
index.wiki {Home Page}
2628
inout.wiki {Import And Export To And From Git}
2729
makefile.wiki {The Fossil Build Process}
2830
password.wiki {Password Management And Authentication}
@@ -34,13 +36,15 @@
3436
{Quotes: What People Are Saying About Fossil, Git, and DVCSes in General}
3537
../test/release-checklist.wiki {Pre-Release Testing Checklist}
3638
selfcheck.wiki {Fossil Repository Integrity Self Checks}
3739
selfhost.wiki {Fossil Self Hosting Repositories}
3840
server.wiki {How To Configure A Fossil Server}
41
+ settings.wiki {Fossil Settings}
3942
shunning.wiki {Shunning: Deleting Content From Fossil}
4043
stats.wiki {Performance Statistics}
4144
style.wiki {Source Code Style Guidelines}
45
+ ssl.wiki {Using SSL with Fossil}
4246
sync.wiki {The Fossil Sync Protocol}
4347
tech_overview.wiki {A Technical Overview Of The Design And Implementation
4448
Of Fossil}
4549
tech_overview.wiki {SQLite Databases Used By Fossil}
4650
theory1.wiki {Thoughts On The Design Of The Fossil DVCS}
@@ -47,11 +51,11 @@
4751
webui.wiki {The Fossil Web Interface}
4852
wikitheory.wiki {Wiki In Fossil}
4953
}
5054
5155
set permindex {}
52
-set stopwords {fossil and a in of on the to are about used by}
56
+set stopwords {fossil and a in of on the to are about used by for or}
5357
foreach {file title} $doclist {
5458
set n [llength $title]
5559
lappend permindex [list $title $file]
5660
for {set i 0} {$i<$n-1} {incr i} {
5761
set prefix [lrange $title 0 $i]
@@ -61,13 +65,14 @@
6165
lappend permindex [list "$suffix &#151; $prefix" $file]
6266
}
6367
}
6468
}
6569
set permindex [lsort -dict $permindex]
66
-puts "<title>Permuted Index Of Fossil Documentation</title>"
67
-puts "<nowiki>"
68
-puts "<ul>"
70
+set out [open permutedindex.wiki w]
71
+puts $out "<title>Permuted Index Of Fossil Documentation</title>"
72
+puts $out "<nowiki>"
73
+puts $out "<ul>"
6974
foreach entry $permindex {
7075
foreach {title file} $entry break
71
- puts "<li><a href=\"$file\">$title</a></li>"
76
+ puts $out "<li><a href=\"$file\">$title</a></li>"
7277
}
73
-puts "</ul>"
78
+puts $out "</ul>"
7479
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -9,10 +9,11 @@
9 set doclist {
10 bugtheory.wiki {Bug Tracking In Fossil}
11 branching.wiki {Branching, Forking, Merging, and Tagging}
12 build.wiki {Building and Installing Fossil}
13 checkin_names.wiki {Checkin And Version Names}
 
14 copyright-release.html {Contributor License Agreement}
15 concepts.wiki {Fossil Core Concepts}
16 contribute.wiki {Contributing Code or Documentation To The Fossil Project}
17 custom_ticket.wiki {Customizing The Ticket System}
18 delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
@@ -19,10 +20,11 @@
19 delta_format.wiki {Fossil Delta Format}
20 embeddeddoc.wiki {Embedded Project Documentation}
21 event.wiki {Events}
22 faq.wiki {Frequently Asked Questions}
23 fileformat.wiki {Fossil File Format}
 
24 fossil-v-git.wiki {Fossil Versus Git}
25 index.wiki {Home Page}
26 inout.wiki {Import And Export To And From Git}
27 makefile.wiki {The Fossil Build Process}
28 password.wiki {Password Management And Authentication}
@@ -34,13 +36,15 @@
34 {Quotes: What People Are Saying About Fossil, Git, and DVCSes in General}
35 ../test/release-checklist.wiki {Pre-Release Testing Checklist}
36 selfcheck.wiki {Fossil Repository Integrity Self Checks}
37 selfhost.wiki {Fossil Self Hosting Repositories}
38 server.wiki {How To Configure A Fossil Server}
 
39 shunning.wiki {Shunning: Deleting Content From Fossil}
40 stats.wiki {Performance Statistics}
41 style.wiki {Source Code Style Guidelines}
 
42 sync.wiki {The Fossil Sync Protocol}
43 tech_overview.wiki {A Technical Overview Of The Design And Implementation
44 Of Fossil}
45 tech_overview.wiki {SQLite Databases Used By Fossil}
46 theory1.wiki {Thoughts On The Design Of The Fossil DVCS}
@@ -47,11 +51,11 @@
47 webui.wiki {The Fossil Web Interface}
48 wikitheory.wiki {Wiki In Fossil}
49 }
50
51 set permindex {}
52 set stopwords {fossil and a in of on the to are about used by}
53 foreach {file title} $doclist {
54 set n [llength $title]
55 lappend permindex [list $title $file]
56 for {set i 0} {$i<$n-1} {incr i} {
57 set prefix [lrange $title 0 $i]
@@ -61,13 +65,14 @@
61 lappend permindex [list "$suffix &#151; $prefix" $file]
62 }
63 }
64 }
65 set permindex [lsort -dict $permindex]
66 puts "<title>Permuted Index Of Fossil Documentation</title>"
67 puts "<nowiki>"
68 puts "<ul>"
 
69 foreach entry $permindex {
70 foreach {title file} $entry break
71 puts "<li><a href=\"$file\">$title</a></li>"
72 }
73 puts "</ul>"
74
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -9,10 +9,11 @@
9 set doclist {
10 bugtheory.wiki {Bug Tracking In Fossil}
11 branching.wiki {Branching, Forking, Merging, and Tagging}
12 build.wiki {Building and Installing Fossil}
13 checkin_names.wiki {Checkin And Version Names}
14 changes.wiki {Fossil Changelog}
15 copyright-release.html {Contributor License Agreement}
16 concepts.wiki {Fossil Core Concepts}
17 contribute.wiki {Contributing Code or Documentation To The Fossil Project}
18 custom_ticket.wiki {Customizing The Ticket System}
19 delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
@@ -19,10 +20,11 @@
20 delta_format.wiki {Fossil Delta Format}
21 embeddeddoc.wiki {Embedded Project Documentation}
22 event.wiki {Events}
23 faq.wiki {Frequently Asked Questions}
24 fileformat.wiki {Fossil File Format}
25 foss-cklist.wiki {Checklist For Successful Open-Source Projects}
26 fossil-v-git.wiki {Fossil Versus Git}
27 index.wiki {Home Page}
28 inout.wiki {Import And Export To And From Git}
29 makefile.wiki {The Fossil Build Process}
30 password.wiki {Password Management And Authentication}
@@ -34,13 +36,15 @@
36 {Quotes: What People Are Saying About Fossil, Git, and DVCSes in General}
37 ../test/release-checklist.wiki {Pre-Release Testing Checklist}
38 selfcheck.wiki {Fossil Repository Integrity Self Checks}
39 selfhost.wiki {Fossil Self Hosting Repositories}
40 server.wiki {How To Configure A Fossil Server}
41 settings.wiki {Fossil Settings}
42 shunning.wiki {Shunning: Deleting Content From Fossil}
43 stats.wiki {Performance Statistics}
44 style.wiki {Source Code Style Guidelines}
45 ssl.wiki {Using SSL with Fossil}
46 sync.wiki {The Fossil Sync Protocol}
47 tech_overview.wiki {A Technical Overview Of The Design And Implementation
48 Of Fossil}
49 tech_overview.wiki {SQLite Databases Used By Fossil}
50 theory1.wiki {Thoughts On The Design Of The Fossil DVCS}
@@ -47,11 +51,11 @@
51 webui.wiki {The Fossil Web Interface}
52 wikitheory.wiki {Wiki In Fossil}
53 }
54
55 set permindex {}
56 set stopwords {fossil and a in of on the to are about used by for or}
57 foreach {file title} $doclist {
58 set n [llength $title]
59 lappend permindex [list $title $file]
60 for {set i 0} {$i<$n-1} {incr i} {
61 set prefix [lrange $title 0 $i]
@@ -61,13 +65,14 @@
65 lappend permindex [list "$suffix &#151; $prefix" $file]
66 }
67 }
68 }
69 set permindex [lsort -dict $permindex]
70 set out [open permutedindex.wiki w]
71 puts $out "<title>Permuted Index Of Fossil Documentation</title>"
72 puts $out "<nowiki>"
73 puts $out "<ul>"
74 foreach entry $permindex {
75 foreach {title file} $entry break
76 puts $out "<li><a href=\"$file\">$title</a></li>"
77 }
78 puts $out "</ul>"
79
--- www/permutedindex.wiki
+++ www/permutedindex.wiki
@@ -11,12 +11,14 @@
1111
<li><a href="private.wiki">Branches &#151; Creating, Syncing, and Deleting Private</a></li>
1212
<li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li>
1313
<li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li>
1414
<li><a href="makefile.wiki">Build Process &#151; The Fossil</a></li>
1515
<li><a href="build.wiki">Building and Installing Fossil</a></li>
16
+<li><a href="changes.wiki">Changelog &#151; Fossil</a></li>
1617
<li><a href="checkin_names.wiki">Checkin And Version Names</a></li>
1718
<li><a href="../test/release-checklist.wiki">Checklist &#151; Pre-Release Testing</a></li>
19
+<li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
1820
<li><a href="selfcheck.wiki">Checks &#151; Fossil Repository Integrity Self</a></li>
1921
<li><a href="contribute.wiki">Code or Documentation To The Fossil Project &#151; Contributing</a></li>
2022
<li><a href="style.wiki">Code Style Guidelines &#151; Source</a></li>
2123
<li><a href="concepts.wiki">Concepts &#151; Fossil Core</a></li>
2224
<li><a href="server.wiki">Configure A Fossil Server &#151; How To</a></li>
@@ -43,17 +45,19 @@
4345
<li><a href="inout.wiki">Export To And From Git &#151; Import And</a></li>
4446
<li><a href="fileformat.wiki">File Format &#151; Fossil</a></li>
4547
<li><a href="branching.wiki">Forking, Merging, and Tagging &#151; Branching,</a></li>
4648
<li><a href="delta_format.wiki">Format &#151; Fossil Delta</a></li>
4749
<li><a href="fileformat.wiki">Format &#151; Fossil File</a></li>
50
+<li><a href="changes.wiki">Fossil Changelog</a></li>
4851
<li><a href="concepts.wiki">Fossil Core Concepts</a></li>
4952
<li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li>
5053
<li><a href="delta_format.wiki">Fossil Delta Format</a></li>
5154
<li><a href="fileformat.wiki">Fossil File Format</a></li>
5255
<li><a href="quickstart.wiki">Fossil Quick Start Guide</a></li>
5356
<li><a href="selfcheck.wiki">Fossil Repository Integrity Self Checks</a></li>
5457
<li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li>
58
+<li><a href="settings.wiki">Fossil Settings</a></li>
5559
<li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li>
5660
<li><a href="quotes.wiki">Fossil, Git, and DVCSes in General &#151; Quotes: What People Are Saying About</a></li>
5761
<li><a href="faq.wiki">Frequently Asked Questions</a></li>
5862
<li><a href="shunning.wiki">From Fossil &#151; Shunning: Deleting Content</a></li>
5963
<li><a href="inout.wiki">From Git &#151; Import And Export To And</a></li>
@@ -73,12 +77,12 @@
7377
<li><a href="webui.wiki">Interface &#151; The Fossil Web</a></li>
7478
<li><a href="copyright-release.html">License Agreement &#151; Contributor</a></li>
7579
<li><a href="password.wiki">Management And Authentication &#151; Password</a></li>
7680
<li><a href="branching.wiki">Merging, and Tagging &#151; Branching, Forking,</a></li>
7781
<li><a href="checkin_names.wiki">Names &#151; Checkin And Version</a></li>
82
+<li><a href="foss-cklist.wiki">Open-Source Projects &#151; Checklist For Successful</a></li>
7883
<li><a href="pop.wiki">Operations &#151; Principles Of</a></li>
79
-<li><a href="contribute.wiki">or Documentation To The Fossil Project &#151; Contributing Code</a></li>
8084
<li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &#151; A Technical</a></li>
8185
<li><a href="index.wiki">Page &#151; Home</a></li>
8286
<li><a href="password.wiki">Password Management And Authentication</a></li>
8387
<li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &#151; Quotes: What</a></li>
8488
<li><a href="stats.wiki">Performance Statistics</a></li>
@@ -86,10 +90,11 @@
8690
<li><a href="pop.wiki">Principles Of Operations</a></li>
8791
<li><a href="private.wiki">Private Branches &#151; Creating, Syncing, and Deleting</a></li>
8892
<li><a href="makefile.wiki">Process &#151; The Fossil Build</a></li>
8993
<li><a href="contribute.wiki">Project &#151; Contributing Code or Documentation To The Fossil</a></li>
9094
<li><a href="embeddeddoc.wiki">Project Documentation &#151; Embedded</a></li>
95
+<li><a href="foss-cklist.wiki">Projects &#151; Checklist For Successful Open-Source</a></li>
9196
<li><a href="sync.wiki">Protocol &#151; The Fossil Sync</a></li>
9297
<li><a href="faq.wiki">Questions &#151; Frequently Asked</a></li>
9398
<li><a href="qandc.wiki">Questions And Criticisms</a></li>
9499
<li><a href="quickstart.wiki">Quick Start Guide &#151; Fossil</a></li>
95100
<li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li>
@@ -97,16 +102,19 @@
97102
<li><a href="selfcheck.wiki">Repository Integrity Self Checks &#151; Fossil</a></li>
98103
<li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &#151; Quotes: What People Are</a></li>
99104
<li><a href="selfcheck.wiki">Self Checks &#151; Fossil Repository Integrity</a></li>
100105
<li><a href="selfhost.wiki">Self Hosting Repositories &#151; Fossil</a></li>
101106
<li><a href="server.wiki">Server &#151; How To Configure A Fossil</a></li>
107
+<li><a href="settings.wiki">Settings &#151; Fossil</a></li>
102108
<li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li>
103109
<li><a href="style.wiki">Source Code Style Guidelines</a></li>
104110
<li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li>
111
+<li><a href="ssl.wiki">SSL with Fossil &#151; Using</a></li>
105112
<li><a href="quickstart.wiki">Start Guide &#151; Fossil Quick</a></li>
106113
<li><a href="stats.wiki">Statistics &#151; Performance</a></li>
107114
<li><a href="style.wiki">Style Guidelines &#151; Source Code</a></li>
115
+<li><a href="foss-cklist.wiki">Successful Open-Source Projects &#151; Checklist For</a></li>
108116
<li><a href="sync.wiki">Sync Protocol &#151; The Fossil</a></li>
109117
<li><a href="private.wiki">Syncing, and Deleting Private Branches &#151; Creating,</a></li>
110118
<li><a href="custom_ticket.wiki">System &#151; Customizing The Ticket</a></li>
111119
<li><a href="branching.wiki">Tagging &#151; Branching, Forking, Merging, and</a></li>
112120
<li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &#151; A</a></li>
@@ -115,11 +123,13 @@
115123
<li><a href="sync.wiki">The Fossil Sync Protocol</a></li>
116124
<li><a href="webui.wiki">The Fossil Web Interface</a></li>
117125
<li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li>
118126
<li><a href="custom_ticket.wiki">Ticket System &#151; Customizing The</a></li>
119127
<li><a href="bugtheory.wiki">Tracking In Fossil &#151; Bug</a></li>
128
+<li><a href="ssl.wiki">Using SSL with Fossil</a></li>
120129
<li><a href="checkin_names.wiki">Version Names &#151; Checkin And</a></li>
121130
<li><a href="fossil-v-git.wiki">Versus Git &#151; Fossil</a></li>
122131
<li><a href="webui.wiki">Web Interface &#151; The Fossil</a></li>
123132
<li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &#151; Quotes:</a></li>
124133
<li><a href="wikitheory.wiki">Wiki In Fossil</a></li>
134
+<li><a href="ssl.wiki">with Fossil &#151; Using SSL</a></li>
125135
</ul>
126136
--- www/permutedindex.wiki
+++ www/permutedindex.wiki
@@ -11,12 +11,14 @@
11 <li><a href="private.wiki">Branches &#151; Creating, Syncing, and Deleting Private</a></li>
12 <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li>
13 <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li>
14 <li><a href="makefile.wiki">Build Process &#151; The Fossil</a></li>
15 <li><a href="build.wiki">Building and Installing Fossil</a></li>
 
16 <li><a href="checkin_names.wiki">Checkin And Version Names</a></li>
17 <li><a href="../test/release-checklist.wiki">Checklist &#151; Pre-Release Testing</a></li>
 
18 <li><a href="selfcheck.wiki">Checks &#151; Fossil Repository Integrity Self</a></li>
19 <li><a href="contribute.wiki">Code or Documentation To The Fossil Project &#151; Contributing</a></li>
20 <li><a href="style.wiki">Code Style Guidelines &#151; Source</a></li>
21 <li><a href="concepts.wiki">Concepts &#151; Fossil Core</a></li>
22 <li><a href="server.wiki">Configure A Fossil Server &#151; How To</a></li>
@@ -43,17 +45,19 @@
43 <li><a href="inout.wiki">Export To And From Git &#151; Import And</a></li>
44 <li><a href="fileformat.wiki">File Format &#151; Fossil</a></li>
45 <li><a href="branching.wiki">Forking, Merging, and Tagging &#151; Branching,</a></li>
46 <li><a href="delta_format.wiki">Format &#151; Fossil Delta</a></li>
47 <li><a href="fileformat.wiki">Format &#151; Fossil File</a></li>
 
48 <li><a href="concepts.wiki">Fossil Core Concepts</a></li>
49 <li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li>
50 <li><a href="delta_format.wiki">Fossil Delta Format</a></li>
51 <li><a href="fileformat.wiki">Fossil File Format</a></li>
52 <li><a href="quickstart.wiki">Fossil Quick Start Guide</a></li>
53 <li><a href="selfcheck.wiki">Fossil Repository Integrity Self Checks</a></li>
54 <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li>
 
55 <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li>
56 <li><a href="quotes.wiki">Fossil, Git, and DVCSes in General &#151; Quotes: What People Are Saying About</a></li>
57 <li><a href="faq.wiki">Frequently Asked Questions</a></li>
58 <li><a href="shunning.wiki">From Fossil &#151; Shunning: Deleting Content</a></li>
59 <li><a href="inout.wiki">From Git &#151; Import And Export To And</a></li>
@@ -73,12 +77,12 @@
73 <li><a href="webui.wiki">Interface &#151; The Fossil Web</a></li>
74 <li><a href="copyright-release.html">License Agreement &#151; Contributor</a></li>
75 <li><a href="password.wiki">Management And Authentication &#151; Password</a></li>
76 <li><a href="branching.wiki">Merging, and Tagging &#151; Branching, Forking,</a></li>
77 <li><a href="checkin_names.wiki">Names &#151; Checkin And Version</a></li>
 
78 <li><a href="pop.wiki">Operations &#151; Principles Of</a></li>
79 <li><a href="contribute.wiki">or Documentation To The Fossil Project &#151; Contributing Code</a></li>
80 <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &#151; A Technical</a></li>
81 <li><a href="index.wiki">Page &#151; Home</a></li>
82 <li><a href="password.wiki">Password Management And Authentication</a></li>
83 <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &#151; Quotes: What</a></li>
84 <li><a href="stats.wiki">Performance Statistics</a></li>
@@ -86,10 +90,11 @@
86 <li><a href="pop.wiki">Principles Of Operations</a></li>
87 <li><a href="private.wiki">Private Branches &#151; Creating, Syncing, and Deleting</a></li>
88 <li><a href="makefile.wiki">Process &#151; The Fossil Build</a></li>
89 <li><a href="contribute.wiki">Project &#151; Contributing Code or Documentation To The Fossil</a></li>
90 <li><a href="embeddeddoc.wiki">Project Documentation &#151; Embedded</a></li>
 
91 <li><a href="sync.wiki">Protocol &#151; The Fossil Sync</a></li>
92 <li><a href="faq.wiki">Questions &#151; Frequently Asked</a></li>
93 <li><a href="qandc.wiki">Questions And Criticisms</a></li>
94 <li><a href="quickstart.wiki">Quick Start Guide &#151; Fossil</a></li>
95 <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li>
@@ -97,16 +102,19 @@
97 <li><a href="selfcheck.wiki">Repository Integrity Self Checks &#151; Fossil</a></li>
98 <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &#151; Quotes: What People Are</a></li>
99 <li><a href="selfcheck.wiki">Self Checks &#151; Fossil Repository Integrity</a></li>
100 <li><a href="selfhost.wiki">Self Hosting Repositories &#151; Fossil</a></li>
101 <li><a href="server.wiki">Server &#151; How To Configure A Fossil</a></li>
 
102 <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li>
103 <li><a href="style.wiki">Source Code Style Guidelines</a></li>
104 <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li>
 
105 <li><a href="quickstart.wiki">Start Guide &#151; Fossil Quick</a></li>
106 <li><a href="stats.wiki">Statistics &#151; Performance</a></li>
107 <li><a href="style.wiki">Style Guidelines &#151; Source Code</a></li>
 
108 <li><a href="sync.wiki">Sync Protocol &#151; The Fossil</a></li>
109 <li><a href="private.wiki">Syncing, and Deleting Private Branches &#151; Creating,</a></li>
110 <li><a href="custom_ticket.wiki">System &#151; Customizing The Ticket</a></li>
111 <li><a href="branching.wiki">Tagging &#151; Branching, Forking, Merging, and</a></li>
112 <li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &#151; A</a></li>
@@ -115,11 +123,13 @@
115 <li><a href="sync.wiki">The Fossil Sync Protocol</a></li>
116 <li><a href="webui.wiki">The Fossil Web Interface</a></li>
117 <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li>
118 <li><a href="custom_ticket.wiki">Ticket System &#151; Customizing The</a></li>
119 <li><a href="bugtheory.wiki">Tracking In Fossil &#151; Bug</a></li>
 
120 <li><a href="checkin_names.wiki">Version Names &#151; Checkin And</a></li>
121 <li><a href="fossil-v-git.wiki">Versus Git &#151; Fossil</a></li>
122 <li><a href="webui.wiki">Web Interface &#151; The Fossil</a></li>
123 <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &#151; Quotes:</a></li>
124 <li><a href="wikitheory.wiki">Wiki In Fossil</a></li>
 
125 </ul>
126
--- www/permutedindex.wiki
+++ www/permutedindex.wiki
@@ -11,12 +11,14 @@
11 <li><a href="private.wiki">Branches &#151; Creating, Syncing, and Deleting Private</a></li>
12 <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li>
13 <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li>
14 <li><a href="makefile.wiki">Build Process &#151; The Fossil</a></li>
15 <li><a href="build.wiki">Building and Installing Fossil</a></li>
16 <li><a href="changes.wiki">Changelog &#151; Fossil</a></li>
17 <li><a href="checkin_names.wiki">Checkin And Version Names</a></li>
18 <li><a href="../test/release-checklist.wiki">Checklist &#151; Pre-Release Testing</a></li>
19 <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li>
20 <li><a href="selfcheck.wiki">Checks &#151; Fossil Repository Integrity Self</a></li>
21 <li><a href="contribute.wiki">Code or Documentation To The Fossil Project &#151; Contributing</a></li>
22 <li><a href="style.wiki">Code Style Guidelines &#151; Source</a></li>
23 <li><a href="concepts.wiki">Concepts &#151; Fossil Core</a></li>
24 <li><a href="server.wiki">Configure A Fossil Server &#151; How To</a></li>
@@ -43,17 +45,19 @@
45 <li><a href="inout.wiki">Export To And From Git &#151; Import And</a></li>
46 <li><a href="fileformat.wiki">File Format &#151; Fossil</a></li>
47 <li><a href="branching.wiki">Forking, Merging, and Tagging &#151; Branching,</a></li>
48 <li><a href="delta_format.wiki">Format &#151; Fossil Delta</a></li>
49 <li><a href="fileformat.wiki">Format &#151; Fossil File</a></li>
50 <li><a href="changes.wiki">Fossil Changelog</a></li>
51 <li><a href="concepts.wiki">Fossil Core Concepts</a></li>
52 <li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li>
53 <li><a href="delta_format.wiki">Fossil Delta Format</a></li>
54 <li><a href="fileformat.wiki">Fossil File Format</a></li>
55 <li><a href="quickstart.wiki">Fossil Quick Start Guide</a></li>
56 <li><a href="selfcheck.wiki">Fossil Repository Integrity Self Checks</a></li>
57 <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li>
58 <li><a href="settings.wiki">Fossil Settings</a></li>
59 <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li>
60 <li><a href="quotes.wiki">Fossil, Git, and DVCSes in General &#151; Quotes: What People Are Saying About</a></li>
61 <li><a href="faq.wiki">Frequently Asked Questions</a></li>
62 <li><a href="shunning.wiki">From Fossil &#151; Shunning: Deleting Content</a></li>
63 <li><a href="inout.wiki">From Git &#151; Import And Export To And</a></li>
@@ -73,12 +77,12 @@
77 <li><a href="webui.wiki">Interface &#151; The Fossil Web</a></li>
78 <li><a href="copyright-release.html">License Agreement &#151; Contributor</a></li>
79 <li><a href="password.wiki">Management And Authentication &#151; Password</a></li>
80 <li><a href="branching.wiki">Merging, and Tagging &#151; Branching, Forking,</a></li>
81 <li><a href="checkin_names.wiki">Names &#151; Checkin And Version</a></li>
82 <li><a href="foss-cklist.wiki">Open-Source Projects &#151; Checklist For Successful</a></li>
83 <li><a href="pop.wiki">Operations &#151; Principles Of</a></li>
 
84 <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &#151; A Technical</a></li>
85 <li><a href="index.wiki">Page &#151; Home</a></li>
86 <li><a href="password.wiki">Password Management And Authentication</a></li>
87 <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &#151; Quotes: What</a></li>
88 <li><a href="stats.wiki">Performance Statistics</a></li>
@@ -86,10 +90,11 @@
90 <li><a href="pop.wiki">Principles Of Operations</a></li>
91 <li><a href="private.wiki">Private Branches &#151; Creating, Syncing, and Deleting</a></li>
92 <li><a href="makefile.wiki">Process &#151; The Fossil Build</a></li>
93 <li><a href="contribute.wiki">Project &#151; Contributing Code or Documentation To The Fossil</a></li>
94 <li><a href="embeddeddoc.wiki">Project Documentation &#151; Embedded</a></li>
95 <li><a href="foss-cklist.wiki">Projects &#151; Checklist For Successful Open-Source</a></li>
96 <li><a href="sync.wiki">Protocol &#151; The Fossil Sync</a></li>
97 <li><a href="faq.wiki">Questions &#151; Frequently Asked</a></li>
98 <li><a href="qandc.wiki">Questions And Criticisms</a></li>
99 <li><a href="quickstart.wiki">Quick Start Guide &#151; Fossil</a></li>
100 <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li>
@@ -97,16 +102,19 @@
102 <li><a href="selfcheck.wiki">Repository Integrity Self Checks &#151; Fossil</a></li>
103 <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &#151; Quotes: What People Are</a></li>
104 <li><a href="selfcheck.wiki">Self Checks &#151; Fossil Repository Integrity</a></li>
105 <li><a href="selfhost.wiki">Self Hosting Repositories &#151; Fossil</a></li>
106 <li><a href="server.wiki">Server &#151; How To Configure A Fossil</a></li>
107 <li><a href="settings.wiki">Settings &#151; Fossil</a></li>
108 <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li>
109 <li><a href="style.wiki">Source Code Style Guidelines</a></li>
110 <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li>
111 <li><a href="ssl.wiki">SSL with Fossil &#151; Using</a></li>
112 <li><a href="quickstart.wiki">Start Guide &#151; Fossil Quick</a></li>
113 <li><a href="stats.wiki">Statistics &#151; Performance</a></li>
114 <li><a href="style.wiki">Style Guidelines &#151; Source Code</a></li>
115 <li><a href="foss-cklist.wiki">Successful Open-Source Projects &#151; Checklist For</a></li>
116 <li><a href="sync.wiki">Sync Protocol &#151; The Fossil</a></li>
117 <li><a href="private.wiki">Syncing, and Deleting Private Branches &#151; Creating,</a></li>
118 <li><a href="custom_ticket.wiki">System &#151; Customizing The Ticket</a></li>
119 <li><a href="branching.wiki">Tagging &#151; Branching, Forking, Merging, and</a></li>
120 <li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &#151; A</a></li>
@@ -115,11 +123,13 @@
123 <li><a href="sync.wiki">The Fossil Sync Protocol</a></li>
124 <li><a href="webui.wiki">The Fossil Web Interface</a></li>
125 <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li>
126 <li><a href="custom_ticket.wiki">Ticket System &#151; Customizing The</a></li>
127 <li><a href="bugtheory.wiki">Tracking In Fossil &#151; Bug</a></li>
128 <li><a href="ssl.wiki">Using SSL with Fossil</a></li>
129 <li><a href="checkin_names.wiki">Version Names &#151; Checkin And</a></li>
130 <li><a href="fossil-v-git.wiki">Versus Git &#151; Fossil</a></li>
131 <li><a href="webui.wiki">Web Interface &#151; The Fossil</a></li>
132 <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &#151; Quotes:</a></li>
133 <li><a href="wikitheory.wiki">Wiki In Fossil</a></li>
134 <li><a href="ssl.wiki">with Fossil &#151; Using SSL</a></li>
135 </ul>
136
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -9,11 +9,11 @@
99
<p>Fossil is a single self-contained C program. You need to
1010
either download a
1111
<a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
1212
or <a href="build.wiki">build it yourself</a> from sources.
1313
Install fossil by putting the fossil binary
14
- someplace on your PATH environment variable.</p>
14
+ someplace on your $PATH.</p>
1515
1616
<a name="fslclone"></a>
1717
<h2>General Work Flow</h2>
1818
1919
<p>Fossil works with repository files (a database with the project's
@@ -20,29 +20,27 @@
2020
complete history) and with checked-out local trees (the working directory
2121
you use to do your work).
2222
The workflow looks like this:</p>
2323
2424
<ul>
25
- <li>Create or clone a repository file. ([/help/new|fossil new] or
25
+ <li>Create or clone a repository file. ([/help/init|fossil init] or
2626
[/help/clone | fossil clone])
2727
<li>Check out a local tree. ([/help/open | fossil open])
2828
<li>Perform operations on the repository (including repository
2929
configuration).
30
- <li><em>Optionally</em> close the local tree.
31
- ([/help/close | fossil close], but this is rarely used.)
3230
</ul>
3331
3432
<p>The following sections will give you a brief overview of these
3533
operations.</p>
3634
3735
<h2>Starting A New Project</h2>
3836
3937
<p>To start a new project with fossil, create a new empty repository
40
- this way: ([/help/new | more info]) </p>
38
+ this way: ([/help/init | more info]) </p>
4139
4240
<blockquote>
43
- <b>fossil new </b><i> repository-filename</i>
41
+ <b>fossil init </b><i> repository-filename</i>
4442
</blockquote>
4543
4644
<h2>Cloning An Existing Repository</h2>
4745
4846
<p>Most fossil operations interact with a repository that is on the
@@ -73,10 +71,19 @@
7371
You can name your repositories anything you want. The ".fossil" suffix
7472
is not required.</p>
7573
7674
<p>Note: If you are behind a restrictive firewall, you might need
7775
to <a href="#proxy">specify an HTTP proxy</a> to use.</p>
76
+
77
+ <p>A Fossil repository is a single disk file. Instead of cloning,
78
+ you can just make a copy of the repository file (for example, using
79
+ "scp"). Note, however, that the repository file contains auxiliary
80
+ information above and beyond the versioned files, including some
81
+ sensitive information such as passwords and email addresses. If you
82
+ want to share Fossil repositories directly, consider running the
83
+ [/help/scrub|fossil scrub] command to remove sensitive information
84
+ before transmitting the file.
7885
7986
<h2>Importing From Another Version Control System</h2>
8087
8188
<p>Rather than start a new project, or clone an existing Fossil project,
8289
you might prefer to
@@ -147,11 +154,12 @@
147154
<p>To add new files to your project, or remove old files, use these
148155
commands:</p>
149156
150157
<blockquote>
151158
<b>[/help/add | fossil add]</b> <i>file...</i><br>
152
- <b>[/help/rm | fossil rm]</b> <i>file...</i>
159
+ <b>[/help/rm | fossil rm]</b> <i>file...</i><br>
160
+ <b>[/help/addremove | fossil addremove]</b> <i>file...</i><br>
153161
</blockquote>
154162
155163
<p>You can also edit files freely. Once you are ready to commit
156164
your changes, type:</p>
157165
158166
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -9,11 +9,11 @@
9 <p>Fossil is a single self-contained C program. You need to
10 either download a
11 <a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
12 or <a href="build.wiki">build it yourself</a> from sources.
13 Install fossil by putting the fossil binary
14 someplace on your PATH environment variable.</p>
15
16 <a name="fslclone"></a>
17 <h2>General Work Flow</h2>
18
19 <p>Fossil works with repository files (a database with the project's
@@ -20,29 +20,27 @@
20 complete history) and with checked-out local trees (the working directory
21 you use to do your work).
22 The workflow looks like this:</p>
23
24 <ul>
25 <li>Create or clone a repository file. ([/help/new|fossil new] or
26 [/help/clone | fossil clone])
27 <li>Check out a local tree. ([/help/open | fossil open])
28 <li>Perform operations on the repository (including repository
29 configuration).
30 <li><em>Optionally</em> close the local tree.
31 ([/help/close | fossil close], but this is rarely used.)
32 </ul>
33
34 <p>The following sections will give you a brief overview of these
35 operations.</p>
36
37 <h2>Starting A New Project</h2>
38
39 <p>To start a new project with fossil, create a new empty repository
40 this way: ([/help/new | more info]) </p>
41
42 <blockquote>
43 <b>fossil new </b><i> repository-filename</i>
44 </blockquote>
45
46 <h2>Cloning An Existing Repository</h2>
47
48 <p>Most fossil operations interact with a repository that is on the
@@ -73,10 +71,19 @@
73 You can name your repositories anything you want. The ".fossil" suffix
74 is not required.</p>
75
76 <p>Note: If you are behind a restrictive firewall, you might need
77 to <a href="#proxy">specify an HTTP proxy</a> to use.</p>
 
 
 
 
 
 
 
 
 
78
79 <h2>Importing From Another Version Control System</h2>
80
81 <p>Rather than start a new project, or clone an existing Fossil project,
82 you might prefer to
@@ -147,11 +154,12 @@
147 <p>To add new files to your project, or remove old files, use these
148 commands:</p>
149
150 <blockquote>
151 <b>[/help/add | fossil add]</b> <i>file...</i><br>
152 <b>[/help/rm | fossil rm]</b> <i>file...</i>
 
153 </blockquote>
154
155 <p>You can also edit files freely. Once you are ready to commit
156 your changes, type:</p>
157
158
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -9,11 +9,11 @@
9 <p>Fossil is a single self-contained C program. You need to
10 either download a
11 <a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
12 or <a href="build.wiki">build it yourself</a> from sources.
13 Install fossil by putting the fossil binary
14 someplace on your $PATH.</p>
15
16 <a name="fslclone"></a>
17 <h2>General Work Flow</h2>
18
19 <p>Fossil works with repository files (a database with the project's
@@ -20,29 +20,27 @@
20 complete history) and with checked-out local trees (the working directory
21 you use to do your work).
22 The workflow looks like this:</p>
23
24 <ul>
25 <li>Create or clone a repository file. ([/help/init|fossil init] or
26 [/help/clone | fossil clone])
27 <li>Check out a local tree. ([/help/open | fossil open])
28 <li>Perform operations on the repository (including repository
29 configuration).
 
 
30 </ul>
31
32 <p>The following sections will give you a brief overview of these
33 operations.</p>
34
35 <h2>Starting A New Project</h2>
36
37 <p>To start a new project with fossil, create a new empty repository
38 this way: ([/help/init | more info]) </p>
39
40 <blockquote>
41 <b>fossil init </b><i> repository-filename</i>
42 </blockquote>
43
44 <h2>Cloning An Existing Repository</h2>
45
46 <p>Most fossil operations interact with a repository that is on the
@@ -73,10 +71,19 @@
71 You can name your repositories anything you want. The ".fossil" suffix
72 is not required.</p>
73
74 <p>Note: If you are behind a restrictive firewall, you might need
75 to <a href="#proxy">specify an HTTP proxy</a> to use.</p>
76
77 <p>A Fossil repository is a single disk file. Instead of cloning,
78 you can just make a copy of the repository file (for example, using
79 "scp"). Note, however, that the repository file contains auxiliary
80 information above and beyond the versioned files, including some
81 sensitive information such as passwords and email addresses. If you
82 want to share Fossil repositories directly, consider running the
83 [/help/scrub|fossil scrub] command to remove sensitive information
84 before transmitting the file.
85
86 <h2>Importing From Another Version Control System</h2>
87
88 <p>Rather than start a new project, or clone an existing Fossil project,
89 you might prefer to
@@ -147,11 +154,12 @@
154 <p>To add new files to your project, or remove old files, use these
155 commands:</p>
156
157 <blockquote>
158 <b>[/help/add | fossil add]</b> <i>file...</i><br>
159 <b>[/help/rm | fossil rm]</b> <i>file...</i><br>
160 <b>[/help/addremove | fossil addremove]</b> <i>file...</i><br>
161 </blockquote>
162
163 <p>You can also edit files freely. Once you are ready to commit
164 your changes, type:</p>
165
166
--- www/server.wiki
+++ www/server.wiki
@@ -97,10 +97,13 @@
9797
If you are using "inetd" to serve your repository, then you simply need to add "/usr/bin/stunnel" (perhaps on a different path, depending on your setup) before the command line to launch Fossil.
9898
</p>
9999
<p>
100100
At this stage, the standalone server (e.g. "fossil server") does not support SSL.
101101
</p>
102
+<p>
103
+For more information, see <a href="./ssl.wiki">Using SSL with Fossil</a>.
104
+</p>
102105
</blockquote>
103106
104107
<h2>Various security concerns with hosted repositories</h2><blockquote>
105108
<p>
106109
There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data):
107110
108111
ADDED www/settings.wiki
109112
ADDED www/ssl.wiki
--- www/server.wiki
+++ www/server.wiki
@@ -97,10 +97,13 @@
97 If you are using "inetd" to serve your repository, then you simply need to add "/usr/bin/stunnel" (perhaps on a different path, depending on your setup) before the command line to launch Fossil.
98 </p>
99 <p>
100 At this stage, the standalone server (e.g. "fossil server") does not support SSL.
101 </p>
 
 
 
102 </blockquote>
103
104 <h2>Various security concerns with hosted repositories</h2><blockquote>
105 <p>
106 There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data):
107
108 DDED www/settings.wiki
109 DDED www/ssl.wiki
--- www/server.wiki
+++ www/server.wiki
@@ -97,10 +97,13 @@
97 If you are using "inetd" to serve your repository, then you simply need to add "/usr/bin/stunnel" (perhaps on a different path, depending on your setup) before the command line to launch Fossil.
98 </p>
99 <p>
100 At this stage, the standalone server (e.g. "fossil server") does not support SSL.
101 </p>
102 <p>
103 For more information, see <a href="./ssl.wiki">Using SSL with Fossil</a>.
104 </p>
105 </blockquote>
106
107 <h2>Various security concerns with hosted repositories</h2><blockquote>
108 <p>
109 There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data):
110
111 DDED www/settings.wiki
112 DDED www/ssl.wiki
--- a/www/settings.wiki
+++ b/www/settings.wiki
@@ -0,0 +1,6 @@
1
+ command.
2
+ a repository on the web. b</tt>,
3
+ � �
4
+ddirectory < <title>Fossil S nl-glob</tt>,
5
+ � �
6
+ddirectory t ignorealso
--- a/www/settings.wiki
+++ b/www/settings.wiki
@@ -0,0 +1,6 @@
 
 
 
 
 
 
--- a/www/settings.wiki
+++ b/www/settings.wiki
@@ -0,0 +1,6 @@
1 command.
2 a repository on the web. b</tt>,
3 � �
4 ddirectory < <title>Fossil S nl-glob</tt>,
5 � �
6 ddirectory t ignorealso
+22
--- a/www/ssl.wiki
+++ b/www/ssl.wiki
@@ -0,0 +1,22 @@
1
+<title>SSL and Fossiluring a Repository wSSLyour repositge." This setting is not . This will protectessed via HTTP,
2
+sas well preventing eavesdropping of the contents of your repository.
3
+
4
+To host a repository with SSL, you need to use an web server which supports SSL in front of the Fossil server. You can host it using the CGI option or by proxying Fossil's built in HTTP server.
5
+
6
+Your fossil client must system Make sure scheme to ensure you're using SSL. from http as w important S front end proxy up again for access, which
7
+causes Fossil to see that it's being accessed via HTTP, so it redirects
8
+the client to detects
9
+
10
+
11
+If you wishto a Fossil web server, iayer, not by use of Fossil-
12
+shows one way to`ssl`SSL uses certificates.certificates you trustyou wishto a Fossil web server, iayer, not by use of Fossil-
13
+shows one way e of Fossil-
14
+shows one way to`ssl` using a certificate signed by a certificate authority, you need to specifyil-
15
+shows one was you trust with the <tt>ssl-ca-location</tt> setting. Set this globally with the <tt>-global</tt> option for convenience.
16
+
17
+This should be set to the location of a file containing all the PEM encoded certificates you trust. You can obtain a certificate using a web browser, for example, Firefox, or just refer to your system's trusted CA roots which are usually stored somewhere in <tt>/etc</tt>.
18
+
19
+
20
+<h2>C nications with Fossil</h2>
21
+
22
+If you are storing sensitive information T <title title>TLS and Fossiluring a Repository with TLS</title>
--- a/www/ssl.wiki
+++ b/www/ssl.wiki
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/ssl.wiki
+++ b/www/ssl.wiki
@@ -0,0 +1,22 @@
1 <title>SSL and Fossiluring a Repository wSSLyour repositge." This setting is not . This will protectessed via HTTP,
2 sas well preventing eavesdropping of the contents of your repository.
3
4 To host a repository with SSL, you need to use an web server which supports SSL in front of the Fossil server. You can host it using the CGI option or by proxying Fossil's built in HTTP server.
5
6 Your fossil client must system Make sure scheme to ensure you're using SSL. from http as w important S front end proxy up again for access, which
7 causes Fossil to see that it's being accessed via HTTP, so it redirects
8 the client to detects
9
10
11 If you wishto a Fossil web server, iayer, not by use of Fossil-
12 shows one way to`ssl`SSL uses certificates.certificates you trustyou wishto a Fossil web server, iayer, not by use of Fossil-
13 shows one way e of Fossil-
14 shows one way to`ssl` using a certificate signed by a certificate authority, you need to specifyil-
15 shows one was you trust with the <tt>ssl-ca-location</tt> setting. Set this globally with the <tt>-global</tt> option for convenience.
16
17 This should be set to the location of a file containing all the PEM encoded certificates you trust. You can obtain a certificate using a web browser, for example, Firefox, or just refer to your system's trusted CA roots which are usually stored somewhere in <tt>/etc</tt>.
18
19
20 <h2>C nications with Fossil</h2>
21
22 If you are storing sensitive information T <title title>TLS and Fossiluring a Repository with TLS</title>

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button