Fossil SCM

Merge trunk into ben-testing

ben 2011-08-04 15:54 ben-testing merge
Commit 3eb07708b1160724e5be464ee1ce5efd65ef3a87
+30 -21
--- BUILD.txt
+++ BUILD.txt
@@ -1,54 +1,60 @@
1
-To do a complete build on most unix systems, just type:
2
-
3
- make
4
-
5
-If you have an unusual unix system for which the standard Makefile
6
-will not work, or if you want to do some non-standard options, you can
7
-also run:
1
+To do a complete build, just type:
82
93
./configure; make
104
11
-The ./configure script builds GNUmakefile which will be used in place
12
-of Makefile. Run "./configure --help" for a listing of the available
13
-options.
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
1413
1514
On a windows box, use one of the Makefiles in the win/ subdirectory,
1615
according to your compiler and environment. If you have GCC and MSYS
17
-installed on your system, the consider:
16
+installed on your system, then consider:
1817
1918
make -f win/Makefile.mingw
2019
2120
If you have VC++ installed on your system, then consider:
2221
2322
cd win; nmake /f Makefile.msc
2423
2524
If you have trouble, or you want to do something fancy, just look at
26
-top level makefile. There are 6 configuration options that are all well
27
-commented. Instead of editing the Makefile, consider copying the Makefile
28
-to an alternative name such as "GNUMakefile", "BSDMakefile", or "makefile"
29
-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.
3029
3130
3231
BUILDING OUTSIDE THE SOURCE TREE
3332
3433
An out of source build is pretty easy:
3534
36
- 1. Make a new directory to do the builds in.
37
- 2. Copy "Makefile" from the source into the build directory and
38
- 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:
3940
40
- SRCDIR=../src
41
-
42
- 3. type: "make"
41
+ mkdir build
42
+ cd build
43
+ ../configure
44
+ make
4345
4446
This will now keep all generates files seperate from the maintained
4547
source code.
4648
4749
--------------------------------------------------------------------------
4850
4951
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
5056
5157
* The Makefile just sets up a few macros and then invokes the
5258
real makefile in src/main.mk. The src/main.mk makefile is
5359
automatically generated by a TCL script found at src/makemake.tcl.
5460
Do not edit src/main.mk directly. Update src/makemake.tcl and
@@ -64,5 +70,8 @@
6470
A header comment in src/translate.c explains in detail what it does.
6571
6672
* The src/mkindex.c program generates some C code that implements
6773
static lookup tables. See the header comment in the source code
6874
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
6978
7079
DELETED GNUmakefile.in
7180
DELETED Makefile
7281
ADDED Makefile.classic
7382
ADDED Makefile.in
--- BUILD.txt
+++ BUILD.txt
@@ -1,54 +1,60 @@
1 To do a complete build on most unix systems, just type:
2
3 make
4
5 If you have an unusual unix system for which the standard Makefile
6 will not work, or if you want to do some non-standard options, you can
7 also run:
8
9 ./configure; make
10
11 The ./configure script builds GNUmakefile which will be used in place
12 of Makefile. Run "./configure --help" for a listing of the available
13 options.
 
 
 
 
 
14
15 On a windows box, use one of the Makefiles in the win/ subdirectory,
16 according to your compiler and environment. If you have GCC and MSYS
17 installed on your system, the consider:
18
19 make -f win/Makefile.mingw
20
21 If you have VC++ installed on your system, then consider:
22
23 cd win; nmake /f Makefile.msc
24
25 If you have trouble, or you want to do something fancy, just look at
26 top level makefile. There are 6 configuration options that are all well
27 commented. Instead of editing the Makefile, consider copying the Makefile
28 to an alternative name such as "GNUMakefile", "BSDMakefile", or "makefile"
29 and editing the copy.
30
31
32 BUILDING OUTSIDE THE SOURCE TREE
33
34 An out of source build is pretty easy:
35
36 1. Make a new directory to do the builds in.
37 2. Copy "Makefile" from the source into the build directory and
38 modify the SRCDIR macro along the lines of:
 
 
39
40 SRCDIR=../src
41
42 3. type: "make"
 
43
44 This will now keep all generates files seperate from the maintained
45 source code.
46
47 --------------------------------------------------------------------------
48
49 Here are some notes on what is happening behind the scenes:
 
 
 
 
50
51 * The Makefile just sets up a few macros and then invokes the
52 real makefile in src/main.mk. The src/main.mk makefile is
53 automatically generated by a TCL script found at src/makemake.tcl.
54 Do not edit src/main.mk directly. Update src/makemake.tcl and
@@ -64,5 +70,8 @@
64 A header comment in src/translate.c explains in detail what it does.
65
66 * The src/mkindex.c program generates some C code that implements
67 static lookup tables. See the header comment in the source code
68 for details on what it does.
 
 
 
69
70 ELETED GNUmakefile.in
71 ELETED Makefile
72 DDED Makefile.classic
73 DDED Makefile.in
--- BUILD.txt
+++ BUILD.txt
@@ -1,54 +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
@@ -64,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 GNUmakefile.in
80 ELETED Makefile
81 DDED Makefile.classic
82 DDED Makefile.in
D GNUmakefile.in
-45
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -1,45 +0,0 @@
1
-#!/usr/bin/make
2
-#
3
-# This is the top-level makefile for Fossil when the build is occurring
4
-# on a unix platform. This works out-of-the-box on most unix platforms.
5
-# But you are free to vary some of the definitions if desired.
6
-#
7
-#### The toplevel directory of the source tree. Fossil can be built
8
-# in a directory that is separate from the source tree. Just change
9
-# the following to point from the build directory to the src/ folder.
10
-#
11
-SRCDIR = @srcdir@/src
12
-
13
-#### The directory into which object code files should be written.
14
-#
15
-#
16
-OBJDIR = ./bld
17
-
18
-#### C Compiler and options for use in building executables that
19
-# will run on the platform that is doing the build. This is used
20
-# to compile code-generator programs as part of the build process.
21
-# See TCC below for the C compiler for building the finished binary.
22
-#
23
-BCC = @CC_FOR_BUILD@
24
-
25
-#### The suffix to add to final executable file. When cross-compiling
26
-# to windows, make this ".exe". Otherwise leave it blank.
27
-#
28
-E = @EXEEXT@
29
-
30
-TCC = @CC@
31
-
32
-#### Tcl shell for use in running the fossil testsuite. If you do not
33
-# care about testing the end result, this can be blank.
34
-#
35
-TCLSH = tclsh
36
-
37
-LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
38
-TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
39
-INSTALLDIR = $(DESTDIR)@prefix@/bin
40
-USE_SYSTEM_SQLFORM_CHECK_KIND = disable
41
-
42
-include $(SRCDIR)/main.mk
43
-
44
-distclean: clean
45
- rm -f autoconfi
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -1,45 +0,0 @@
1 #!/usr/bin/make
2 #
3 # This is the top-level makefile for Fossil when the build is occurring
4 # on a unix platform. This works out-of-the-box on most unix platforms.
5 # But you are free to vary some of the definitions if desired.
6 #
7 #### The toplevel directory of the source tree. Fossil can be built
8 # in a directory that is separate from the source tree. Just change
9 # the following to point from the build directory to the src/ folder.
10 #
11 SRCDIR = @srcdir@/src
12
13 #### The directory into which object code files should be written.
14 #
15 #
16 OBJDIR = ./bld
17
18 #### C Compiler and options for use in building executables that
19 # will run on the platform that is doing the build. This is used
20 # to compile code-generator programs as part of the build process.
21 # See TCC below for the C compiler for building the finished binary.
22 #
23 BCC = @CC_FOR_BUILD@
24
25 #### The suffix to add to final executable file. When cross-compiling
26 # to windows, make this ".exe". Otherwise leave it blank.
27 #
28 E = @EXEEXT@
29
30 TCC = @CC@
31
32 #### Tcl shell for use in running the fossil testsuite. If you do not
33 # care about testing the end result, this can be blank.
34 #
35 TCLSH = tclsh
36
37 LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
38 TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
39 INSTALLDIR = $(DESTDIR)@prefix@/bin
40 USE_SYSTEM_SQLFORM_CHECK_KIND = disable
41
42 include $(SRCDIR)/main.mk
43
44 distclean: clean
45 rm -f autoconfi
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -1,45 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+7 -43
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,45 +1,9 @@
1
-#!/usr/bin/make
2
-#
3
-# This is the top-level makefile for Fossil when the build is occurring
4
-# on a unix platform. This works out-of-the-box on most unix platforms.
5
-# But you are free to vary some of the definitions if desired.
6
-#
7
-#### The toplevel directory of the source tree. Fossil can be built
8
-# in a directory that is separate from the source tree. Just change
9
-# the following to point from the build directory to the src/ folder.
10
-#
11
-SRCDIR = @srcdir@/src
12
-
13
-#### The directory into which object code files should be written.
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
142
#
153
#
16
-OBJDIR = ./bld
17
-
18
-#### C Compiler and options for use in building executables that
19
-# will run on the platform that is doing the build. This is used
20
-# to compile code-generator programs as part of the build process.
21
-# See TCC below for the C compiler for building the finished binary.
22
-#
23
-BCC = @CC_FOR_BUILD@
24
-
25
-#### The suffix to add to final executable file. When cross-compiling
26
-# to windows, make this ".exe". Otherwise leave it blank.
27
-#
28
-E = @EXEEXT@
29
-
30
-TCC = @CC@
31
-
32
-#### Tcl shell for use in running the fossil testsuite. If you do not
33
-# care about testing the end result, this can be blank.
34
-#
35
-TCLSH = tclsh
36
-
37
-LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
38
-TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
39
-INSTALLDIR = $(DESTDIR)@prefix@/bin
40
-USE_SYSTEM_SQLFORM_CHECK_KIND = disable
41
-
42
-include $(SRCDIR)/main.mk
43
-
44
-distclean: clean
45
- rm -f autoconfi
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
@@ -1,45 +1,9 @@
1 #!/usr/bin/make
2 #
3 # This is the top-level makefile for Fossil when the build is occurring
4 # on a unix platform. This works out-of-the-box on most unix platforms.
5 # But you are free to vary some of the definitions if desired.
6 #
7 #### The toplevel directory of the source tree. Fossil can be built
8 # in a directory that is separate from the source tree. Just change
9 # the following to point from the build directory to the src/ folder.
10 #
11 SRCDIR = @srcdir@/src
12
13 #### The directory into which object code files should be written.
14 #
15 #
16 OBJDIR = ./bld
17
18 #### C Compiler and options for use in building executables that
19 # will run on the platform that is doing the build. This is used
20 # to compile code-generator programs as part of the build process.
21 # See TCC below for the C compiler for building the finished binary.
22 #
23 BCC = @CC_FOR_BUILD@
24
25 #### The suffix to add to final executable file. When cross-compiling
26 # to windows, make this ".exe". Otherwise leave it blank.
27 #
28 E = @EXEEXT@
29
30 TCC = @CC@
31
32 #### Tcl shell for use in running the fossil testsuite. If you do not
33 # care about testing the end result, this can be blank.
34 #
35 TCLSH = tclsh
36
37 LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
38 TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
39 INSTALLDIR = $(DESTDIR)@prefix@/bin
40 USE_SYSTEM_SQLFORM_CHECK_KIND = disable
41
42 include $(SRCDIR)/main.mk
43
44 distclean: clean
45 rm -f autoconfi
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,45 +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 @@
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 -1
--- auto.def
+++ auto.def
@@ -166,7 +166,7 @@
166166
if {![cc-check-functions getpassphrase]} {
167167
# Haiku needs this
168168
cc-check-function-in-lib getpass bsd
169169
}
170170
171
-make-template GNUmakefile.in
171
+make-template Makefile.in
172172
make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
173173
--- auto.def
+++ auto.def
@@ -166,7 +166,7 @@
166 if {![cc-check-functions getpassphrase]} {
167 # Haiku needs this
168 cc-check-function-in-lib getpass bsd
169 }
170
171 make-template GNUmakefile.in
172 make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
173
--- auto.def
+++ auto.def
@@ -166,7 +166,7 @@
166 if {![cc-check-functions getpassphrase]} {
167 # Haiku needs this
168 cc-check-function-in-lib getpass bsd
169 }
170
171 make-template Makefile.in
172 make-config-header autoconfig.h -auto {USE_* FOSSIL_*}
173
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -1,7 +1,7 @@
11
#!/bin/sh
2
-# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
2
+# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
33
# All rights reserved
44
# vim:se syntax=tcl:
55
# \
66
dir=`dirname "$0"`; exec `"$dir/find-tclsh" || echo false` "$0" "$@"
77
@@ -84,11 +84,11 @@
8484
help:=local => "display help and options. Optionally specify a module name, such as --help=system"
8585
version => "display the version of autosetup"
8686
ref:=text manual:=text
8787
reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
8888
debug => "display debugging output as autosetup runs"
89
- install => "install autosetup to the current directory (in the 'autosetup/' subdirectory)"
89
+ install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)"
9090
force init => "create an initial 'configure' script if none exists"
9191
# Undocumented options
9292
option-checking=1
9393
nopager
9494
quiet
@@ -133,13 +133,13 @@
133133
if {[opt-bool init]} {
134134
use init
135135
autosetup_init
136136
}
137137
138
- if {[opt-bool install]} {
138
+ if {[opt-val install] ne ""} {
139139
use install
140
- autosetup_install
140
+ autosetup_install [opt-val install]
141141
}
142142
143143
if {![file exists $autosetup(autodef)]} {
144144
# Check for invalid option first
145145
options {}
@@ -1299,12 +1299,13 @@
12991299
# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
13001300
# All rights reserved
13011301
13021302
# Module which can install autosetup
13031303
1304
-proc autosetup_install {} {
1304
+proc autosetup_install {dir} {
13051305
if {[catch {
1306
+ cd $dir
13061307
file mkdir autosetup
13071308
13081309
set f [open autosetup/autosetup w]
13091310
13101311
set publicmodules {}
13111312
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -1,7 +1,7 @@
1 #!/bin/sh
2 # Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
3 # All rights reserved
4 # vim:se syntax=tcl:
5 # \
6 dir=`dirname "$0"`; exec `"$dir/find-tclsh" || echo false` "$0" "$@"
7
@@ -84,11 +84,11 @@
84 help:=local => "display help and options. Optionally specify a module name, such as --help=system"
85 version => "display the version of autosetup"
86 ref:=text manual:=text
87 reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
88 debug => "display debugging output as autosetup runs"
89 install => "install autosetup to the current directory (in the 'autosetup/' subdirectory)"
90 force init => "create an initial 'configure' script if none exists"
91 # Undocumented options
92 option-checking=1
93 nopager
94 quiet
@@ -133,13 +133,13 @@
133 if {[opt-bool init]} {
134 use init
135 autosetup_init
136 }
137
138 if {[opt-bool install]} {
139 use install
140 autosetup_install
141 }
142
143 if {![file exists $autosetup(autodef)]} {
144 # Check for invalid option first
145 options {}
@@ -1299,12 +1299,13 @@
1299 # Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
1300 # All rights reserved
1301
1302 # Module which can install autosetup
1303
1304 proc autosetup_install {} {
1305 if {[catch {
 
1306 file mkdir autosetup
1307
1308 set f [open autosetup/autosetup w]
1309
1310 set publicmodules {}
1311
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -1,7 +1,7 @@
1 #!/bin/sh
2 # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
3 # All rights reserved
4 # vim:se syntax=tcl:
5 # \
6 dir=`dirname "$0"`; exec `"$dir/find-tclsh" || echo false` "$0" "$@"
7
@@ -84,11 +84,11 @@
84 help:=local => "display help and options. Optionally specify a module name, such as --help=system"
85 version => "display the version of autosetup"
86 ref:=text manual:=text
87 reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
88 debug => "display debugging output as autosetup runs"
89 install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)"
90 force init => "create an initial 'configure' script if none exists"
91 # Undocumented options
92 option-checking=1
93 nopager
94 quiet
@@ -133,13 +133,13 @@
133 if {[opt-bool init]} {
134 use init
135 autosetup_init
136 }
137
138 if {[opt-val install] ne ""} {
139 use install
140 autosetup_install [opt-val install]
141 }
142
143 if {![file exists $autosetup(autodef)]} {
144 # Check for invalid option first
145 options {}
@@ -1299,12 +1299,13 @@
1299 # Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
1300 # All rights reserved
1301
1302 # Module which can install autosetup
1303
1304 proc autosetup_install {dir} {
1305 if {[catch {
1306 cd $dir
1307 file mkdir autosetup
1308
1309 set f [open autosetup/autosetup w]
1310
1311 set publicmodules {}
1312
--- autosetup/find-tclsh
+++ autosetup/find-tclsh
@@ -10,5 +10,6 @@
1010
for cc in ${CC_FOR_BUILD:-cc} gcc; do
1111
{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
1212
"$d/jimsh0" "$d/test-tclsh" && exit 0
1313
done
1414
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
15
+echo false
1516
--- autosetup/find-tclsh
+++ autosetup/find-tclsh
@@ -10,5 +10,6 @@
10 for cc in ${CC_FOR_BUILD:-cc} gcc; do
11 { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
12 "$d/jimsh0" "$d/test-tclsh" && exit 0
13 done
14 echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
 
15
--- autosetup/find-tclsh
+++ autosetup/find-tclsh
@@ -10,5 +10,6 @@
10 for cc in ${CC_FOR_BUILD:-cc} gcc; do
11 { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
12 "$d/jimsh0" "$d/test-tclsh" && exit 0
13 done
14 echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
15 echo false
16
+27 -41
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -2597,11 +2597,11 @@
25972597
25982598
static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
25992599
{
26002600
AioFile *af = Jim_CmdPrivData(interp);
26012601
2602
- static const char *options[] = {
2602
+ static const char * const options[] = {
26032603
"none",
26042604
"line",
26052605
"full",
26062606
NULL
26072607
};
@@ -5156,17 +5156,17 @@
51565156
return result;
51575157
}
51585158
51595159
void Jim_ReapDetachedPids(struct WaitInfoTable *table)
51605160
{
5161
+ struct WaitInfo *waitPtr;
5162
+ int count;
5163
+
51615164
if (!table) {
51625165
return;
51635166
}
51645167
5165
- struct WaitInfo *waitPtr;
5166
- int count;
5167
-
51685168
for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
51695169
if (waitPtr->flags & WI_DETACHED) {
51705170
int status;
51715171
int pid = waitpid(waitPtr->pid, &status, WNOHANG);
51725172
if (pid > 0) {
@@ -6365,30 +6365,30 @@
63656365
return JIM_OK;
63666366
}
63676367
int Jim_InitStaticExtensions(Jim_Interp *interp)
63686368
{
63696369
extern int Jim_bootstrapInit(Jim_Interp *);
6370
-Jim_bootstrapInit(interp);
63716370
extern int Jim_aioInit(Jim_Interp *);
6372
-Jim_aioInit(interp);
63736371
extern int Jim_readdirInit(Jim_Interp *);
6374
-Jim_readdirInit(interp);
63756372
extern int Jim_globInit(Jim_Interp *);
6376
-Jim_globInit(interp);
63776373
extern int Jim_regexpInit(Jim_Interp *);
6378
-Jim_regexpInit(interp);
63796374
extern int Jim_fileInit(Jim_Interp *);
6375
+extern int Jim_execInit(Jim_Interp *);
6376
+extern int Jim_clockInit(Jim_Interp *);
6377
+extern int Jim_arrayInit(Jim_Interp *);
6378
+extern int Jim_stdlibInit(Jim_Interp *);
6379
+extern int Jim_tclcompatInit(Jim_Interp *);
6380
+Jim_bootstrapInit(interp);
6381
+Jim_aioInit(interp);
6382
+Jim_readdirInit(interp);
6383
+Jim_globInit(interp);
6384
+Jim_regexpInit(interp);
63806385
Jim_fileInit(interp);
6381
-extern int Jim_execInit(Jim_Interp *);
63826386
Jim_execInit(interp);
6383
-extern int Jim_clockInit(Jim_Interp *);
63846387
Jim_clockInit(interp);
6385
-extern int Jim_arrayInit(Jim_Interp *);
63866388
Jim_arrayInit(interp);
6387
-extern int Jim_stdlibInit(Jim_Interp *);
63886389
Jim_stdlibInit(interp);
6389
-extern int Jim_tclcompatInit(Jim_Interp *);
63906390
Jim_tclcompatInit(interp);
63916391
return JIM_OK;
63926392
}
63936393
63946394
/* Jim - A small embeddable Tcl interpreter
@@ -16669,15 +16669,16 @@
1666916669
i = 1;
1667016670
for (d = 0; d < cmd->u.proc.argListLen; d++) {
1667116671
Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
1667216672
if (d == cmd->u.proc.argsPos) {
1667316673
/* assign $args */
16674
+ Jim_Obj *listObjPtr;
1667416675
int argsLen = 0;
1667516676
if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
1667616677
argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
1667716678
}
16678
- Jim_Obj *listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
16679
+ listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
1667916680
1668016681
/* It is possible to rename args. */
1668116682
if (cmd->u.proc.arglist[d].defaultObjPtr) {
1668216683
nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
1668316684
}
@@ -16813,11 +16814,10 @@
1681316814
{
1681416815
FILE *fp;
1681516816
char *buf;
1681616817
Jim_Obj *scriptObjPtr;
1681716818
Jim_Obj *prevScriptObj;
16818
- Jim_Stack *prevLocalProcs;
1681916819
struct stat sb;
1682016820
int retcode;
1682116821
int readlen;
1682216822
struct JimParseResult result;
1682316823
@@ -16872,20 +16872,12 @@
1687216872
}
1687316873
1687416874
prevScriptObj = interp->currentScriptObj;
1687516875
interp->currentScriptObj = scriptObjPtr;
1687616876
16877
- /* Install a new stack for local procs */
16878
- prevLocalProcs = interp->localProcs;
16879
- interp->localProcs = NULL;
16880
-
1688116877
retcode = Jim_EvalObj(interp, scriptObjPtr);
1688216878
16883
- /* Delete any local procs */
16884
- JimDeleteLocalProcs(interp);
16885
- interp->localProcs = prevLocalProcs;
16886
-
1688716879
/* Handle the JIM_RETURN return code */
1688816880
if (retcode == JIM_RETURN) {
1688916881
if (--interp->returnLevel <= 0) {
1689016882
retcode = interp->returnCode;
1689116883
interp->returnCode = JIM_OK;
@@ -18366,11 +18358,11 @@
1836618358
}
1836718359
1836818360
/* [lsort] */
1836918361
static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
1837018362
{
18371
- const char *options[] = {
18363
+ static const char * const options[] = {
1837218364
"-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
1837318365
};
1837418366
enum
1837518367
{ OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
1837618368
Jim_Obj *resObj;
@@ -18488,11 +18480,11 @@
1848818480
1848918481
/* [debug] */
1849018482
static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1849118483
{
1849218484
#ifdef JIM_DEBUG_COMMAND
18493
- const char *options[] = {
18485
+ static const char * const options[] = {
1849418486
"refcount", "objcount", "objects", "invstr", "scriptlen", "exprlen",
1849518487
"exprbc", "show",
1849618488
NULL
1849718489
};
1849818490
enum
@@ -18693,32 +18685,23 @@
1869318685
1869418686
/* [eval] */
1869518687
static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1869618688
{
1869718689
int rc;
18698
- Jim_Stack *prevLocalProcs;
1869918690
1870018691
if (argc < 2) {
1870118692
Jim_WrongNumArgs(interp, 1, argv, "script ?...?");
1870218693
return JIM_ERR;
1870318694
}
1870418695
18705
- /* Install a new stack for local procs */
18706
- prevLocalProcs = interp->localProcs;
18707
- interp->localProcs = NULL;
18708
-
1870918696
if (argc == 2) {
1871018697
rc = Jim_EvalObj(interp, argv[1]);
1871118698
}
1871218699
else {
1871318700
rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
1871418701
}
1871518702
18716
- /* Delete any local procs */
18717
- JimDeleteLocalProcs(interp);
18718
- interp->localProcs = prevLocalProcs;
18719
-
1872018703
if (rc == JIM_ERR) {
1872118704
/* eval is "interesting", so add a stack frame here */
1872218705
interp->addStackTrace++;
1872318706
}
1872418707
return rc;
@@ -19504,12 +19487,12 @@
1950419487
else {
1950519488
exitCode = Jim_EvalObj(interp, argv[0]);
1950619489
}
1950719490
interp->signal_level -= sig;
1950819491
19509
- /* Catch or pass through? Only the first 64 codes can be passed through */
19510
- if (exitCode >= 0 && exitCode < (int)sizeof(mask) && ((1 << exitCode) & mask) == 0) {
19492
+ /* Catch or pass through? Only the first 32/64 codes can be passed through */
19493
+ if (exitCode >= 0 && exitCode < (int)sizeof(mask) * 8 && ((1 << exitCode) & mask) == 0) {
1951119494
/* Not caught, pass it up */
1951219495
return exitCode;
1951319496
}
1951419497
1951519498
if (sig && exitCode == JIM_SIGNAL) {
@@ -19736,11 +19719,11 @@
1973619719
/* [dict] */
1973719720
static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1973819721
{
1973919722
Jim_Obj *objPtr;
1974019723
int option;
19741
- const char *options[] = {
19724
+ static const char * const options[] = {
1974219725
"create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
1974319726
};
1974419727
enum
1974519728
{
1974619729
OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
@@ -19852,11 +19835,11 @@
1985219835
}
1985319836
1985419837
/* [subst] */
1985519838
static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1985619839
{
19857
- const char *options[] = {
19840
+ static const char * const options[] = {
1985819841
"-nobackslashes", "-nocommands", "-novariables", NULL
1985919842
};
1986019843
enum
1986119844
{ OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES };
1986219845
int i;
@@ -21399,10 +21382,11 @@
2139921382
#endif
2140021383
#include <errno.h>
2140121384
#include <string.h>
2140221385
2140321386
#ifdef USE_LINENOISE
21387
+#include <unistd.h>
2140421388
#include "linenoise.h"
2140521389
#else
2140621390
2140721391
#define MAX_LINE_LEN 512
2140821392
@@ -21427,11 +21411,11 @@
2142721411
char *history_file = NULL;
2142821412
#ifdef USE_LINENOISE
2142921413
const char *home;
2143021414
2143121415
home = getenv("HOME");
21432
- if (home) {
21416
+ if (home && isatty(STDIN_FILENO)) {
2143321417
int history_len = strlen(home) + sizeof("/.jim_history");
2143421418
history_file = Jim_Alloc(history_len);
2143521419
snprintf(history_file, history_len, "%s/.jim_history", home);
2143621420
linenoiseHistoryLoad(history_file);
2143721421
}
@@ -21504,11 +21488,13 @@
2150421488
Jim_DecrRefCount(interp, scriptObjPtr);
2150521489
continue;
2150621490
}
2150721491
2150821492
linenoiseHistoryAdd(Jim_String(scriptObjPtr));
21509
- linenoiseHistorySave(history_file);
21493
+ if (history_file) {
21494
+ linenoiseHistorySave(history_file);
21495
+ }
2151021496
#endif
2151121497
retcode = Jim_EvalObj(interp, scriptObjPtr);
2151221498
Jim_DecrRefCount(interp, scriptObjPtr);
2151321499
2151421500
2151521501
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -2597,11 +2597,11 @@
2597
2598 static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2599 {
2600 AioFile *af = Jim_CmdPrivData(interp);
2601
2602 static const char *options[] = {
2603 "none",
2604 "line",
2605 "full",
2606 NULL
2607 };
@@ -5156,17 +5156,17 @@
5156 return result;
5157 }
5158
5159 void Jim_ReapDetachedPids(struct WaitInfoTable *table)
5160 {
 
 
 
5161 if (!table) {
5162 return;
5163 }
5164
5165 struct WaitInfo *waitPtr;
5166 int count;
5167
5168 for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
5169 if (waitPtr->flags & WI_DETACHED) {
5170 int status;
5171 int pid = waitpid(waitPtr->pid, &status, WNOHANG);
5172 if (pid > 0) {
@@ -6365,30 +6365,30 @@
6365 return JIM_OK;
6366 }
6367 int Jim_InitStaticExtensions(Jim_Interp *interp)
6368 {
6369 extern int Jim_bootstrapInit(Jim_Interp *);
6370 Jim_bootstrapInit(interp);
6371 extern int Jim_aioInit(Jim_Interp *);
6372 Jim_aioInit(interp);
6373 extern int Jim_readdirInit(Jim_Interp *);
6374 Jim_readdirInit(interp);
6375 extern int Jim_globInit(Jim_Interp *);
6376 Jim_globInit(interp);
6377 extern int Jim_regexpInit(Jim_Interp *);
6378 Jim_regexpInit(interp);
6379 extern int Jim_fileInit(Jim_Interp *);
 
 
 
 
 
 
 
 
 
 
6380 Jim_fileInit(interp);
6381 extern int Jim_execInit(Jim_Interp *);
6382 Jim_execInit(interp);
6383 extern int Jim_clockInit(Jim_Interp *);
6384 Jim_clockInit(interp);
6385 extern int Jim_arrayInit(Jim_Interp *);
6386 Jim_arrayInit(interp);
6387 extern int Jim_stdlibInit(Jim_Interp *);
6388 Jim_stdlibInit(interp);
6389 extern int Jim_tclcompatInit(Jim_Interp *);
6390 Jim_tclcompatInit(interp);
6391 return JIM_OK;
6392 }
6393
6394 /* Jim - A small embeddable Tcl interpreter
@@ -16669,15 +16669,16 @@
16669 i = 1;
16670 for (d = 0; d < cmd->u.proc.argListLen; d++) {
16671 Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
16672 if (d == cmd->u.proc.argsPos) {
16673 /* assign $args */
 
16674 int argsLen = 0;
16675 if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
16676 argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
16677 }
16678 Jim_Obj *listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
16679
16680 /* It is possible to rename args. */
16681 if (cmd->u.proc.arglist[d].defaultObjPtr) {
16682 nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
16683 }
@@ -16813,11 +16814,10 @@
16813 {
16814 FILE *fp;
16815 char *buf;
16816 Jim_Obj *scriptObjPtr;
16817 Jim_Obj *prevScriptObj;
16818 Jim_Stack *prevLocalProcs;
16819 struct stat sb;
16820 int retcode;
16821 int readlen;
16822 struct JimParseResult result;
16823
@@ -16872,20 +16872,12 @@
16872 }
16873
16874 prevScriptObj = interp->currentScriptObj;
16875 interp->currentScriptObj = scriptObjPtr;
16876
16877 /* Install a new stack for local procs */
16878 prevLocalProcs = interp->localProcs;
16879 interp->localProcs = NULL;
16880
16881 retcode = Jim_EvalObj(interp, scriptObjPtr);
16882
16883 /* Delete any local procs */
16884 JimDeleteLocalProcs(interp);
16885 interp->localProcs = prevLocalProcs;
16886
16887 /* Handle the JIM_RETURN return code */
16888 if (retcode == JIM_RETURN) {
16889 if (--interp->returnLevel <= 0) {
16890 retcode = interp->returnCode;
16891 interp->returnCode = JIM_OK;
@@ -18366,11 +18358,11 @@
18366 }
18367
18368 /* [lsort] */
18369 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
18370 {
18371 const char *options[] = {
18372 "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
18373 };
18374 enum
18375 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
18376 Jim_Obj *resObj;
@@ -18488,11 +18480,11 @@
18488
18489 /* [debug] */
18490 static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18491 {
18492 #ifdef JIM_DEBUG_COMMAND
18493 const char *options[] = {
18494 "refcount", "objcount", "objects", "invstr", "scriptlen", "exprlen",
18495 "exprbc", "show",
18496 NULL
18497 };
18498 enum
@@ -18693,32 +18685,23 @@
18693
18694 /* [eval] */
18695 static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18696 {
18697 int rc;
18698 Jim_Stack *prevLocalProcs;
18699
18700 if (argc < 2) {
18701 Jim_WrongNumArgs(interp, 1, argv, "script ?...?");
18702 return JIM_ERR;
18703 }
18704
18705 /* Install a new stack for local procs */
18706 prevLocalProcs = interp->localProcs;
18707 interp->localProcs = NULL;
18708
18709 if (argc == 2) {
18710 rc = Jim_EvalObj(interp, argv[1]);
18711 }
18712 else {
18713 rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
18714 }
18715
18716 /* Delete any local procs */
18717 JimDeleteLocalProcs(interp);
18718 interp->localProcs = prevLocalProcs;
18719
18720 if (rc == JIM_ERR) {
18721 /* eval is "interesting", so add a stack frame here */
18722 interp->addStackTrace++;
18723 }
18724 return rc;
@@ -19504,12 +19487,12 @@
19504 else {
19505 exitCode = Jim_EvalObj(interp, argv[0]);
19506 }
19507 interp->signal_level -= sig;
19508
19509 /* Catch or pass through? Only the first 64 codes can be passed through */
19510 if (exitCode >= 0 && exitCode < (int)sizeof(mask) && ((1 << exitCode) & mask) == 0) {
19511 /* Not caught, pass it up */
19512 return exitCode;
19513 }
19514
19515 if (sig && exitCode == JIM_SIGNAL) {
@@ -19736,11 +19719,11 @@
19736 /* [dict] */
19737 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19738 {
19739 Jim_Obj *objPtr;
19740 int option;
19741 const char *options[] = {
19742 "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
19743 };
19744 enum
19745 {
19746 OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
@@ -19852,11 +19835,11 @@
19852 }
19853
19854 /* [subst] */
19855 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19856 {
19857 const char *options[] = {
19858 "-nobackslashes", "-nocommands", "-novariables", NULL
19859 };
19860 enum
19861 { OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES };
19862 int i;
@@ -21399,10 +21382,11 @@
21399 #endif
21400 #include <errno.h>
21401 #include <string.h>
21402
21403 #ifdef USE_LINENOISE
 
21404 #include "linenoise.h"
21405 #else
21406
21407 #define MAX_LINE_LEN 512
21408
@@ -21427,11 +21411,11 @@
21427 char *history_file = NULL;
21428 #ifdef USE_LINENOISE
21429 const char *home;
21430
21431 home = getenv("HOME");
21432 if (home) {
21433 int history_len = strlen(home) + sizeof("/.jim_history");
21434 history_file = Jim_Alloc(history_len);
21435 snprintf(history_file, history_len, "%s/.jim_history", home);
21436 linenoiseHistoryLoad(history_file);
21437 }
@@ -21504,11 +21488,13 @@
21504 Jim_DecrRefCount(interp, scriptObjPtr);
21505 continue;
21506 }
21507
21508 linenoiseHistoryAdd(Jim_String(scriptObjPtr));
21509 linenoiseHistorySave(history_file);
 
 
21510 #endif
21511 retcode = Jim_EvalObj(interp, scriptObjPtr);
21512 Jim_DecrRefCount(interp, scriptObjPtr);
21513
21514
21515
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -2597,11 +2597,11 @@
2597
2598 static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
2599 {
2600 AioFile *af = Jim_CmdPrivData(interp);
2601
2602 static const char * const options[] = {
2603 "none",
2604 "line",
2605 "full",
2606 NULL
2607 };
@@ -5156,17 +5156,17 @@
5156 return result;
5157 }
5158
5159 void Jim_ReapDetachedPids(struct WaitInfoTable *table)
5160 {
5161 struct WaitInfo *waitPtr;
5162 int count;
5163
5164 if (!table) {
5165 return;
5166 }
5167
 
 
 
5168 for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
5169 if (waitPtr->flags & WI_DETACHED) {
5170 int status;
5171 int pid = waitpid(waitPtr->pid, &status, WNOHANG);
5172 if (pid > 0) {
@@ -6365,30 +6365,30 @@
6365 return JIM_OK;
6366 }
6367 int Jim_InitStaticExtensions(Jim_Interp *interp)
6368 {
6369 extern int Jim_bootstrapInit(Jim_Interp *);
 
6370 extern int Jim_aioInit(Jim_Interp *);
 
6371 extern int Jim_readdirInit(Jim_Interp *);
 
6372 extern int Jim_globInit(Jim_Interp *);
 
6373 extern int Jim_regexpInit(Jim_Interp *);
 
6374 extern int Jim_fileInit(Jim_Interp *);
6375 extern int Jim_execInit(Jim_Interp *);
6376 extern int Jim_clockInit(Jim_Interp *);
6377 extern int Jim_arrayInit(Jim_Interp *);
6378 extern int Jim_stdlibInit(Jim_Interp *);
6379 extern int Jim_tclcompatInit(Jim_Interp *);
6380 Jim_bootstrapInit(interp);
6381 Jim_aioInit(interp);
6382 Jim_readdirInit(interp);
6383 Jim_globInit(interp);
6384 Jim_regexpInit(interp);
6385 Jim_fileInit(interp);
 
6386 Jim_execInit(interp);
 
6387 Jim_clockInit(interp);
 
6388 Jim_arrayInit(interp);
 
6389 Jim_stdlibInit(interp);
 
6390 Jim_tclcompatInit(interp);
6391 return JIM_OK;
6392 }
6393
6394 /* Jim - A small embeddable Tcl interpreter
@@ -16669,15 +16669,16 @@
16669 i = 1;
16670 for (d = 0; d < cmd->u.proc.argListLen; d++) {
16671 Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
16672 if (d == cmd->u.proc.argsPos) {
16673 /* assign $args */
16674 Jim_Obj *listObjPtr;
16675 int argsLen = 0;
16676 if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
16677 argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
16678 }
16679 listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
16680
16681 /* It is possible to rename args. */
16682 if (cmd->u.proc.arglist[d].defaultObjPtr) {
16683 nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
16684 }
@@ -16813,11 +16814,10 @@
16814 {
16815 FILE *fp;
16816 char *buf;
16817 Jim_Obj *scriptObjPtr;
16818 Jim_Obj *prevScriptObj;
 
16819 struct stat sb;
16820 int retcode;
16821 int readlen;
16822 struct JimParseResult result;
16823
@@ -16872,20 +16872,12 @@
16872 }
16873
16874 prevScriptObj = interp->currentScriptObj;
16875 interp->currentScriptObj = scriptObjPtr;
16876
 
 
 
 
16877 retcode = Jim_EvalObj(interp, scriptObjPtr);
16878
 
 
 
 
16879 /* Handle the JIM_RETURN return code */
16880 if (retcode == JIM_RETURN) {
16881 if (--interp->returnLevel <= 0) {
16882 retcode = interp->returnCode;
16883 interp->returnCode = JIM_OK;
@@ -18366,11 +18358,11 @@
18358 }
18359
18360 /* [lsort] */
18361 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
18362 {
18363 static const char * const options[] = {
18364 "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
18365 };
18366 enum
18367 { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
18368 Jim_Obj *resObj;
@@ -18488,11 +18480,11 @@
18480
18481 /* [debug] */
18482 static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18483 {
18484 #ifdef JIM_DEBUG_COMMAND
18485 static const char * const options[] = {
18486 "refcount", "objcount", "objects", "invstr", "scriptlen", "exprlen",
18487 "exprbc", "show",
18488 NULL
18489 };
18490 enum
@@ -18693,32 +18685,23 @@
18685
18686 /* [eval] */
18687 static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18688 {
18689 int rc;
 
18690
18691 if (argc < 2) {
18692 Jim_WrongNumArgs(interp, 1, argv, "script ?...?");
18693 return JIM_ERR;
18694 }
18695
 
 
 
 
18696 if (argc == 2) {
18697 rc = Jim_EvalObj(interp, argv[1]);
18698 }
18699 else {
18700 rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
18701 }
18702
 
 
 
 
18703 if (rc == JIM_ERR) {
18704 /* eval is "interesting", so add a stack frame here */
18705 interp->addStackTrace++;
18706 }
18707 return rc;
@@ -19504,12 +19487,12 @@
19487 else {
19488 exitCode = Jim_EvalObj(interp, argv[0]);
19489 }
19490 interp->signal_level -= sig;
19491
19492 /* Catch or pass through? Only the first 32/64 codes can be passed through */
19493 if (exitCode >= 0 && exitCode < (int)sizeof(mask) * 8 && ((1 << exitCode) & mask) == 0) {
19494 /* Not caught, pass it up */
19495 return exitCode;
19496 }
19497
19498 if (sig && exitCode == JIM_SIGNAL) {
@@ -19736,11 +19719,11 @@
19719 /* [dict] */
19720 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19721 {
19722 Jim_Obj *objPtr;
19723 int option;
19724 static const char * const options[] = {
19725 "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
19726 };
19727 enum
19728 {
19729 OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
@@ -19852,11 +19835,11 @@
19835 }
19836
19837 /* [subst] */
19838 static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
19839 {
19840 static const char * const options[] = {
19841 "-nobackslashes", "-nocommands", "-novariables", NULL
19842 };
19843 enum
19844 { OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES };
19845 int i;
@@ -21399,10 +21382,11 @@
21382 #endif
21383 #include <errno.h>
21384 #include <string.h>
21385
21386 #ifdef USE_LINENOISE
21387 #include <unistd.h>
21388 #include "linenoise.h"
21389 #else
21390
21391 #define MAX_LINE_LEN 512
21392
@@ -21427,11 +21411,11 @@
21411 char *history_file = NULL;
21412 #ifdef USE_LINENOISE
21413 const char *home;
21414
21415 home = getenv("HOME");
21416 if (home && isatty(STDIN_FILENO)) {
21417 int history_len = strlen(home) + sizeof("/.jim_history");
21418 history_file = Jim_Alloc(history_len);
21419 snprintf(history_file, history_len, "%s/.jim_history", home);
21420 linenoiseHistoryLoad(history_file);
21421 }
@@ -21504,11 +21488,13 @@
21488 Jim_DecrRefCount(interp, scriptObjPtr);
21489 continue;
21490 }
21491
21492 linenoiseHistoryAdd(Jim_String(scriptObjPtr));
21493 if (history_file) {
21494 linenoiseHistorySave(history_file);
21495 }
21496 #endif
21497 retcode = Jim_EvalObj(interp, scriptObjPtr);
21498 Jim_DecrRefCount(interp, scriptObjPtr);
21499
21500
21501
+1
--- src/db.c
+++ src/db.c
@@ -1747,10 +1747,11 @@
17471747
{ "self-register", 0, 0, 0, "off" },
17481748
{ "ssl-ca-location",0, 40, 0, "" },
17491749
{ "ssl-identity", 0, 40, 0, "" },
17501750
{ "ssh-command", 0, 32, 0, "" },
17511751
{ "web-browser", 0, 32, 0, "" },
1752
+ { "white-foreground", 0, 0, 0, "off" },
17521753
{ 0,0,0,0,0 }
17531754
};
17541755
17551756
/*
17561757
** COMMAND: settings
17571758
--- src/db.c
+++ src/db.c
@@ -1747,10 +1747,11 @@
1747 { "self-register", 0, 0, 0, "off" },
1748 { "ssl-ca-location",0, 40, 0, "" },
1749 { "ssl-identity", 0, 40, 0, "" },
1750 { "ssh-command", 0, 32, 0, "" },
1751 { "web-browser", 0, 32, 0, "" },
 
1752 { 0,0,0,0,0 }
1753 };
1754
1755 /*
1756 ** COMMAND: settings
1757
--- src/db.c
+++ src/db.c
@@ -1747,10 +1747,11 @@
1747 { "self-register", 0, 0, 0, "off" },
1748 { "ssl-ca-location",0, 40, 0, "" },
1749 { "ssl-identity", 0, 40, 0, "" },
1750 { "ssh-command", 0, 32, 0, "" },
1751 { "web-browser", 0, 32, 0, "" },
1752 { "white-foreground", 0, 0, 0, "off" },
1753 { 0,0,0,0,0 }
1754 };
1755
1756 /*
1757 ** COMMAND: settings
1758
+1
--- src/db.c
+++ src/db.c
@@ -1747,10 +1747,11 @@
17471747
{ "self-register", 0, 0, 0, "off" },
17481748
{ "ssl-ca-location",0, 40, 0, "" },
17491749
{ "ssl-identity", 0, 40, 0, "" },
17501750
{ "ssh-command", 0, 32, 0, "" },
17511751
{ "web-browser", 0, 32, 0, "" },
1752
+ { "white-foreground", 0, 0, 0, "off" },
17521753
{ 0,0,0,0,0 }
17531754
};
17541755
17551756
/*
17561757
** COMMAND: settings
17571758
--- src/db.c
+++ src/db.c
@@ -1747,10 +1747,11 @@
1747 { "self-register", 0, 0, 0, "off" },
1748 { "ssl-ca-location",0, 40, 0, "" },
1749 { "ssl-identity", 0, 40, 0, "" },
1750 { "ssh-command", 0, 32, 0, "" },
1751 { "web-browser", 0, 32, 0, "" },
 
1752 { 0,0,0,0,0 }
1753 };
1754
1755 /*
1756 ** COMMAND: settings
1757
--- src/db.c
+++ src/db.c
@@ -1747,10 +1747,11 @@
1747 { "self-register", 0, 0, 0, "off" },
1748 { "ssl-ca-location",0, 40, 0, "" },
1749 { "ssl-identity", 0, 40, 0, "" },
1750 { "ssh-command", 0, 32, 0, "" },
1751 { "web-browser", 0, 32, 0, "" },
1752 { "white-foreground", 0, 0, 0, "off" },
1753 { 0,0,0,0,0 }
1754 };
1755
1756 /*
1757 ** COMMAND: settings
1758
+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
--- 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
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -589,11 +589,11 @@
589589
clean:
590590
-del $(OBJDIR)\*.obj
591591
-del *.obj *_.c *.h *.map
592592
593593
realclean:
594
- -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
594
+ -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
595595
596596
}
597597
foreach s [lsort $src] {
598598
writeln "\$(OBJDIR)\\$s\$O : ${s}_.c ${s}.h"
599599
writeln "\t\$(TCC) -o\$@ -c ${s}_.c\n"
@@ -727,11 +727,11 @@
727727
-del $(OX)\*.obj
728728
-del *.obj *_.c *.h *.map
729729
-del headers linkopts
730730
731731
realclean:
732
- -del $(APPNAME) translate$E mkindex$E makeheaders$E version$E
732
+ -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E
733733
734734
}
735735
foreach s [lsort $src] {
736736
writeln "\$(OX)\\$s\$O : ${s}_.c ${s}.h"
737737
writeln "\t\$(TCC) /Fo\$@ -c ${s}_.c\n"
738738
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -589,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 version$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"
@@ -727,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 version$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"
738
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -589,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"
@@ -727,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"
738
+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
+1212 -471
--- 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.
@@ -648,13 +648,13 @@
648648
**
649649
** See also: [sqlite3_libversion()],
650650
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651651
** [sqlite_version()] and [sqlite_source_id()].
652652
*/
653
-#define SQLITE_VERSION "3.7.7"
654
-#define SQLITE_VERSION_NUMBER 3007007
655
-#define SQLITE_SOURCE_ID "2011-06-24 11:29:51 9b191bb4c7c1e1b12b188c0b3eee1f8f587887c8"
653
+#define SQLITE_VERSION "3.7.8"
654
+#define SQLITE_VERSION_NUMBER 3007008
655
+#define SQLITE_SOURCE_ID "2011-07-19 18:29:00 ed5f0aad6b21066bacd01521e82c22e96991f400"
656656
657657
/*
658658
** CAPI3REF: Run-Time Library Version Numbers
659659
** KEYWORDS: sqlite3_version, sqlite3_sourceid
660660
**
@@ -1282,20 +1282,37 @@
12821282
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
12831283
** VFSes do not need this signal and should silently ignore this opcode.
12841284
** Applications should not call [sqlite3_file_control()] with this
12851285
** opcode as doing so may disrupt the operation of the specialized VFSes
12861286
** that do require it.
1287
+**
1288
+** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
1289
+** retry counts and intervals for certain disk I/O operations for the
1290
+** windows [VFS] in order to work to provide robustness against
1291
+** anti-virus programs. By default, the windows VFS will retry file read,
1292
+** file write, and file delete opertions up to 10 times, with a delay
1293
+** of 25 milliseconds before the first retry and with the delay increasing
1294
+** by an additional 25 milliseconds with each subsequent retry. This
1295
+** opcode allows those to values (10 retries and 25 milliseconds of delay)
1296
+** to be adjusted. The values are changed for all database connections
1297
+** within the same process. The argument is a pointer to an array of two
1298
+** integers where the first integer i the new retry count and the second
1299
+** integer is the delay. If either integer is negative, then the setting
1300
+** is not changed but instead the prior value of that setting is written
1301
+** into the array entry, allowing the current retry settings to be
1302
+** interrogated. The zDbName parameter is ignored.
1303
+**
12871304
*/
12881305
#define SQLITE_FCNTL_LOCKSTATE 1
12891306
#define SQLITE_GET_LOCKPROXYFILE 2
12901307
#define SQLITE_SET_LOCKPROXYFILE 3
12911308
#define SQLITE_LAST_ERRNO 4
12921309
#define SQLITE_FCNTL_SIZE_HINT 5
12931310
#define SQLITE_FCNTL_CHUNK_SIZE 6
12941311
#define SQLITE_FCNTL_FILE_POINTER 7
12951312
#define SQLITE_FCNTL_SYNC_OMITTED 8
1296
-
1313
+#define SQLITE_FCNTL_WIN32_AV_RETRY 9
12971314
12981315
/*
12991316
** CAPI3REF: Mutex Handle
13001317
**
13011318
** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -9558,10 +9575,11 @@
95589575
#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
95599576
#define SQLITE_IndexCover 0x10 /* Disable index covering table */
95609577
#define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
95619578
#define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
95629579
#define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */
9580
+#define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */
95639581
#define SQLITE_OptMask 0xff /* Mask of all disablable opts */
95649582
95659583
/*
95669584
** Possible values for the sqlite.magic field.
95679585
** The numbers are obtained at random and have no special meaning, other
@@ -10449,10 +10467,11 @@
1044910467
Table *pTab; /* An SQL table corresponding to zName */
1045010468
Select *pSelect; /* A SELECT statement used in place of a table name */
1045110469
u8 isPopulated; /* Temporary table associated with SELECT is populated */
1045210470
u8 jointype; /* Type of join between this able and the previous */
1045310471
u8 notIndexed; /* True if there is a NOT INDEXED clause */
10472
+ u8 isCorrelated; /* True if sub-query is correlated */
1045410473
#ifndef SQLITE_OMIT_EXPLAIN
1045510474
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
1045610475
#endif
1045710476
int iCursor; /* The VDBE cursor number used to access this table */
1045810477
Expr *pOn; /* The ON clause of a join */
@@ -10568,10 +10587,11 @@
1056810587
struct WhereInfo {
1056910588
Parse *pParse; /* Parsing and code generating context */
1057010589
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
1057110590
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
1057210591
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
10592
+ u8 eDistinct;
1057310593
SrcList *pTabList; /* List of tables in the join */
1057410594
int iTop; /* The very beginning of the WHERE loop */
1057510595
int iContinue; /* Jump here to continue with next record */
1057610596
int iBreak; /* Jump here to break out of the loop */
1057710597
int nLevel; /* Number of nested loop */
@@ -10579,10 +10599,13 @@
1057910599
double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
1058010600
double nRowOut; /* Estimated number of output rows */
1058110601
WhereLevel a[1]; /* Information about each nest loop in WHERE */
1058210602
};
1058310603
10604
+#define WHERE_DISTINCT_UNIQUE 1
10605
+#define WHERE_DISTINCT_ORDERED 2
10606
+
1058410607
/*
1058510608
** A NameContext defines a context in which to resolve table and column
1058610609
** names. The context consists of a list of tables (the pSrcList) field and
1058710610
** a list of named expression (pEList). The named expression list may
1058810611
** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
@@ -11340,11 +11363,11 @@
1134011363
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
1134111364
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
1134211365
#endif
1134311366
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
1134411367
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11345
-SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
11368
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
1134611369
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
1134711370
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
1134811371
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
1134911372
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
1135011373
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
@@ -15841,11 +15864,11 @@
1584115864
** Free an outstanding memory allocation.
1584215865
**
1584315866
** This function assumes that the necessary mutexes, if any, are
1584415867
** already held by the caller. Hence "Unsafe".
1584515868
*/
15846
-void memsys3FreeUnsafe(void *pOld){
15869
+static void memsys3FreeUnsafe(void *pOld){
1584715870
Mem3Block *p = (Mem3Block*)pOld;
1584815871
int i;
1584915872
u32 size, x;
1585015873
assert( sqlite3_mutex_held(mem3.mutex) );
1585115874
assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
@@ -15916,21 +15939,21 @@
1591615939
}
1591715940
1591815941
/*
1591915942
** Free memory.
1592015943
*/
15921
-void memsys3Free(void *pPrior){
15944
+static void memsys3Free(void *pPrior){
1592215945
assert( pPrior );
1592315946
memsys3Enter();
1592415947
memsys3FreeUnsafe(pPrior);
1592515948
memsys3Leave();
1592615949
}
1592715950
1592815951
/*
1592915952
** Change the size of an existing memory allocation
1593015953
*/
15931
-void *memsys3Realloc(void *pPrior, int nBytes){
15954
+static void *memsys3Realloc(void *pPrior, int nBytes){
1593215955
int nOld;
1593315956
void *p;
1593415957
if( pPrior==0 ){
1593515958
return sqlite3_malloc(nBytes);
1593615959
}
@@ -25143,11 +25166,13 @@
2514325166
case EINVAL:
2514425167
case ENOTCONN:
2514525168
case ENODEV:
2514625169
case ENXIO:
2514725170
case ENOENT:
25171
+#ifdef ESTALE /* ESTALE is not defined on Interix systems */
2514825172
case ESTALE:
25173
+#endif
2514925174
case ENOSYS:
2515025175
/* these should force the client to close the file and reconnect */
2515125176
2515225177
default:
2515325178
return sqliteIOErr;
@@ -31820,10 +31845,58 @@
3182031845
iLine, iErrno, zFunc, zPath, zMsg
3182131846
);
3182231847
3182331848
return errcode;
3182431849
}
31850
+
31851
+/*
31852
+** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
31853
+** will be retried following a locking error - probably caused by
31854
+** antivirus software. Also the initial delay before the first retry.
31855
+** The delay increases linearly with each retry.
31856
+*/
31857
+#ifndef SQLITE_WIN32_IOERR_RETRY
31858
+# define SQLITE_WIN32_IOERR_RETRY 10
31859
+#endif
31860
+#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
31861
+# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
31862
+#endif
31863
+static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
31864
+static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
31865
+
31866
+/*
31867
+** If a ReadFile() or WriteFile() error occurs, invoke this routine
31868
+** to see if it should be retried. Return TRUE to retry. Return FALSE
31869
+** to give up with an error.
31870
+*/
31871
+static int retryIoerr(int *pnRetry){
31872
+ DWORD e;
31873
+ if( *pnRetry>=win32IoerrRetry ){
31874
+ return 0;
31875
+ }
31876
+ e = GetLastError();
31877
+ if( e==ERROR_ACCESS_DENIED ||
31878
+ e==ERROR_LOCK_VIOLATION ||
31879
+ e==ERROR_SHARING_VIOLATION ){
31880
+ Sleep(win32IoerrRetryDelay*(1+*pnRetry));
31881
+ ++*pnRetry;
31882
+ return 1;
31883
+ }
31884
+ return 0;
31885
+}
31886
+
31887
+/*
31888
+** Log a I/O error retry episode.
31889
+*/
31890
+static void logIoerr(int nRetry){
31891
+ if( nRetry ){
31892
+ sqlite3_log(SQLITE_IOERR,
31893
+ "delayed %dms for lock/sharing conflict",
31894
+ win32IoerrRetryDelay*nRetry*(nRetry+1)/2
31895
+ );
31896
+ }
31897
+}
3182531898
3182631899
#if SQLITE_OS_WINCE
3182731900
/*************************************************************************
3182831901
** This section contains code for WinCE only.
3182931902
*/
@@ -32238,22 +32311,25 @@
3223832311
int amt, /* Number of bytes to read */
3223932312
sqlite3_int64 offset /* Begin reading at this offset */
3224032313
){
3224132314
winFile *pFile = (winFile*)id; /* file handle */
3224232315
DWORD nRead; /* Number of bytes actually read from file */
32316
+ int nRetry = 0; /* Number of retrys */
3224332317
3224432318
assert( id!=0 );
3224532319
SimulateIOError(return SQLITE_IOERR_READ);
3224632320
OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
3224732321
3224832322
if( seekWinFile(pFile, offset) ){
3224932323
return SQLITE_FULL;
3225032324
}
32251
- if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
32325
+ while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
32326
+ if( retryIoerr(&nRetry) ) continue;
3225232327
pFile->lastErrno = GetLastError();
3225332328
return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
3225432329
}
32330
+ logIoerr(nRetry);
3225532331
if( nRead<(DWORD)amt ){
3225632332
/* Unread parts of the buffer must be zero-filled */
3225732333
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
3225832334
return SQLITE_IOERR_SHORT_READ;
3225932335
}
@@ -32271,10 +32347,11 @@
3227132347
int amt, /* Number of bytes to write */
3227232348
sqlite3_int64 offset /* Offset into the file to begin writing at */
3227332349
){
3227432350
int rc; /* True if error has occured, else false */
3227532351
winFile *pFile = (winFile*)id; /* File handle */
32352
+ int nRetry = 0; /* Number of retries */
3227632353
3227732354
assert( amt>0 );
3227832355
assert( pFile );
3227932356
SimulateIOError(return SQLITE_IOERR_WRITE);
3228032357
SimulateDiskfullError(return SQLITE_FULL);
@@ -32285,11 +32362,16 @@
3228532362
if( rc==0 ){
3228632363
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
3228732364
int nRem = amt; /* Number of bytes yet to be written */
3228832365
DWORD nWrite; /* Bytes written by each WriteFile() call */
3228932366
32290
- while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
32367
+ while( nRem>0 ){
32368
+ if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
32369
+ if( retryIoerr(&nRetry) ) continue;
32370
+ break;
32371
+ }
32372
+ if( nWrite<=0 ) break;
3229132373
aRem += nWrite;
3229232374
nRem -= nWrite;
3229332375
}
3229432376
if( nRem>0 ){
3229532377
pFile->lastErrno = GetLastError();
@@ -32301,10 +32383,12 @@
3230132383
if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
3230232384
|| ( pFile->lastErrno==ERROR_DISK_FULL )){
3230332385
return SQLITE_FULL;
3230432386
}
3230532387
return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
32388
+ }else{
32389
+ logIoerr(nRetry);
3230632390
}
3230732391
return SQLITE_OK;
3230832392
}
3230932393
3231032394
/*
@@ -32716,10 +32800,24 @@
3271632800
SimulateIOErrorBenign(0);
3271732801
return SQLITE_OK;
3271832802
}
3271932803
case SQLITE_FCNTL_SYNC_OMITTED: {
3272032804
return SQLITE_OK;
32805
+ }
32806
+ case SQLITE_FCNTL_WIN32_AV_RETRY: {
32807
+ int *a = (int*)pArg;
32808
+ if( a[0]>0 ){
32809
+ win32IoerrRetry = a[0];
32810
+ }else{
32811
+ a[0] = win32IoerrRetry;
32812
+ }
32813
+ if( a[1]>0 ){
32814
+ win32IoerrRetryDelay = a[1];
32815
+ }else{
32816
+ a[1] = win32IoerrRetryDelay;
32817
+ }
32818
+ return SQLITE_OK;
3272132819
}
3272232820
}
3272332821
return SQLITE_NOTFOUND;
3272432822
}
3272532823
@@ -33734,19 +33832,17 @@
3373433832
** file open, we will be unable to delete it. To work around this
3373533833
** problem, we delay 100 milliseconds and try to delete again. Up
3373633834
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
3373733835
** up and returning an error.
3373833836
*/
33739
-#define MX_DELETION_ATTEMPTS 5
3374033837
static int winDelete(
3374133838
sqlite3_vfs *pVfs, /* Not used on win32 */
3374233839
const char *zFilename, /* Name of file to delete */
3374333840
int syncDir /* Not used on win32 */
3374433841
){
3374533842
int cnt = 0;
33746
- DWORD rc;
33747
- DWORD error = 0;
33843
+ int rc;
3374833844
void *zConverted;
3374933845
UNUSED_PARAMETER(pVfs);
3375033846
UNUSED_PARAMETER(syncDir);
3375133847
3375233848
SimulateIOError(return SQLITE_IOERR_DELETE);
@@ -33753,38 +33849,34 @@
3375333849
zConverted = convertUtf8Filename(zFilename);
3375433850
if( zConverted==0 ){
3375533851
return SQLITE_NOMEM;
3375633852
}
3375733853
if( isNT() ){
33758
- do{
33759
- DeleteFileW(zConverted);
33760
- }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
33761
- || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33762
- && (++cnt < MX_DELETION_ATTEMPTS)
33763
- && (Sleep(100), 1) );
33854
+ rc = 1;
33855
+ while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
33856
+ (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}
33857
+ rc = rc ? SQLITE_OK : SQLITE_ERROR;
3376433858
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3376533859
** Since the ASCII version of these Windows API do not exist for WINCE,
3376633860
** it's important to not reference them for WINCE builds.
3376733861
*/
3376833862
#if SQLITE_OS_WINCE==0
3376933863
}else{
33770
- do{
33771
- DeleteFileA(zConverted);
33772
- }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
33773
- || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33774
- && (++cnt < MX_DELETION_ATTEMPTS)
33775
- && (Sleep(100), 1) );
33864
+ rc = 1;
33865
+ while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
33866
+ (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}
33867
+ rc = rc ? SQLITE_OK : SQLITE_ERROR;
3377633868
#endif
3377733869
}
33870
+ if( rc ){
33871
+ rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
33872
+ }else{
33873
+ logIoerr(cnt);
33874
+ }
3377833875
free(zConverted);
33779
- OSTRACE(("DELETE \"%s\" %s\n", zFilename,
33780
- ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
33781
- "ok" : "failed" ));
33782
-
33783
- return ( (rc == INVALID_FILE_ATTRIBUTES)
33784
- && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
33785
- winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
33876
+ OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
33877
+ return rc;
3378633878
}
3378733879
3378833880
/*
3378933881
** Check the existance and status of a file.
3379033882
*/
@@ -59049,10 +59141,11 @@
5904959141
nMem = 10;
5905059142
}
5905159143
memset(zCsr, 0, zEnd-zCsr);
5905259144
zCsr += (zCsr - (u8*)0)&7;
5905359145
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
59146
+ p->expired = 0;
5905459147
5905559148
/* Memory for registers, parameters, cursor, etc, is allocated in two
5905659149
** passes. On the first pass, we try to reuse unused space at the
5905759150
** end of the opcode array. If we are unable to satisfy all memory
5905859151
** requirements by reusing the opcode array tail, then the second
@@ -61277,11 +61370,11 @@
6127761370
sqlite3_mutex_enter(db->mutex);
6127861371
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
6127961372
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY
6128061373
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
6128161374
sqlite3_reset(pStmt);
61282
- v->expired = 0;
61375
+ assert( v->expired==0 );
6128361376
}
6128461377
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
6128561378
/* This case occurs after failing to recompile an sql statement.
6128661379
** The error message from the SQL compiler has already been loaded
6128761380
** into the database handle. This block copies the error message
@@ -65968,11 +66061,11 @@
6596866061
** automatically created table with root-page 1 (an BLOB_INTKEY table).
6596966062
*/
6597066063
if( pOp->p4.pKeyInfo ){
6597166064
int pgno;
6597266065
assert( pOp->p4type==P4_KEYINFO );
65973
- rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY);
66066
+ rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
6597466067
if( rc==SQLITE_OK ){
6597566068
assert( pgno==MASTER_ROOT+1 );
6597666069
rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
6597766070
(KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
6597866071
u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
@@ -71007,15 +71100,29 @@
7100771100
/* Recursively resolve names in all subqueries
7100871101
*/
7100971102
for(i=0; i<p->pSrc->nSrc; i++){
7101071103
struct SrcList_item *pItem = &p->pSrc->a[i];
7101171104
if( pItem->pSelect ){
71105
+ NameContext *pNC; /* Used to iterate name contexts */
71106
+ int nRef = 0; /* Refcount for pOuterNC and outer contexts */
7101271107
const char *zSavedContext = pParse->zAuthContext;
71108
+
71109
+ /* Count the total number of references to pOuterNC and all of its
71110
+ ** parent contexts. After resolving references to expressions in
71111
+ ** pItem->pSelect, check if this value has changed. If so, then
71112
+ ** SELECT statement pItem->pSelect must be correlated. Set the
71113
+ ** pItem->isCorrelated flag if this is the case. */
71114
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
71115
+
7101371116
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
7101471117
sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
7101571118
pParse->zAuthContext = zSavedContext;
7101671119
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
71120
+
71121
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
71122
+ assert( pItem->isCorrelated==0 && nRef<=0 );
71123
+ pItem->isCorrelated = (nRef!=0);
7101771124
}
7101871125
}
7101971126
7102071127
/* If there are no aggregate functions in the result-set, and no GROUP BY
7102171128
** expression, do not allow aggregates in any of the other expressions.
@@ -72119,10 +72226,11 @@
7211972226
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
7212072227
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
7212172228
pNewItem->jointype = pOldItem->jointype;
7212272229
pNewItem->iCursor = pOldItem->iCursor;
7212372230
pNewItem->isPopulated = pOldItem->isPopulated;
72231
+ pNewItem->isCorrelated = pOldItem->isCorrelated;
7212472232
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
7212572233
pNewItem->notIndexed = pOldItem->notIndexed;
7212672234
pNewItem->pIndex = pOldItem->pIndex;
7212772235
pTab = pNewItem->pTab = pOldItem->pTab;
7212872236
if( pTab ){
@@ -80126,11 +80234,11 @@
8012680234
if( pStart ){
8012780235
assert( pEnd!=0 );
8012880236
/* A named index with an explicit CREATE INDEX statement */
8012980237
zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
8013080238
onError==OE_None ? "" : " UNIQUE",
80131
- pEnd->z - pName->z + 1,
80239
+ (int)(pEnd->z - pName->z) + 1,
8013280240
pName->z);
8013380241
}else{
8013480242
/* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
8013580243
/* zStmt = sqlite3MPrintf(""); */
8013680244
zStmt = 0;
@@ -81921,11 +82029,13 @@
8192182029
int regRowid; /* Actual register containing rowids */
8192282030
8192382031
/* Collect rowids of every row to be deleted.
8192482032
*/
8192582033
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
81926
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
82034
+ pWInfo = sqlite3WhereBegin(
82035
+ pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
82036
+ );
8192782037
if( pWInfo==0 ) goto delete_from_cleanup;
8192882038
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
8192982039
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
8193082040
if( db->flags & SQLITE_CountRows ){
8193182041
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
@@ -84368,11 +84478,11 @@
8436884478
8436984479
/* Create VDBE to loop through the entries in pSrc that match the WHERE
8437084480
** clause. If the constraint is not deferred, throw an exception for
8437184481
** each row found. Otherwise, for deferred constraints, increment the
8437284482
** deferred constraint counter by nIncr for each row selected. */
84373
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0);
84483
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
8437484484
if( nIncr>0 && pFKey->isDeferred==0 ){
8437584485
sqlite3ParseToplevel(pParse)->mayAbort = 1;
8437684486
}
8437784487
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
8437884488
if( pWInfo ){
@@ -87235,10 +87345,13 @@
8723587345
int (*strnicmp)(const char*,const char*,int);
8723687346
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
8723787347
int (*wal_autocheckpoint)(sqlite3*,int);
8723887348
int (*wal_checkpoint)(sqlite3*,const char*);
8723987349
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
87350
+ int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
87351
+ int (*vtab_config)(sqlite3*,int op,...);
87352
+ int (*vtab_on_conflict)(sqlite3*);
8724087353
};
8724187354
8724287355
/*
8724387356
** The following macros redefine the API routines so that they are
8724487357
** redirected throught the global sqlite3_api structure.
@@ -87435,10 +87548,13 @@
8743587548
#define sqlite3_strnicmp sqlite3_api->strnicmp
8743687549
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
8743787550
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
8743887551
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
8743987552
#define sqlite3_wal_hook sqlite3_api->wal_hook
87553
+#define sqlite3_blob_reopen sqlite3_api->blob_reopen
87554
+#define sqlite3_vtab_config sqlite3_api->vtab_config
87555
+#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
8744087556
#endif /* SQLITE_CORE */
8744187557
8744287558
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
8744387559
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
8744487560
@@ -87509,10 +87625,12 @@
8750987625
8751087626
#ifdef SQLITE_OMIT_VIRTUALTABLE
8751187627
# define sqlite3_create_module 0
8751287628
# define sqlite3_create_module_v2 0
8751387629
# define sqlite3_declare_vtab 0
87630
+# define sqlite3_vtab_config 0
87631
+# define sqlite3_vtab_on_conflict 0
8751487632
#endif
8751587633
8751687634
#ifdef SQLITE_OMIT_SHARED_CACHE
8751787635
# define sqlite3_enable_shared_cache 0
8751887636
#endif
@@ -87532,10 +87650,11 @@
8753287650
#define sqlite3_blob_bytes 0
8753387651
#define sqlite3_blob_close 0
8753487652
#define sqlite3_blob_open 0
8753587653
#define sqlite3_blob_read 0
8753687654
#define sqlite3_blob_write 0
87655
+#define sqlite3_blob_reopen 0
8753787656
#endif
8753887657
8753987658
/*
8754087659
** The following structure contains pointers to all SQLite API routines.
8754187660
** A pointer to this structure is passed into extensions when they are
@@ -87797,10 +87916,13 @@
8779787916
#else
8779887917
0,
8779987918
0,
8780087919
0,
8780187920
#endif
87921
+ sqlite3_blob_reopen,
87922
+ sqlite3_vtab_config,
87923
+ sqlite3_vtab_on_conflict,
8780287924
};
8780387925
8780487926
/*
8780587927
** Attempt to load an SQLite extension library contained in the file
8780687928
** zFile. The entry point is zProc. zProc may be 0 in which case a
@@ -94186,10 +94308,11 @@
9418694308
Expr *pHaving; /* The HAVING clause. May be NULL */
9418794309
int isDistinct; /* True if the DISTINCT keyword is present */
9418894310
int distinct; /* Table to use for the distinct set */
9418994311
int rc = 1; /* Value to return from this function */
9419094312
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
94313
+ int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
9419194314
AggInfo sAggInfo; /* Information used by aggregate queries */
9419294315
int iEnd; /* Address of the end of the query */
9419394316
sqlite3 *db; /* The database connection */
9419494317
9419594318
#ifndef SQLITE_OMIT_EXPLAIN
@@ -94312,20 +94435,10 @@
9431294435
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
9431394436
return rc;
9431494437
}
9431594438
#endif
9431694439
94317
- /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
94318
- ** GROUP BY might use an index, DISTINCT never does.
94319
- */
94320
- assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
94321
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
94322
- p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
94323
- pGroupBy = p->pGroupBy;
94324
- p->selFlags &= ~SF_Distinct;
94325
- }
94326
-
9432794440
/* If there is both a GROUP BY and an ORDER BY clause and they are
9432894441
** identical, then disable the ORDER BY clause since the GROUP BY
9432994442
** will cause elements to come out in the correct order. This is
9433094443
** an optimization - the correct answer should result regardless.
9433194444
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
@@ -94333,10 +94446,34 @@
9433394446
*/
9433494447
if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
9433594448
&& (db->flags & SQLITE_GroupByOrder)==0 ){
9433694449
pOrderBy = 0;
9433794450
}
94451
+
94452
+ /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
94453
+ ** if the select-list is the same as the ORDER BY list, then this query
94454
+ ** can be rewritten as a GROUP BY. In other words, this:
94455
+ **
94456
+ ** SELECT DISTINCT xyz FROM ... ORDER BY xyz
94457
+ **
94458
+ ** is transformed to:
94459
+ **
94460
+ ** SELECT xyz FROM ... GROUP BY xyz
94461
+ **
94462
+ ** The second form is preferred as a single index (or temp-table) may be
94463
+ ** used for both the ORDER BY and DISTINCT processing. As originally
94464
+ ** written the query must use a temp-table for at least one of the ORDER
94465
+ ** BY and DISTINCT, and an index or separate temp-table for the other.
94466
+ */
94467
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
94468
+ && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
94469
+ ){
94470
+ p->selFlags &= ~SF_Distinct;
94471
+ p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
94472
+ pGroupBy = p->pGroupBy;
94473
+ pOrderBy = 0;
94474
+ }
9433894475
9433994476
/* If there is an ORDER BY clause, then this sorting
9434094477
** index might end up being unused if the data can be
9434194478
** extracted in pre-sorted order. If that is the case, then the
9434294479
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
@@ -94369,26 +94506,25 @@
9436994506
9437094507
/* Open a virtual index to use for the distinct set.
9437194508
*/
9437294509
if( p->selFlags & SF_Distinct ){
9437394510
KeyInfo *pKeyInfo;
94374
- assert( isAgg || pGroupBy );
9437594511
distinct = pParse->nTab++;
9437694512
pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
94377
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
94378
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
94513
+ addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
94514
+ (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
9437994515
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
9438094516
}else{
94381
- distinct = -1;
94517
+ distinct = addrDistinctIndex = -1;
9438294518
}
9438394519
9438494520
/* Aggregate and non-aggregate queries are handled differently */
9438594521
if( !isAgg && pGroupBy==0 ){
94386
- /* This case is for non-aggregate queries
94387
- ** Begin the database scan
94388
- */
94389
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
94522
+ ExprList *pDist = (isDistinct ? p->pEList : 0);
94523
+
94524
+ /* Begin the database scan. */
94525
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
9439094526
if( pWInfo==0 ) goto select_end;
9439194527
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
9439294528
9439394529
/* If sorting index that was created by a prior OP_OpenEphemeral
9439494530
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -94397,14 +94533,56 @@
9439794533
if( addrSortIndex>=0 && pOrderBy==0 ){
9439894534
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
9439994535
p->addrOpenEphm[2] = -1;
9440094536
}
9440194537
94402
- /* Use the standard inner loop
94403
- */
94404
- assert(!isDistinct);
94405
- selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
94538
+ if( pWInfo->eDistinct ){
94539
+ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
94540
+
94541
+ assert( addrDistinctIndex>0 );
94542
+ pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
94543
+
94544
+ assert( isDistinct );
94545
+ assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
94546
+ || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
94547
+ );
94548
+ distinct = -1;
94549
+ if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
94550
+ int iJump;
94551
+ int iExpr;
94552
+ int iFlag = ++pParse->nMem;
94553
+ int iBase = pParse->nMem+1;
94554
+ int iBase2 = iBase + pEList->nExpr;
94555
+ pParse->nMem += (pEList->nExpr*2);
94556
+
94557
+ /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
94558
+ ** OP_Integer initializes the "first row" flag. */
94559
+ pOp->opcode = OP_Integer;
94560
+ pOp->p1 = 1;
94561
+ pOp->p2 = iFlag;
94562
+
94563
+ sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
94564
+ iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
94565
+ sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
94566
+ for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
94567
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
94568
+ sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
94569
+ sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
94570
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
94571
+ }
94572
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
94573
+
94574
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
94575
+ assert( sqlite3VdbeCurrentAddr(v)==iJump );
94576
+ sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
94577
+ }else{
94578
+ pOp->opcode = OP_Noop;
94579
+ }
94580
+ }
94581
+
94582
+ /* Use the standard inner loop. */
94583
+ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
9440694584
pWInfo->iContinue, pWInfo->iBreak);
9440794585
9440894586
/* End the database scan loop.
9440994587
*/
9441094588
sqlite3WhereEnd(pWInfo);
@@ -94510,11 +94688,11 @@
9451094688
** This might involve two separate loops with an OP_Sort in between, or
9451194689
** it might be a single loop that uses an index to extract information
9451294690
** in the right order to begin with.
9451394691
*/
9451494692
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
94515
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
94693
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
9451694694
if( pWInfo==0 ) goto select_end;
9451794695
if( pGroupBy==0 ){
9451894696
/* The optimizer is able to deliver rows in group by order so
9451994697
** we do not have to sort. The OP_OpenEphemeral table will be
9452094698
** cancelled later because we still need to use the pKeyInfo
@@ -94772,11 +94950,11 @@
9477294950
/* This case runs if the aggregate has no GROUP BY clause. The
9477394951
** processing is much simpler since there is only a single row
9477494952
** of output.
9477594953
*/
9477694954
resetAccumulator(pParse, &sAggInfo);
94777
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
94955
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
9477894956
if( pWInfo==0 ){
9477994957
sqlite3ExprListDelete(db, pDel);
9478094958
goto select_end;
9478194959
}
9478294960
updateAccumulator(pParse, &sAggInfo);
@@ -95248,19 +95426,32 @@
9524895426
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
9524995427
if( iDb<0 ){
9525095428
goto trigger_cleanup;
9525195429
}
9525295430
}
95431
+ if( !pTableName || db->mallocFailed ){
95432
+ goto trigger_cleanup;
95433
+ }
95434
+
95435
+ /* A long-standing parser bug is that this syntax was allowed:
95436
+ **
95437
+ ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
95438
+ ** ^^^^^^^^
95439
+ **
95440
+ ** To maintain backwards compatibility, ignore the database
95441
+ ** name on pTableName if we are reparsing our of SQLITE_MASTER.
95442
+ */
95443
+ if( db->init.busy && iDb!=1 ){
95444
+ sqlite3DbFree(db, pTableName->a[0].zDatabase);
95445
+ pTableName->a[0].zDatabase = 0;
95446
+ }
9525395447
9525495448
/* If the trigger name was unqualified, and the table is a temp table,
9525595449
** then set iDb to 1 to create the trigger in the temporary database.
9525695450
** If sqlite3SrcListLookup() returns 0, indicating the table does not
9525795451
** exist, the error is caught by the block below.
9525895452
*/
95259
- if( !pTableName || db->mallocFailed ){
95260
- goto trigger_cleanup;
95261
- }
9526295453
pTab = sqlite3SrcListLookup(pParse, pTableName);
9526395454
if( db->init.busy==0 && pName2->n==0 && pTab
9526495455
&& pTab->pSchema==db->aDb[1].pSchema ){
9526595456
iDb = 1;
9526695457
}
@@ -96554,11 +96745,13 @@
9655496745
}
9655596746
9655696747
/* Begin the database scan
9655796748
*/
9655896749
sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
96559
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
96750
+ pWInfo = sqlite3WhereBegin(
96751
+ pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
96752
+ );
9656096753
if( pWInfo==0 ) goto update_cleanup;
9656196754
okOnePass = pWInfo->okOnePass;
9656296755
9656396756
/* Remember the rowid of every item to be updated.
9656496757
*/
@@ -98580,10 +98773,11 @@
9858098773
#define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
9858198774
#define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
9858298775
#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
9858398776
#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
9858498777
#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
98778
+#define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
9858598779
9858698780
/*
9858798781
** Initialize a preallocated WhereClause structure.
9858898782
*/
9858998783
static void whereClauseInit(
@@ -99724,10 +99918,166 @@
9972499918
}
9972599919
}
9972699920
return 0;
9972799921
}
9972899922
99923
+/*
99924
+** This function searches the expression list passed as the second argument
99925
+** for an expression of type TK_COLUMN that refers to the same column and
99926
+** uses the same collation sequence as the iCol'th column of index pIdx.
99927
+** Argument iBase is the cursor number used for the table that pIdx refers
99928
+** to.
99929
+**
99930
+** If such an expression is found, its index in pList->a[] is returned. If
99931
+** no expression is found, -1 is returned.
99932
+*/
99933
+static int findIndexCol(
99934
+ Parse *pParse, /* Parse context */
99935
+ ExprList *pList, /* Expression list to search */
99936
+ int iBase, /* Cursor for table associated with pIdx */
99937
+ Index *pIdx, /* Index to match column of */
99938
+ int iCol /* Column of index to match */
99939
+){
99940
+ int i;
99941
+ const char *zColl = pIdx->azColl[iCol];
99942
+
99943
+ for(i=0; i<pList->nExpr; i++){
99944
+ Expr *p = pList->a[i].pExpr;
99945
+ if( p->op==TK_COLUMN
99946
+ && p->iColumn==pIdx->aiColumn[iCol]
99947
+ && p->iTable==iBase
99948
+ ){
99949
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
99950
+ if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
99951
+ return i;
99952
+ }
99953
+ }
99954
+ }
99955
+
99956
+ return -1;
99957
+}
99958
+
99959
+/*
99960
+** This routine determines if pIdx can be used to assist in processing a
99961
+** DISTINCT qualifier. In other words, it tests whether or not using this
99962
+** index for the outer loop guarantees that rows with equal values for
99963
+** all expressions in the pDistinct list are delivered grouped together.
99964
+**
99965
+** For example, the query
99966
+**
99967
+** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
99968
+**
99969
+** can benefit from any index on columns "b" and "c".
99970
+*/
99971
+static int isDistinctIndex(
99972
+ Parse *pParse, /* Parsing context */
99973
+ WhereClause *pWC, /* The WHERE clause */
99974
+ Index *pIdx, /* The index being considered */
99975
+ int base, /* Cursor number for the table pIdx is on */
99976
+ ExprList *pDistinct, /* The DISTINCT expressions */
99977
+ int nEqCol /* Number of index columns with == */
99978
+){
99979
+ Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
99980
+ int i; /* Iterator variable */
99981
+
99982
+ if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
99983
+ testcase( pDistinct->nExpr==BMS-1 );
99984
+
99985
+ /* Loop through all the expressions in the distinct list. If any of them
99986
+ ** are not simple column references, return early. Otherwise, test if the
99987
+ ** WHERE clause contains a "col=X" clause. If it does, the expression
99988
+ ** can be ignored. If it does not, and the column does not belong to the
99989
+ ** same table as index pIdx, return early. Finally, if there is no
99990
+ ** matching "col=X" expression and the column is on the same table as pIdx,
99991
+ ** set the corresponding bit in variable mask.
99992
+ */
99993
+ for(i=0; i<pDistinct->nExpr; i++){
99994
+ WhereTerm *pTerm;
99995
+ Expr *p = pDistinct->a[i].pExpr;
99996
+ if( p->op!=TK_COLUMN ) return 0;
99997
+ pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
99998
+ if( pTerm ){
99999
+ Expr *pX = pTerm->pExpr;
100000
+ CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
100001
+ CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
100002
+ if( p1==p2 ) continue;
100003
+ }
100004
+ if( p->iTable!=base ) return 0;
100005
+ mask |= (((Bitmask)1) << i);
100006
+ }
100007
+
100008
+ for(i=nEqCol; mask && i<pIdx->nColumn; i++){
100009
+ int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
100010
+ if( iExpr<0 ) break;
100011
+ mask &= ~(((Bitmask)1) << iExpr);
100012
+ }
100013
+
100014
+ return (mask==0);
100015
+}
100016
+
100017
+
100018
+/*
100019
+** Return true if the DISTINCT expression-list passed as the third argument
100020
+** is redundant. A DISTINCT list is redundant if the database contains a
100021
+** UNIQUE index that guarantees that the result of the query will be distinct
100022
+** anyway.
100023
+*/
100024
+static int isDistinctRedundant(
100025
+ Parse *pParse,
100026
+ SrcList *pTabList,
100027
+ WhereClause *pWC,
100028
+ ExprList *pDistinct
100029
+){
100030
+ Table *pTab;
100031
+ Index *pIdx;
100032
+ int i;
100033
+ int iBase;
100034
+
100035
+ /* If there is more than one table or sub-select in the FROM clause of
100036
+ ** this query, then it will not be possible to show that the DISTINCT
100037
+ ** clause is redundant. */
100038
+ if( pTabList->nSrc!=1 ) return 0;
100039
+ iBase = pTabList->a[0].iCursor;
100040
+ pTab = pTabList->a[0].pTab;
100041
+
100042
+ /* If any of the expressions is an IPK column on table iBase, then return
100043
+ ** true. Note: The (p->iTable==iBase) part of this test may be false if the
100044
+ ** current SELECT is a correlated sub-query.
100045
+ */
100046
+ for(i=0; i<pDistinct->nExpr; i++){
100047
+ Expr *p = pDistinct->a[i].pExpr;
100048
+ if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
100049
+ }
100050
+
100051
+ /* Loop through all indices on the table, checking each to see if it makes
100052
+ ** the DISTINCT qualifier redundant. It does so if:
100053
+ **
100054
+ ** 1. The index is itself UNIQUE, and
100055
+ **
100056
+ ** 2. All of the columns in the index are either part of the pDistinct
100057
+ ** list, or else the WHERE clause contains a term of the form "col=X",
100058
+ ** where X is a constant value. The collation sequences of the
100059
+ ** comparison and select-list expressions must match those of the index.
100060
+ */
100061
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
100062
+ if( pIdx->onError==OE_None ) continue;
100063
+ for(i=0; i<pIdx->nColumn; i++){
100064
+ int iCol = pIdx->aiColumn[i];
100065
+ if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx)
100066
+ && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
100067
+ ){
100068
+ break;
100069
+ }
100070
+ }
100071
+ if( i==pIdx->nColumn ){
100072
+ /* This index implies that the DISTINCT qualifier is redundant. */
100073
+ return 1;
100074
+ }
100075
+ }
100076
+
100077
+ return 0;
100078
+}
99729100079
99730100080
/*
99731100081
** This routine decides if pIdx can be used to satisfy the ORDER BY
99732100082
** clause. If it can, it returns 1. If pIdx cannot satisfy the
99733100083
** ORDER BY clause, this routine returns 0.
@@ -99760,11 +100110,14 @@
99760100110
int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
99761100111
int nTerm; /* Number of ORDER BY terms */
99762100112
struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
99763100113
sqlite3 *db = pParse->db;
99764100114
99765
- assert( pOrderBy!=0 );
100115
+ if( !pOrderBy ) return 0;
100116
+ if( wsFlags & WHERE_COLUMN_IN ) return 0;
100117
+ if( pIdx->bUnordered ) return 0;
100118
+
99766100119
nTerm = pOrderBy->nExpr;
99767100120
assert( nTerm>0 );
99768100121
99769100122
/* Argument pIdx must either point to a 'real' named index structure,
99770100123
** or an index structure allocated on the stack by bestBtreeIndex() to
@@ -100073,10 +100426,14 @@
100073100426
double costTempIdx; /* per-query cost of the transient index */
100074100427
WhereTerm *pTerm; /* A single term of the WHERE clause */
100075100428
WhereTerm *pWCEnd; /* End of pWC->a[] */
100076100429
Table *pTable; /* Table tht might be indexed */
100077100430
100431
+ if( pParse->nQueryLoop<=(double)1 ){
100432
+ /* There is no point in building an automatic index for a single scan */
100433
+ return;
100434
+ }
100078100435
if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
100079100436
/* Automatic indices are disabled at run-time */
100080100437
return;
100081100438
}
100082100439
if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
@@ -100084,10 +100441,14 @@
100084100441
return;
100085100442
}
100086100443
if( pSrc->notIndexed ){
100087100444
/* The NOT INDEXED clause appears in the SQL. */
100088100445
return;
100446
+ }
100447
+ if( pSrc->isCorrelated ){
100448
+ /* The source is a correlated sub-query. No point in indexing it. */
100449
+ return;
100089100450
}
100090100451
100091100452
assert( pParse->nQueryLoop >= (double)1 );
100092100453
pTable = pSrc->pTab;
100093100454
nTableRow = pTable->nRowEst;
@@ -101016,10 +101377,11 @@
101016101377
WhereClause *pWC, /* The WHERE clause */
101017101378
struct SrcList_item *pSrc, /* The FROM clause term to search */
101018101379
Bitmask notReady, /* Mask of cursors not available for indexing */
101019101380
Bitmask notValid, /* Cursors not available for any purpose */
101020101381
ExprList *pOrderBy, /* The ORDER BY clause */
101382
+ ExprList *pDistinct, /* The select-list if query is DISTINCT */
101021101383
WhereCost *pCost /* Lowest cost query plan */
101022101384
){
101023101385
int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
101024101386
Index *pProbe; /* An index we are evaluating */
101025101387
Index *pIdx; /* Copy of pProbe, or zero for IPK index */
@@ -101156,11 +101518,12 @@
101156101518
int nEq; /* Number of == or IN terms matching index */
101157101519
int bInEst = 0; /* True if "x IN (SELECT...)" seen */
101158101520
int nInMul = 1; /* Number of distinct equalities to lookup */
101159101521
int estBound = 100; /* Estimated reduction in search space */
101160101522
int nBound = 0; /* Number of range constraints seen */
101161
- int bSort = 0; /* True if external sort required */
101523
+ int bSort = !!pOrderBy; /* True if external sort required */
101524
+ int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */
101162101525
int bLookup = 0; /* True if not a covering index */
101163101526
WhereTerm *pTerm; /* A single term of the WHERE clause */
101164101527
#ifdef SQLITE_ENABLE_STAT2
101165101528
WhereTerm *pFirstTerm = 0; /* First term matching the index */
101166101529
#endif
@@ -101220,21 +101583,24 @@
101220101583
101221101584
/* If there is an ORDER BY clause and the index being considered will
101222101585
** naturally scan rows in the required order, set the appropriate flags
101223101586
** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
101224101587
** will scan rows in a different order, set the bSort variable. */
101225
- if( pOrderBy ){
101226
- if( (wsFlags & WHERE_COLUMN_IN)==0
101227
- && pProbe->bUnordered==0
101228
- && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
101229
- nEq, wsFlags, &rev)
101230
- ){
101231
- wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
101232
- wsFlags |= (rev ? WHERE_REVERSE : 0);
101233
- }else{
101234
- bSort = 1;
101235
- }
101588
+ if( isSortingIndex(
101589
+ pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
101590
+ ){
101591
+ bSort = 0;
101592
+ wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
101593
+ wsFlags |= (rev ? WHERE_REVERSE : 0);
101594
+ }
101595
+
101596
+ /* If there is a DISTINCT qualifier and this index will scan rows in
101597
+ ** order of the DISTINCT expressions, clear bDist and set the appropriate
101598
+ ** flags in wsFlags. */
101599
+ if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
101600
+ bDist = 0;
101601
+ wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
101236101602
}
101237101603
101238101604
/* If currently calculating the cost of using an index (not the IPK
101239101605
** index), determine if all required column data may be obtained without
101240101606
** using the main table (i.e. if the index is a covering
@@ -101265,16 +101631,17 @@
101265101631
nRow = aiRowEst[0]/2;
101266101632
nInMul = (int)(nRow / aiRowEst[nEq]);
101267101633
}
101268101634
101269101635
#ifdef SQLITE_ENABLE_STAT2
101270
- /* If the constraint is of the form x=VALUE and histogram
101636
+ /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
101637
+ ** and we do not think that values of x are unique and if histogram
101271101638
** data is available for column x, then it might be possible
101272101639
** to get a better estimate on the number of rows based on
101273101640
** VALUE and how common that value is according to the histogram.
101274101641
*/
101275
- if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
101642
+ if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
101276101643
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
101277101644
testcase( pFirstTerm->eOperator==WO_EQ );
101278101645
testcase( pFirstTerm->eOperator==WO_ISNULL );
101279101646
whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
101280101647
}else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
@@ -101347,10 +101714,13 @@
101347101714
** difference and select C of 3.0.
101348101715
*/
101349101716
if( bSort ){
101350101717
cost += nRow*estLog(nRow)*3;
101351101718
}
101719
+ if( bDist ){
101720
+ cost += nRow*estLog(nRow)*3;
101721
+ }
101352101722
101353101723
/**** Cost of using this index has now been computed ****/
101354101724
101355101725
/* If there are additional constraints on this table that cannot
101356101726
** be used with the current index, but which might lower the number
@@ -101492,11 +101862,11 @@
101492101862
}
101493101863
sqlite3DbFree(pParse->db, p);
101494101864
}else
101495101865
#endif
101496101866
{
101497
- bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
101867
+ bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
101498101868
}
101499101869
}
101500101870
101501101871
/*
101502101872
** Disable a term in the WHERE clause. Except, do not disable the term
@@ -102454,11 +102824,11 @@
102454102824
for(ii=0; ii<pOrWc->nTerm; ii++){
102455102825
WhereTerm *pOrTerm = &pOrWc->a[ii];
102456102826
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
102457102827
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
102458102828
/* Loop through table entries that match term pOrTerm. */
102459
- pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
102829
+ pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0, 0,
102460102830
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
102461102831
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
102462102832
if( pSubWInfo ){
102463102833
explainOneScan(
102464102834
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -102695,10 +103065,11 @@
102695103065
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
102696103066
Parse *pParse, /* The parser context */
102697103067
SrcList *pTabList, /* A list of all tables to be scanned */
102698103068
Expr *pWhere, /* The WHERE clause */
102699103069
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
103070
+ ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
102700103071
u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
102701103072
){
102702103073
int i; /* Loop counter */
102703103074
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
102704103075
int nTabList; /* Number of elements in pTabList */
@@ -102754,10 +103125,14 @@
102754103125
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
102755103126
pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
102756103127
pWInfo->wctrlFlags = wctrlFlags;
102757103128
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
102758103129
pMaskSet = (WhereMaskSet*)&pWC[1];
103130
+
103131
+ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
103132
+ ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
103133
+ if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
102759103134
102760103135
/* Split the WHERE clause into separate subexpressions where each
102761103136
** subexpression is separated by an AND operator.
102762103137
*/
102763103138
initMaskSet(pMaskSet);
@@ -102821,10 +103196,19 @@
102821103196
*/
102822103197
exprAnalyzeAll(pTabList, pWC);
102823103198
if( db->mallocFailed ){
102824103199
goto whereBeginError;
102825103200
}
103201
+
103202
+ /* Check if the DISTINCT qualifier, if there is one, is redundant.
103203
+ ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
103204
+ ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
103205
+ */
103206
+ if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
103207
+ pDistinct = 0;
103208
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
103209
+ }
102826103210
102827103211
/* Chose the best index to use for each table in the FROM clause.
102828103212
**
102829103213
** This loop fills in the following fields:
102830103214
**
@@ -102905,10 +103289,11 @@
102905103289
Bitmask mask; /* Mask of tables not yet ready */
102906103290
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
102907103291
int doNotReorder; /* True if this table should not be reordered */
102908103292
WhereCost sCost; /* Cost information from best[Virtual]Index() */
102909103293
ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
103294
+ ExprList *pDist; /* DISTINCT clause for index to optimize */
102910103295
102911103296
doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
102912103297
if( j!=iFrom && doNotReorder ) break;
102913103298
m = getMask(pMaskSet, pTabItem->iCursor);
102914103299
if( (m & notReady)==0 ){
@@ -102915,10 +103300,11 @@
102915103300
if( j==iFrom ) iFrom++;
102916103301
continue;
102917103302
}
102918103303
mask = (isOptimal ? m : notReady);
102919103304
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
103305
+ pDist = (i==0 ? pDistinct : 0);
102920103306
if( pTabItem->pIndex==0 ) nUnconstrained++;
102921103307
102922103308
WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
102923103309
j, isOptimal));
102924103310
assert( pTabItem->pTab );
@@ -102929,11 +103315,11 @@
102929103315
&sCost, pp);
102930103316
}else
102931103317
#endif
102932103318
{
102933103319
bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
102934
- &sCost);
103320
+ pDist, &sCost);
102935103321
}
102936103322
assert( isOptimal || (sCost.used&notReady)==0 );
102937103323
102938103324
/* If an INDEXED BY clause is present, then the plan must use that
102939103325
** index if it uses any index at all */
@@ -102989,10 +103375,14 @@
102989103375
WHERETRACE(("*** Optimizer selects table %d for loop %d"
102990103376
" with cost=%g and nRow=%g\n",
102991103377
bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
102992103378
if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
102993103379
*ppOrderBy = 0;
103380
+ }
103381
+ if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
103382
+ assert( pWInfo->eDistinct==0 );
103383
+ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
102994103384
}
102995103385
andFlags &= bestPlan.plan.wsFlags;
102996103386
pLevel->plan = bestPlan.plan;
102997103387
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
102998103388
testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
@@ -111519,11 +111909,17 @@
111519111909
*/
111520111910
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
111521111911
# define SQLITE_ENABLE_FTS3
111522111912
#endif
111523111913
111524
-#ifdef SQLITE_ENABLE_FTS3
111914
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
111915
+
111916
+/* If not building as part of the core, include sqlite3ext.h. */
111917
+#ifndef SQLITE_CORE
111918
+SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
111919
+#endif
111920
+
111525111921
/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
111526111922
/************** Begin file fts3_tokenizer.h **********************************/
111527111923
/*
111528111924
** 2006 July 10
111529111925
**
@@ -112052,11 +112448,11 @@
112052112448
112053112449
sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
112054112450
int bFreeList; /* True if pList should be sqlite3_free()d */
112055112451
char *pList; /* Pointer to position list following iDocid */
112056112452
int nList; /* Length of position list */
112057
-} doclist;
112453
+};
112058112454
112059112455
/*
112060112456
** A "phrase" is a sequence of one or more tokens that must match in
112061112457
** sequence. A single token is the base case and the most common case.
112062112458
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
@@ -112252,23 +112648,12 @@
112252112648
#endif
112253112649
112254112650
/* fts3_aux.c */
112255112651
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
112256112652
112257
-SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
112258
- Fts3Cursor *pCsr, /* Virtual table cursor handle */
112259
- const char *zTerm, /* Term to query for */
112260
- int nTerm, /* Size of zTerm in bytes */
112261
- int isPrefix, /* True for a prefix search */
112262
- Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
112263
-);
112264
-
112265112653
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
112266112654
112267
-SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
112268
-SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
112269
-
112270112655
SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
112271112656
Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
112272112657
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
112273112658
Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
112274112659
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
@@ -112275,11 +112660,11 @@
112275112660
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
112276112661
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
112277112662
112278112663
SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
112279112664
112280
-#endif /* SQLITE_ENABLE_FTS3 */
112665
+#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
112281112666
#endif /* _FTSINT_H */
112282112667
112283112668
/************** End of fts3Int.h *********************************************/
112284112669
/************** Continuing where we left off in fts3.c ***********************/
112285112670
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
@@ -112291,10 +112676,15 @@
112291112676
112292112677
#ifndef SQLITE_CORE
112293112678
SQLITE_EXTENSION_INIT1
112294112679
#endif
112295112680
112681
+static int fts3EvalNext(Fts3Cursor *pCsr);
112682
+static int fts3EvalStart(Fts3Cursor *pCsr);
112683
+static int fts3TermSegReaderCursor(
112684
+ Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
112685
+
112296112686
/*
112297112687
** Write a 64-bit variable-length integer to memory starting at p[0].
112298112688
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
112299112689
** The number of bytes written is returned.
112300112690
*/
@@ -112799,31 +113189,60 @@
112799113189
}
112800113190
sqlite3_free(zFree);
112801113191
return zRet;
112802113192
}
112803113193
113194
+/*
113195
+** This function interprets the string at (*pp) as a non-negative integer
113196
+** value. It reads the integer and sets *pnOut to the value read, then
113197
+** sets *pp to point to the byte immediately following the last byte of
113198
+** the integer value.
113199
+**
113200
+** Only decimal digits ('0'..'9') may be part of an integer value.
113201
+**
113202
+** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
113203
+** the output value undefined. Otherwise SQLITE_OK is returned.
113204
+**
113205
+** This function is used when parsing the "prefix=" FTS4 parameter.
113206
+*/
112804113207
static int fts3GobbleInt(const char **pp, int *pnOut){
112805
- const char *p = *pp;
112806
- int nInt = 0;
113208
+ const char *p = *pp; /* Iterator pointer */
113209
+ int nInt = 0; /* Output value */
113210
+
112807113211
for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
112808113212
nInt = nInt * 10 + (p[0] - '0');
112809113213
}
112810113214
if( p==*pp ) return SQLITE_ERROR;
112811113215
*pnOut = nInt;
112812113216
*pp = p;
112813113217
return SQLITE_OK;
112814113218
}
112815113219
112816
-
113220
+/*
113221
+** This function is called to allocate an array of Fts3Index structures
113222
+** representing the indexes maintained by the current FTS table. FTS tables
113223
+** always maintain the main "terms" index, but may also maintain one or
113224
+** more "prefix" indexes, depending on the value of the "prefix=" parameter
113225
+** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
113226
+**
113227
+** Argument zParam is passed the value of the "prefix=" option if one was
113228
+** specified, or NULL otherwise.
113229
+**
113230
+** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
113231
+** the allocated array. *pnIndex is set to the number of elements in the
113232
+** array. If an error does occur, an SQLite error code is returned.
113233
+**
113234
+** Regardless of whether or not an error is returned, it is the responsibility
113235
+** of the caller to call sqlite3_free() on the output array to free it.
113236
+*/
112817113237
static int fts3PrefixParameter(
112818113238
const char *zParam, /* ABC in prefix=ABC parameter to parse */
112819113239
int *pnIndex, /* OUT: size of *apIndex[] array */
112820
- struct Fts3Index **apIndex, /* OUT: Array of indexes for this table */
112821
- struct Fts3Index **apFree /* OUT: Free this with sqlite3_free() */
113240
+ struct Fts3Index **apIndex /* OUT: Array of indexes for this table */
112822113241
){
112823
- struct Fts3Index *aIndex;
112824
- int nIndex = 1;
113242
+ struct Fts3Index *aIndex; /* Allocated array */
113243
+ int nIndex = 1; /* Number of entries in array */
112825113244
112826113245
if( zParam && zParam[0] ){
112827113246
const char *p;
112828113247
nIndex++;
112829113248
for(p=zParam; *p; p++){
@@ -112830,11 +113249,11 @@
112830113249
if( *p==',' ) nIndex++;
112831113250
}
112832113251
}
112833113252
112834113253
aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
112835
- *apIndex = *apFree = aIndex;
113254
+ *apIndex = aIndex;
112836113255
*pnIndex = nIndex;
112837113256
if( !aIndex ){
112838113257
return SQLITE_NOMEM;
112839113258
}
112840113259
@@ -112887,12 +113306,11 @@
112887113306
int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
112888113307
const char **aCol; /* Array of column names */
112889113308
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
112890113309
112891113310
int nIndex; /* Size of aIndex[] array */
112892
- struct Fts3Index *aIndex; /* Array of indexes for this table */
112893
- struct Fts3Index *aFree = 0; /* Free this before returning */
113311
+ struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
112894113312
112895113313
/* The results of parsing supported FTS4 key=value options: */
112896113314
int bNoDocsize = 0; /* True to omit %_docsize table */
112897113315
int bDescIdx = 0; /* True to store descending indexes */
112898113316
char *zPrefix = 0; /* Prefix parameter value (or NULL) */
@@ -113025,11 +113443,11 @@
113025113443
rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
113026113444
if( rc!=SQLITE_OK ) goto fts3_init_out;
113027113445
}
113028113446
assert( pTokenizer );
113029113447
113030
- rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
113448
+ rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
113031113449
if( rc==SQLITE_ERROR ){
113032113450
assert( zPrefix );
113033113451
*pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
113034113452
}
113035113453
if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -113112,11 +113530,11 @@
113112113530
/* Declare the table schema to SQLite. */
113113113531
fts3DeclareVtab(&rc, p);
113114113532
113115113533
fts3_init_out:
113116113534
sqlite3_free(zPrefix);
113117
- sqlite3_free(aFree);
113535
+ sqlite3_free(aIndex);
113118113536
sqlite3_free(zCompress);
113119113537
sqlite3_free(zUncompress);
113120113538
sqlite3_free((void *)aCol);
113121113539
if( rc!=SQLITE_OK ){
113122113540
if( p ){
@@ -113703,12 +114121,10 @@
113703114121
*pp1 = p1 + 1;
113704114122
*pp2 = p2 + 1;
113705114123
}
113706114124
113707114125
/*
113708
-** nToken==1 searches for adjacent positions.
113709
-**
113710114126
** This function is used to merge two position lists into one. When it is
113711114127
** called, *pp1 and *pp2 must both point to position lists. A position-list is
113712114128
** the part of a doclist that follows each document id. For example, if a row
113713114129
** contains:
113714114130
**
@@ -113724,10 +114140,12 @@
113724114140
** If isSaveLeft is 0, an entry is added to the output position list for
113725114141
** each position in *pp2 for which there exists one or more positions in
113726114142
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
113727114143
** when the *pp1 token appears before the *pp2 token, but not more than nToken
113728114144
** slots before it.
114145
+**
114146
+** e.g. nToken==1 searches for adjacent positions.
113729114147
*/
113730114148
static int fts3PoslistPhraseMerge(
113731114149
char **pp, /* IN/OUT: Preallocated output buffer */
113732114150
int nToken, /* Maximum difference in token positions */
113733114151
int isSaveLeft, /* Save the left position */
@@ -113890,26 +114308,38 @@
113890114308
113891114309
return res;
113892114310
}
113893114311
113894114312
/*
113895
-** A pointer to an instance of this structure is used as the context
113896
-** argument to sqlite3Fts3SegReaderIterate()
114313
+** An instance of this function is used to merge together the (potentially
114314
+** large number of) doclists for each term that matches a prefix query.
114315
+** See function fts3TermSelectMerge() for details.
113897114316
*/
113898114317
typedef struct TermSelect TermSelect;
113899114318
struct TermSelect {
113900
- int isReqPos;
113901
- char *aaOutput[16]; /* Malloc'd output buffer */
113902
- int anOutput[16]; /* Size of output in bytes */
114319
+ char *aaOutput[16]; /* Malloc'd output buffers */
114320
+ int anOutput[16]; /* Size each output buffer in bytes */
113903114321
};
113904114322
113905
-
114323
+/*
114324
+** This function is used to read a single varint from a buffer. Parameter
114325
+** pEnd points 1 byte past the end of the buffer. When this function is
114326
+** called, if *pp points to pEnd or greater, then the end of the buffer
114327
+** has been reached. In this case *pp is set to 0 and the function returns.
114328
+**
114329
+** If *pp does not point to or past pEnd, then a single varint is read
114330
+** from *pp. *pp is then set to point 1 byte past the end of the read varint.
114331
+**
114332
+** If bDescIdx is false, the value read is added to *pVal before returning.
114333
+** If it is true, the value read is subtracted from *pVal before this
114334
+** function returns.
114335
+*/
113906114336
static void fts3GetDeltaVarint3(
113907
- char **pp,
113908
- char *pEnd,
113909
- int bDescIdx,
113910
- sqlite3_int64 *pVal
114337
+ char **pp, /* IN/OUT: Point to read varint from */
114338
+ char *pEnd, /* End of buffer */
114339
+ int bDescIdx, /* True if docids are descending */
114340
+ sqlite3_int64 *pVal /* IN/OUT: Integer value */
113911114341
){
113912114342
if( *pp>=pEnd ){
113913114343
*pp = 0;
113914114344
}else{
113915114345
sqlite3_int64 iVal;
@@ -113920,10 +114350,25 @@
113920114350
*pVal += iVal;
113921114351
}
113922114352
}
113923114353
}
113924114354
114355
+/*
114356
+** This function is used to write a single varint to a buffer. The varint
114357
+** is written to *pp. Before returning, *pp is set to point 1 byte past the
114358
+** end of the value written.
114359
+**
114360
+** If *pbFirst is zero when this function is called, the value written to
114361
+** the buffer is that of parameter iVal.
114362
+**
114363
+** If *pbFirst is non-zero when this function is called, then the value
114364
+** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
114365
+** (if bDescIdx is non-zero).
114366
+**
114367
+** Before returning, this function always sets *pbFirst to 1 and *piPrev
114368
+** to the value of parameter iVal.
114369
+*/
113925114370
static void fts3PutDeltaVarint3(
113926114371
char **pp, /* IN/OUT: Output pointer */
113927114372
int bDescIdx, /* True for descending docids */
113928114373
sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
113929114374
int *pbFirst, /* IN/OUT: True after first int written */
@@ -113940,14 +114385,38 @@
113940114385
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
113941114386
*piPrev = iVal;
113942114387
*pbFirst = 1;
113943114388
}
113944114389
113945
-#define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))
113946114390
114391
+/*
114392
+** This macro is used by various functions that merge doclists. The two
114393
+** arguments are 64-bit docid values. If the value of the stack variable
114394
+** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
114395
+** Otherwise, (i2-i1).
114396
+**
114397
+** Using this makes it easier to write code that can merge doclists that are
114398
+** sorted in either ascending or descending order.
114399
+*/
114400
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
114401
+
114402
+/*
114403
+** This function does an "OR" merge of two doclists (output contains all
114404
+** positions contained in either argument doclist). If the docids in the
114405
+** input doclists are sorted in ascending order, parameter bDescDoclist
114406
+** should be false. If they are sorted in ascending order, it should be
114407
+** passed a non-zero value.
114408
+**
114409
+** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
114410
+** containing the output doclist and SQLITE_OK is returned. In this case
114411
+** *pnOut is set to the number of bytes in the output doclist.
114412
+**
114413
+** If an error occurs, an SQLite error code is returned. The output values
114414
+** are undefined in this case.
114415
+*/
113947114416
static int fts3DoclistOrMerge(
113948
- int bDescIdx, /* True if arguments are desc */
114417
+ int bDescDoclist, /* True if arguments are desc */
113949114418
char *a1, int n1, /* First doclist */
113950114419
char *a2, int n2, /* Second doclist */
113951114420
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
113952114421
){
113953114422
sqlite3_int64 i1 = 0;
@@ -113968,35 +114437,47 @@
113968114437
113969114438
p = aOut;
113970114439
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113971114440
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113972114441
while( p1 || p2 ){
113973
- sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
114442
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
113974114443
113975114444
if( p2 && p1 && iDiff==0 ){
113976
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
114445
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
113977114446
fts3PoslistMerge(&p, &p1, &p2);
113978
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113979
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
114447
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
114448
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
113980114449
}else if( !p2 || (p1 && iDiff<0) ){
113981
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
114450
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
113982114451
fts3PoslistCopy(&p, &p1);
113983
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
114452
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
113984114453
}else{
113985
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
114454
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
113986114455
fts3PoslistCopy(&p, &p2);
113987
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
114456
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
113988114457
}
113989114458
}
113990114459
113991114460
*paOut = aOut;
113992114461
*pnOut = (p-aOut);
113993114462
return SQLITE_OK;
113994114463
}
113995114464
114465
+/*
114466
+** This function does a "phrase" merge of two doclists. In a phrase merge,
114467
+** the output contains a copy of each position from the right-hand input
114468
+** doclist for which there is a position in the left-hand input doclist
114469
+** exactly nDist tokens before it.
114470
+**
114471
+** If the docids in the input doclists are sorted in ascending order,
114472
+** parameter bDescDoclist should be false. If they are sorted in ascending
114473
+** order, it should be passed a non-zero value.
114474
+**
114475
+** The right-hand input doclist is overwritten by this function.
114476
+*/
113996114477
static void fts3DoclistPhraseMerge(
113997
- int bDescIdx, /* True if arguments are desc */
114478
+ int bDescDoclist, /* True if arguments are desc */
113998114479
int nDist, /* Distance from left to right (1=adjacent) */
113999114480
char *aLeft, int nLeft, /* Left doclist */
114000114481
char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
114001114482
){
114002114483
sqlite3_int64 i1 = 0;
@@ -114015,30 +114496,30 @@
114015114496
p = aOut;
114016114497
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
114017114498
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
114018114499
114019114500
while( p1 && p2 ){
114020
- sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
114501
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
114021114502
if( iDiff==0 ){
114022114503
char *pSave = p;
114023114504
sqlite3_int64 iPrevSave = iPrev;
114024114505
int bFirstOutSave = bFirstOut;
114025114506
114026
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
114507
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
114027114508
if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
114028114509
p = pSave;
114029114510
iPrev = iPrevSave;
114030114511
bFirstOut = bFirstOutSave;
114031114512
}
114032
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
114033
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
114513
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
114514
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
114034114515
}else if( iDiff<0 ){
114035114516
fts3PoslistCopy(0, &p1);
114036
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
114517
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
114037114518
}else{
114038114519
fts3PoslistCopy(0, &p2);
114039
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
114520
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
114040114521
}
114041114522
}
114042114523
114043114524
*pnRight = p - aOut;
114044114525
}
@@ -114051,11 +114532,11 @@
114051114532
**
114052114533
** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
114053114534
** the responsibility of the caller to free any doclists left in the
114054114535
** TermSelect.aaOutput[] array.
114055114536
*/
114056
-static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
114537
+static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
114057114538
char *aOut = 0;
114058114539
int nOut = 0;
114059114540
int i;
114060114541
114061114542
/* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -114092,28 +114573,29 @@
114092114573
pTS->anOutput[0] = nOut;
114093114574
return SQLITE_OK;
114094114575
}
114095114576
114096114577
/*
114097
-** This function is used as the sqlite3Fts3SegReaderIterate() callback when
114098
-** querying the full-text index for a doclist associated with a term or
114099
-** term-prefix.
114578
+** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
114579
+** as the first argument. The merge is an "OR" merge (see function
114580
+** fts3DoclistOrMerge() for details).
114581
+**
114582
+** This function is called with the doclist for each term that matches
114583
+** a queried prefix. It merges all these doclists into one, the doclist
114584
+** for the specified prefix. Since there can be a very large number of
114585
+** doclists to merge, the merging is done pair-wise using the TermSelect
114586
+** object.
114587
+**
114588
+** This function returns SQLITE_OK if the merge is successful, or an
114589
+** SQLite error code (SQLITE_NOMEM) if an error occurs.
114100114590
*/
114101
-static int fts3TermSelectCb(
114102
- Fts3Table *p, /* Virtual table object */
114103
- void *pContext, /* Pointer to TermSelect structure */
114104
- char *zTerm,
114105
- int nTerm,
114106
- char *aDoclist,
114107
- int nDoclist
114591
+static int fts3TermSelectMerge(
114592
+ Fts3Table *p, /* FTS table handle */
114593
+ TermSelect *pTS, /* TermSelect object to merge into */
114594
+ char *aDoclist, /* Pointer to doclist */
114595
+ int nDoclist /* Size of aDoclist in bytes */
114108114596
){
114109
- TermSelect *pTS = (TermSelect *)pContext;
114110
-
114111
- UNUSED_PARAMETER(p);
114112
- UNUSED_PARAMETER(zTerm);
114113
- UNUSED_PARAMETER(nTerm);
114114
-
114115114597
if( pTS->aaOutput[0]==0 ){
114116114598
/* If this is the first term selected, copy the doclist to the output
114117114599
** buffer using memcpy(). */
114118114600
pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
114119114601
pTS->anOutput[0] = nDoclist;
@@ -114180,23 +114662,30 @@
114180114662
}
114181114663
pCsr->apSegment[pCsr->nSegment++] = pNew;
114182114664
return SQLITE_OK;
114183114665
}
114184114666
114667
+/*
114668
+** Add seg-reader objects to the Fts3MultiSegReader object passed as the
114669
+** 8th argument.
114670
+**
114671
+** This function returns SQLITE_OK if successful, or an SQLite error code
114672
+** otherwise.
114673
+*/
114185114674
static int fts3SegReaderCursor(
114186114675
Fts3Table *p, /* FTS3 table handle */
114187114676
int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114188114677
int iLevel, /* Level of segments to scan */
114189114678
const char *zTerm, /* Term to query for */
114190114679
int nTerm, /* Size of zTerm in bytes */
114191114680
int isPrefix, /* True for a prefix search */
114192114681
int isScan, /* True to scan from zTerm to EOF */
114193
- Fts3MultiSegReader *pCsr /* Cursor object to populate */
114682
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
114194114683
){
114195
- int rc = SQLITE_OK;
114196
- int rc2;
114197
- sqlite3_stmt *pStmt = 0;
114684
+ int rc = SQLITE_OK; /* Error code */
114685
+ sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
114686
+ int rc2; /* Result of sqlite3_reset() */
114198114687
114199114688
/* If iLevel is less than 0 and this is not a scan, include a seg-reader
114200114689
** for the pending-terms. If this is a scan, then this call must be being
114201114690
** made by an fts4aux module, not an FTS table. In this case calling
114202114691
** Fts3SegReaderPending might segfault, as the data structures used by
@@ -114281,28 +114770,46 @@
114281114770
return fts3SegReaderCursor(
114282114771
p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
114283114772
);
114284114773
}
114285114774
114775
+/*
114776
+** In addition to its current configuration, have the Fts3MultiSegReader
114777
+** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
114778
+**
114779
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
114780
+*/
114286114781
static int fts3SegReaderCursorAddZero(
114287
- Fts3Table *p,
114288
- const char *zTerm,
114289
- int nTerm,
114290
- Fts3MultiSegReader *pCsr
114782
+ Fts3Table *p, /* FTS virtual table handle */
114783
+ const char *zTerm, /* Term to scan doclist of */
114784
+ int nTerm, /* Number of bytes in zTerm */
114785
+ Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
114291114786
){
114292114787
return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
114293114788
}
114294114789
114295
-
114296
-SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
114790
+/*
114791
+** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
114792
+** if isPrefix is true, to scan the doclist for all terms for which
114793
+** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
114794
+** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
114795
+** an SQLite error code.
114796
+**
114797
+** It is the responsibility of the caller to free this object by eventually
114798
+** passing it to fts3SegReaderCursorFree()
114799
+**
114800
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
114801
+** Output parameter *ppSegcsr is set to 0 if an error occurs.
114802
+*/
114803
+static int fts3TermSegReaderCursor(
114297114804
Fts3Cursor *pCsr, /* Virtual table cursor handle */
114298114805
const char *zTerm, /* Term to query for */
114299114806
int nTerm, /* Size of zTerm in bytes */
114300114807
int isPrefix, /* True for a prefix search */
114301114808
Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
114302114809
){
114303
- Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114810
+ Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114304114811
int rc = SQLITE_NOMEM; /* Return code */
114305114812
114306114813
pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
114307114814
if( pSegcsr ){
114308114815
int i;
@@ -114342,62 +114849,53 @@
114342114849
114343114850
*ppSegcsr = pSegcsr;
114344114851
return rc;
114345114852
}
114346114853
114854
+/*
114855
+** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
114856
+*/
114347114857
static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
114348114858
sqlite3Fts3SegReaderFinish(pSegcsr);
114349114859
sqlite3_free(pSegcsr);
114350114860
}
114351114861
114352114862
/*
114353114863
** This function retreives the doclist for the specified term (or term
114354
-** prefix) from the database.
114355
-**
114356
-** The returned doclist may be in one of two formats, depending on the
114357
-** value of parameter isReqPos. If isReqPos is zero, then the doclist is
114358
-** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
114359
-** is non-zero, then the returned list is in the same format as is stored
114360
-** in the database without the found length specifier at the start of on-disk
114361
-** doclists.
114864
+** prefix) from the database.
114362114865
*/
114363114866
static int fts3TermSelect(
114364114867
Fts3Table *p, /* Virtual table handle */
114365114868
Fts3PhraseToken *pTok, /* Token to query for */
114366114869
int iColumn, /* Column to query (or -ve for all columns) */
114367
- int isReqPos, /* True to include position lists in output */
114368114870
int *pnOut, /* OUT: Size of buffer at *ppOut */
114369114871
char **ppOut /* OUT: Malloced result buffer */
114370114872
){
114371114873
int rc; /* Return code */
114372
- Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114373
- TermSelect tsc; /* Context object for fts3TermSelectCb() */
114874
+ Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114875
+ TermSelect tsc; /* Object for pair-wise doclist merging */
114374114876
Fts3SegFilter filter; /* Segment term filter configuration */
114375114877
114376114878
pSegcsr = pTok->pSegcsr;
114377114879
memset(&tsc, 0, sizeof(TermSelect));
114378
- tsc.isReqPos = isReqPos;
114379114880
114380
- filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
114881
+ filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
114381114882
| (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
114382
- | (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
114383114883
| (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
114384114884
filter.iCol = iColumn;
114385114885
filter.zTerm = pTok->z;
114386114886
filter.nTerm = pTok->n;
114387114887
114388114888
rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
114389114889
while( SQLITE_OK==rc
114390114890
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
114391114891
){
114392
- rc = fts3TermSelectCb(p, (void *)&tsc,
114393
- pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
114394
- );
114892
+ rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
114395114893
}
114396114894
114397114895
if( rc==SQLITE_OK ){
114398
- rc = fts3TermSelectMerge(p, &tsc);
114896
+ rc = fts3TermSelectFinishMerge(p, &tsc);
114399114897
}
114400114898
if( rc==SQLITE_OK ){
114401114899
*ppOut = tsc.aaOutput[0];
114402114900
*pnOut = tsc.anOutput[0];
114403114901
}else{
@@ -114419,28 +114917,19 @@
114419114917
** If the isPoslist argument is true, then it is assumed that the doclist
114420114918
** contains a position-list following each docid. Otherwise, it is assumed
114421114919
** that the doclist is simply a list of docids stored as delta encoded
114422114920
** varints.
114423114921
*/
114424
-static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
114922
+static int fts3DoclistCountDocids(char *aList, int nList){
114425114923
int nDoc = 0; /* Return value */
114426114924
if( aList ){
114427114925
char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
114428114926
char *p = aList; /* Cursor */
114429
- if( !isPoslist ){
114430
- /* The number of docids in the list is the same as the number of
114431
- ** varints. In FTS3 a varint consists of a single byte with the 0x80
114432
- ** bit cleared and zero or more bytes with the 0x80 bit set. So to
114433
- ** count the varints in the buffer, just count the number of bytes
114434
- ** with the 0x80 bit clear. */
114435
- while( p<aEnd ) nDoc += (((*p++)&0x80)==0);
114436
- }else{
114437
- while( p<aEnd ){
114438
- nDoc++;
114439
- while( (*p++)&0x80 ); /* Skip docid varint */
114440
- fts3PoslistCopy(0, &p); /* Skip over position list */
114441
- }
114927
+ while( p<aEnd ){
114928
+ nDoc++;
114929
+ while( (*p++)&0x80 ); /* Skip docid varint */
114930
+ fts3PoslistCopy(0, &p); /* Skip over position list */
114442114931
}
114443114932
}
114444114933
114445114934
return nDoc;
114446114935
}
@@ -114466,11 +114955,11 @@
114466114955
}else{
114467114956
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114468114957
rc = SQLITE_OK;
114469114958
}
114470114959
}else{
114471
- rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
114960
+ rc = fts3EvalNext((Fts3Cursor *)pCursor);
114472114961
}
114473114962
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
114474114963
return rc;
114475114964
}
114476114965
@@ -114543,11 +115032,11 @@
114543115032
}
114544115033
114545115034
rc = sqlite3Fts3ReadLock(p);
114546115035
if( rc!=SQLITE_OK ) return rc;
114547115036
114548
- rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
115037
+ rc = fts3EvalStart(pCsr);
114549115038
114550115039
sqlite3Fts3SegmentsClose(p);
114551115040
if( rc!=SQLITE_OK ) return rc;
114552115041
pCsr->pNextId = pCsr->aDoclist;
114553115042
pCsr->iPrevId = 0;
@@ -114950,26 +115439,43 @@
114950115439
p->zDb, p->zName, zName
114951115440
);
114952115441
return rc;
114953115442
}
114954115443
115444
+/*
115445
+** The xSavepoint() method.
115446
+**
115447
+** Flush the contents of the pending-terms table to disk.
115448
+*/
114955115449
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
114956115450
UNUSED_PARAMETER(iSavepoint);
114957115451
assert( ((Fts3Table *)pVtab)->inTransaction );
114958115452
assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
114959115453
TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
114960115454
return fts3SyncMethod(pVtab);
114961115455
}
115456
+
115457
+/*
115458
+** The xRelease() method.
115459
+**
115460
+** This is a no-op.
115461
+*/
114962115462
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
114963115463
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114964115464
UNUSED_PARAMETER(iSavepoint);
114965115465
UNUSED_PARAMETER(pVtab);
114966115466
assert( p->inTransaction );
114967115467
assert( p->mxSavepoint >= iSavepoint );
114968115468
TESTONLY( p->mxSavepoint = iSavepoint-1 );
114969115469
return SQLITE_OK;
114970115470
}
115471
+
115472
+/*
115473
+** The xRollbackTo() method.
115474
+**
115475
+** Discard the contents of the pending terms table.
115476
+*/
114971115477
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
114972115478
Fts3Table *p = (Fts3Table*)pVtab;
114973115479
UNUSED_PARAMETER(iSavepoint);
114974115480
assert( p->inTransaction );
114975115481
assert( p->mxSavepoint >= iSavepoint );
@@ -115114,22 +115620,10 @@
115114115620
sqlite3Fts3HashClear(pHash);
115115115621
sqlite3_free(pHash);
115116115622
}
115117115623
return rc;
115118115624
}
115119
-
115120
-#if !SQLITE_CORE
115121
-SQLITE_API int sqlite3_extension_init(
115122
- sqlite3 *db,
115123
- char **pzErrMsg,
115124
- const sqlite3_api_routines *pApi
115125
-){
115126
- SQLITE_EXTENSION_INIT2(pApi)
115127
- return sqlite3Fts3Init(db);
115128
-}
115129
-#endif
115130
-
115131115625
115132115626
/*
115133115627
** Allocate an Fts3MultiSegReader for each token in the expression headed
115134115628
** by pExpr.
115135115629
**
@@ -115143,24 +115637,24 @@
115143115637
** there exists prefix b-tree of the right length) then it may be traversed
115144115638
** and merged incrementally. Otherwise, it has to be merged into an in-memory
115145115639
** doclist and then traversed.
115146115640
*/
115147115641
static void fts3EvalAllocateReaders(
115148
- Fts3Cursor *pCsr,
115149
- Fts3Expr *pExpr,
115642
+ Fts3Cursor *pCsr, /* FTS cursor handle */
115643
+ Fts3Expr *pExpr, /* Allocate readers for this expression */
115150115644
int *pnToken, /* OUT: Total number of tokens in phrase. */
115151115645
int *pnOr, /* OUT: Total number of OR nodes in expr. */
115152
- int *pRc
115646
+ int *pRc /* IN/OUT: Error code */
115153115647
){
115154115648
if( pExpr && SQLITE_OK==*pRc ){
115155115649
if( pExpr->eType==FTSQUERY_PHRASE ){
115156115650
int i;
115157115651
int nToken = pExpr->pPhrase->nToken;
115158115652
*pnToken += nToken;
115159115653
for(i=0; i<nToken; i++){
115160115654
Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
115161
- int rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115655
+ int rc = fts3TermSegReaderCursor(pCsr,
115162115656
pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115163115657
);
115164115658
if( rc!=SQLITE_OK ){
115165115659
*pRc = rc;
115166115660
return;
@@ -115174,16 +115668,24 @@
115174115668
fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
115175115669
}
115176115670
}
115177115671
}
115178115672
115673
+/*
115674
+** Arguments pList/nList contain the doclist for token iToken of phrase p.
115675
+** It is merged into the main doclist stored in p->doclist.aAll/nAll.
115676
+**
115677
+** This function assumes that pList points to a buffer allocated using
115678
+** sqlite3_malloc(). This function takes responsibility for eventually
115679
+** freeing the buffer.
115680
+*/
115179115681
static void fts3EvalPhraseMergeToken(
115180
- Fts3Table *pTab,
115181
- Fts3Phrase *p,
115182
- int iToken,
115183
- char *pList,
115184
- int nList
115682
+ Fts3Table *pTab, /* FTS Table pointer */
115683
+ Fts3Phrase *p, /* Phrase to merge pList/nList into */
115684
+ int iToken, /* Token pList/nList corresponds to */
115685
+ char *pList, /* Pointer to doclist */
115686
+ int nList /* Number of bytes in pList */
115185115687
){
115186115688
assert( iToken!=p->iDoclistToken );
115187115689
115188115690
if( pList==0 ){
115189115691
sqlite3_free(p->doclist.aAll);
@@ -115228,13 +115730,19 @@
115228115730
}
115229115731
115230115732
if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
115231115733
}
115232115734
115735
+/*
115736
+** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
115737
+** does not take deferred tokens into account.
115738
+**
115739
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
115740
+*/
115233115741
static int fts3EvalPhraseLoad(
115234
- Fts3Cursor *pCsr,
115235
- Fts3Phrase *p
115742
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
115743
+ Fts3Phrase *p /* Phrase object */
115236115744
){
115237115745
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115238115746
int iToken;
115239115747
int rc = SQLITE_OK;
115240115748
@@ -115243,11 +115751,11 @@
115243115751
assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
115244115752
115245115753
if( pToken->pSegcsr ){
115246115754
int nThis = 0;
115247115755
char *pThis = 0;
115248
- rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
115756
+ rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
115249115757
if( rc==SQLITE_OK ){
115250115758
fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
115251115759
}
115252115760
}
115253115761
assert( pToken->pSegcsr==0 );
@@ -115254,18 +115762,26 @@
115254115762
}
115255115763
115256115764
return rc;
115257115765
}
115258115766
115767
+/*
115768
+** This function is called on each phrase after the position lists for
115769
+** any deferred tokens have been loaded into memory. It updates the phrases
115770
+** current position list to include only those positions that are really
115771
+** instances of the phrase (after considering deferred tokens). If this
115772
+** means that the phrase does not appear in the current row, doclist.pList
115773
+** and doclist.nList are both zeroed.
115774
+**
115775
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
115776
+*/
115259115777
static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
115260
- int iToken;
115261
- int rc = SQLITE_OK;
115262
-
115263
- int nMaxUndeferred = pPhrase->iDoclistToken;
115264
- char *aPoslist = 0;
115265
- int nPoslist = 0;
115266
- int iPrev = -1;
115778
+ int iToken; /* Used to iterate through phrase tokens */
115779
+ int rc = SQLITE_OK; /* Return code */
115780
+ char *aPoslist = 0; /* Position list for deferred tokens */
115781
+ int nPoslist = 0; /* Number of bytes in aPoslist */
115782
+ int iPrev = -1; /* Token number of previous deferred token */
115267115783
115268115784
assert( pPhrase->doclist.bFreeList==0 );
115269115785
115270115786
for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
115271115787
Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -115307,10 +115823,11 @@
115307115823
iPrev = iToken;
115308115824
}
115309115825
}
115310115826
115311115827
if( iPrev>=0 ){
115828
+ int nMaxUndeferred = pPhrase->iDoclistToken;
115312115829
if( nMaxUndeferred<0 ){
115313115830
pPhrase->doclist.pList = aPoslist;
115314115831
pPhrase->doclist.nList = nPoslist;
115315115832
pPhrase->doclist.iDocid = pCsr->iPrevId;
115316115833
pPhrase->doclist.bFreeList = 1;
@@ -115355,13 +115872,19 @@
115355115872
/*
115356115873
** This function is called for each Fts3Phrase in a full-text query
115357115874
** expression to initialize the mechanism for returning rows. Once this
115358115875
** function has been called successfully on an Fts3Phrase, it may be
115359115876
** used with fts3EvalPhraseNext() to iterate through the matching docids.
115877
+**
115878
+** If parameter bOptOk is true, then the phrase may (or may not) use the
115879
+** incremental loading strategy. Otherwise, the entire doclist is loaded into
115880
+** memory within this call.
115881
+**
115882
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
115360115883
*/
115361115884
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
115362
- int rc;
115885
+ int rc; /* Error code */
115363115886
Fts3PhraseToken *pFirst = &p->aToken[0];
115364115887
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115365115888
115366115889
if( pCsr->bDesc==pTab->bDescIdx
115367115890
&& bOptOk==1
@@ -115385,11 +115908,17 @@
115385115908
return rc;
115386115909
}
115387115910
115388115911
/*
115389115912
** This function is used to iterate backwards (from the end to start)
115390
-** through doclists.
115913
+** through doclists. It is used by this module to iterate through phrase
115914
+** doclists in reverse and by the fts3_write.c module to iterate through
115915
+** pending-terms lists when writing to databases with "order=desc".
115916
+**
115917
+** The doclist may be sorted in ascending (parameter bDescIdx==0) or
115918
+** descending (parameter bDescIdx==1) order of docid. Regardless, this
115919
+** function iterates from the end of the doclist to the beginning.
115391115920
*/
115392115921
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
115393115922
int bDescIdx, /* True if the doclist is desc */
115394115923
char *aDoclist, /* Pointer to entire doclist */
115395115924
int nDoclist, /* Length of aDoclist in bytes */
@@ -115450,13 +115979,13 @@
115450115979
** If there is no "next" entry and no error occurs, then *pbEof is set to
115451115980
** 1 before returning. Otherwise, if no error occurs and the iterator is
115452115981
** successfully advanced, *pbEof is set to 0.
115453115982
*/
115454115983
static int fts3EvalPhraseNext(
115455
- Fts3Cursor *pCsr,
115456
- Fts3Phrase *p,
115457
- u8 *pbEof
115984
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
115985
+ Fts3Phrase *p, /* Phrase object to advance to next docid */
115986
+ u8 *pbEof /* OUT: Set to 1 if EOF */
115458115987
){
115459115988
int rc = SQLITE_OK;
115460115989
Fts3Doclist *pDL = &p->doclist;
115461115990
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115462115991
@@ -115498,14 +116027,14 @@
115498116027
fts3PoslistCopy(0, &pIter);
115499116028
pDL->nList = (pIter - pDL->pList);
115500116029
115501116030
/* pIter now points just past the 0x00 that terminates the position-
115502116031
** list for document pDL->iDocid. However, if this position-list was
115503
- ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
116032
+ ** edited in place by fts3EvalNearTrim(), then pIter may not actually
115504116033
** point to the start of the next docid value. The following line deals
115505116034
** with this case by advancing pIter past the zero-padding added by
115506
- ** fts3EvalNearTrim2(). */
116035
+ ** fts3EvalNearTrim(). */
115507116036
while( pIter<pEnd && *pIter==0 ) pIter++;
115508116037
115509116038
pDL->pNextDocid = pIter;
115510116039
assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
115511116040
*pbEof = 0;
@@ -115513,15 +116042,31 @@
115513116042
}
115514116043
115515116044
return rc;
115516116045
}
115517116046
116047
+/*
116048
+**
116049
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
116050
+** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
116051
+** expression. Also the Fts3Expr.bDeferred variable is set to true for any
116052
+** expressions for which all descendent tokens are deferred.
116053
+**
116054
+** If parameter bOptOk is zero, then it is guaranteed that the
116055
+** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
116056
+** each phrase in the expression (subject to deferred token processing).
116057
+** Or, if bOptOk is non-zero, then one or more tokens within the expression
116058
+** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
116059
+**
116060
+** If an error occurs within this function, *pRc is set to an SQLite error
116061
+** code before returning.
116062
+*/
115518116063
static void fts3EvalStartReaders(
115519
- Fts3Cursor *pCsr,
115520
- Fts3Expr *pExpr,
115521
- int bOptOk,
115522
- int *pRc
116064
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
116065
+ Fts3Expr *pExpr, /* Expression to initialize phrases in */
116066
+ int bOptOk, /* True to enable incremental loading */
116067
+ int *pRc /* IN/OUT: Error code */
115523116068
){
115524116069
if( pExpr && SQLITE_OK==*pRc ){
115525116070
if( pExpr->eType==FTSQUERY_PHRASE ){
115526116071
int i;
115527116072
int nToken = pExpr->pPhrase->nToken;
@@ -115536,27 +116081,46 @@
115536116081
pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
115537116082
}
115538116083
}
115539116084
}
115540116085
116086
+/*
116087
+** An array of the following structures is assembled as part of the process
116088
+** of selecting tokens to defer before the query starts executing (as part
116089
+** of the xFilter() method). There is one element in the array for each
116090
+** token in the FTS expression.
116091
+**
116092
+** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
116093
+** to phrases that are connected only by AND and NEAR operators (not OR or
116094
+** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
116095
+** separately. The root of a tokens AND/NEAR cluster is stored in
116096
+** Fts3TokenAndCost.pRoot.
116097
+*/
115541116098
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
115542116099
struct Fts3TokenAndCost {
115543116100
Fts3Phrase *pPhrase; /* The phrase the token belongs to */
115544116101
int iToken; /* Position of token in phrase */
115545116102
Fts3PhraseToken *pToken; /* The token itself */
115546
- Fts3Expr *pRoot;
115547
- int nOvfl;
116103
+ Fts3Expr *pRoot; /* Root of NEAR/AND cluster */
116104
+ int nOvfl; /* Number of overflow pages to load doclist */
115548116105
int iCol; /* The column the token must match */
115549116106
};
115550116107
116108
+/*
116109
+** This function is used to populate an allocated Fts3TokenAndCost array.
116110
+**
116111
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
116112
+** Otherwise, if an error occurs during execution, *pRc is set to an
116113
+** SQLite error code.
116114
+*/
115551116115
static void fts3EvalTokenCosts(
115552
- Fts3Cursor *pCsr,
115553
- Fts3Expr *pRoot,
115554
- Fts3Expr *pExpr,
115555
- Fts3TokenAndCost **ppTC,
115556
- Fts3Expr ***ppOr,
115557
- int *pRc
116116
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
116117
+ Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */
116118
+ Fts3Expr *pExpr, /* Expression to consider */
116119
+ Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */
116120
+ Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */
116121
+ int *pRc /* IN/OUT: Error code */
115558116122
){
115559116123
if( *pRc==SQLITE_OK && pExpr ){
115560116124
if( pExpr->eType==FTSQUERY_PHRASE ){
115561116125
Fts3Phrase *pPhrase = pExpr->pPhrase;
115562116126
int i;
@@ -115584,23 +116148,34 @@
115584116148
fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
115585116149
}
115586116150
}
115587116151
}
115588116152
116153
+/*
116154
+** Determine the average document (row) size in pages. If successful,
116155
+** write this value to *pnPage and return SQLITE_OK. Otherwise, return
116156
+** an SQLite error code.
116157
+**
116158
+** The average document size in pages is calculated by first calculating
116159
+** determining the average size in bytes, B. If B is less than the amount
116160
+** of data that will fit on a single leaf page of an intkey table in
116161
+** this database, then the average docsize is 1. Otherwise, it is 1 plus
116162
+** the number of overflow pages consumed by a record B bytes in size.
116163
+*/
115589116164
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
115590116165
if( pCsr->nRowAvg==0 ){
115591116166
/* The average document size, which is required to calculate the cost
115592
- ** of each doclist, has not yet been determined. Read the required
115593
- ** data from the %_stat table to calculate it.
115594
- **
115595
- ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
115596
- ** varints, where nCol is the number of columns in the FTS3 table.
115597
- ** The first varint is the number of documents currently stored in
115598
- ** the table. The following nCol varints contain the total amount of
115599
- ** data stored in all rows of each column of the table, from left
115600
- ** to right.
115601
- */
116167
+ ** of each doclist, has not yet been determined. Read the required
116168
+ ** data from the %_stat table to calculate it.
116169
+ **
116170
+ ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
116171
+ ** varints, where nCol is the number of columns in the FTS3 table.
116172
+ ** The first varint is the number of documents currently stored in
116173
+ ** the table. The following nCol varints contain the total amount of
116174
+ ** data stored in all rows of each column of the table, from left
116175
+ ** to right.
116176
+ */
115602116177
int rc;
115603116178
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
115604116179
sqlite3_stmt *pStmt;
115605116180
sqlite3_int64 nDoc = 0;
115606116181
sqlite3_int64 nByte = 0;
@@ -115631,109 +116206,151 @@
115631116206
115632116207
*pnPage = pCsr->nRowAvg;
115633116208
return SQLITE_OK;
115634116209
}
115635116210
116211
+/*
116212
+** This function is called to select the tokens (if any) that will be
116213
+** deferred. The array aTC[] has already been populated when this is
116214
+** called.
116215
+**
116216
+** This function is called once for each AND/NEAR cluster in the
116217
+** expression. Each invocation determines which tokens to defer within
116218
+** the cluster with root node pRoot. See comments above the definition
116219
+** of struct Fts3TokenAndCost for more details.
116220
+**
116221
+** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
116222
+** called on each token to defer. Otherwise, an SQLite error code is
116223
+** returned.
116224
+*/
115636116225
static int fts3EvalSelectDeferred(
115637
- Fts3Cursor *pCsr,
115638
- Fts3Expr *pRoot,
115639
- Fts3TokenAndCost *aTC,
115640
- int nTC
116226
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
116227
+ Fts3Expr *pRoot, /* Consider tokens with this root node */
116228
+ Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */
116229
+ int nTC /* Number of entries in aTC[] */
115641116230
){
115642
- int nDocSize = 0;
115643
- int nDocEst = 0;
115644
- int rc = SQLITE_OK;
115645116231
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115646
- int ii;
116232
+ int nDocSize = 0; /* Number of pages per doc loaded */
116233
+ int rc = SQLITE_OK; /* Return code */
116234
+ int ii; /* Iterator variable for various purposes */
116235
+ int nOvfl = 0; /* Total overflow pages used by doclists */
116236
+ int nToken = 0; /* Total number of tokens in cluster */
115647116237
115648
- int nOvfl = 0;
115649
- int nTerm = 0;
116238
+ int nMinEst = 0; /* The minimum count for any phrase so far. */
116239
+ int nLoad4 = 1; /* (Phrases that will be loaded)^4. */
115650116240
116241
+ /* Count the tokens in this AND/NEAR cluster. If none of the doclists
116242
+ ** associated with the tokens spill onto overflow pages, or if there is
116243
+ ** only 1 token, exit early. No tokens to defer in this case. */
115651116244
for(ii=0; ii<nTC; ii++){
115652116245
if( aTC[ii].pRoot==pRoot ){
115653116246
nOvfl += aTC[ii].nOvfl;
115654
- nTerm++;
116247
+ nToken++;
115655116248
}
115656116249
}
115657
- if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
116250
+ if( nOvfl==0 || nToken<2 ) return SQLITE_OK;
115658116251
116252
+ /* Obtain the average docsize (in pages). */
115659116253
rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
115660
-
115661
- for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
115662
- int jj;
115663
- Fts3TokenAndCost *pTC = 0;
115664
-
115665
- for(jj=0; jj<nTC; jj++){
115666
- if( aTC[jj].pToken && aTC[jj].pRoot==pRoot
115667
- && (!pTC || aTC[jj].nOvfl<pTC->nOvfl)
116254
+ assert( rc!=SQLITE_OK || nDocSize>0 );
116255
+
116256
+
116257
+ /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
116258
+ ** of the number of overflow pages that will be loaded by the pager layer
116259
+ ** to retrieve the entire doclist for the token from the full-text index.
116260
+ ** Load the doclists for tokens that are either:
116261
+ **
116262
+ ** a. The cheapest token in the entire query (i.e. the one visited by the
116263
+ ** first iteration of this loop), or
116264
+ **
116265
+ ** b. Part of a multi-token phrase.
116266
+ **
116267
+ ** After each token doclist is loaded, merge it with the others from the
116268
+ ** same phrase and count the number of documents that the merged doclist
116269
+ ** contains. Set variable "nMinEst" to the smallest number of documents in
116270
+ ** any phrase doclist for which 1 or more token doclists have been loaded.
116271
+ ** Let nOther be the number of other phrases for which it is certain that
116272
+ ** one or more tokens will not be deferred.
116273
+ **
116274
+ ** Then, for each token, defer it if loading the doclist would result in
116275
+ ** loading N or more overflow pages into memory, where N is computed as:
116276
+ **
116277
+ ** (nMinEst + 4^nOther - 1) / (4^nOther)
116278
+ */
116279
+ for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
116280
+ int iTC; /* Used to iterate through aTC[] array. */
116281
+ Fts3TokenAndCost *pTC = 0; /* Set to cheapest remaining token. */
116282
+
116283
+ /* Set pTC to point to the cheapest remaining token. */
116284
+ for(iTC=0; iTC<nTC; iTC++){
116285
+ if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
116286
+ && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
115668116287
){
115669
- pTC = &aTC[jj];
116288
+ pTC = &aTC[iTC];
115670116289
}
115671116290
}
115672116291
assert( pTC );
115673116292
115674
- /* At this point pTC points to the cheapest remaining token. */
115675
- if( ii==0 ){
115676
- if( pTC->nOvfl ){
115677
- nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
115678
- }else{
116293
+ if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
116294
+ /* The number of overflow pages to load for this (and therefore all
116295
+ ** subsequent) tokens is greater than the estimated number of pages
116296
+ ** that will be loaded if all subsequent tokens are deferred.
116297
+ */
116298
+ Fts3PhraseToken *pToken = pTC->pToken;
116299
+ rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
116300
+ fts3SegReaderCursorFree(pToken->pSegcsr);
116301
+ pToken->pSegcsr = 0;
116302
+ }else{
116303
+ nLoad4 = nLoad4*4;
116304
+ if( ii==0 || pTC->pPhrase->nToken>1 ){
116305
+ /* Either this is the cheapest token in the entire query, or it is
116306
+ ** part of a multi-token phrase. Either way, the entire doclist will
116307
+ ** (eventually) be loaded into memory. It may as well be now. */
115679116308
Fts3PhraseToken *pToken = pTC->pToken;
115680116309
int nList = 0;
115681116310
char *pList = 0;
115682
- rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
116311
+ rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
115683116312
assert( rc==SQLITE_OK || pList==0 );
115684
-
115685116313
if( rc==SQLITE_OK ){
115686
- nDocEst = fts3DoclistCountDocids(1, pList, nList);
116314
+ int nCount;
115687116315
fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
116316
+ nCount = fts3DoclistCountDocids(
116317
+ pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
116318
+ );
116319
+ if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
115688116320
}
115689116321
}
115690
- }else{
115691
- if( pTC->nOvfl>=(nDocEst*nDocSize) ){
115692
- Fts3PhraseToken *pToken = pTC->pToken;
115693
- rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
115694
- fts3SegReaderCursorFree(pToken->pSegcsr);
115695
- pToken->pSegcsr = 0;
115696
- }
115697
- nDocEst = 1 + (nDocEst/4);
115698116322
}
115699116323
pTC->pToken = 0;
115700116324
}
115701116325
115702116326
return rc;
115703116327
}
115704116328
115705
-SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
116329
+/*
116330
+** This function is called from within the xFilter method. It initializes
116331
+** the full-text query currently stored in pCsr->pExpr. To iterate through
116332
+** the results of a query, the caller does:
116333
+**
116334
+** fts3EvalStart(pCsr);
116335
+** while( 1 ){
116336
+** fts3EvalNext(pCsr);
116337
+** if( pCsr->bEof ) break;
116338
+** ... return row pCsr->iPrevId to the caller ...
116339
+** }
116340
+*/
116341
+static int fts3EvalStart(Fts3Cursor *pCsr){
115706116342
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115707116343
int rc = SQLITE_OK;
115708116344
int nToken = 0;
115709116345
int nOr = 0;
115710116346
115711116347
/* Allocate a MultiSegReader for each token in the expression. */
115712
- fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
115713
-
115714
- /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
115715
- ** This call will eventually also be responsible for determining which
115716
- ** tokens are 'deferred' until the document text is loaded into memory.
115717
- **
115718
- ** Each token in each phrase is dealt with using one of the following
115719
- ** three strategies:
115720
- **
115721
- ** 1. Entire doclist loaded into memory as part of the
115722
- ** fts3EvalStartReaders() call.
115723
- **
115724
- ** 2. Doclist loaded into memory incrementally, as part of each
115725
- ** sqlite3Fts3EvalNext() call.
115726
- **
115727
- ** 3. Token doclist is never loaded. Instead, documents are loaded into
115728
- ** memory and scanned for the token as part of the sqlite3Fts3EvalNext()
115729
- ** call. This is known as a "deferred" token.
115730
- */
115731
-
115732
- /* If bOptOk is true, check if there are any tokens that should be deferred.
115733
- */
115734
- if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
116348
+ fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
116349
+
116350
+ /* Determine which, if any, tokens in the expression should be deferred. */
116351
+ if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
115735116352
Fts3TokenAndCost *aTC;
115736116353
Fts3Expr **apOr;
115737116354
aTC = (Fts3TokenAndCost *)sqlite3_malloc(
115738116355
sizeof(Fts3TokenAndCost) * nToken
115739116356
+ sizeof(Fts3Expr *) * nOr * 2
@@ -115745,11 +116362,11 @@
115745116362
}else{
115746116363
int ii;
115747116364
Fts3TokenAndCost *pTC = aTC;
115748116365
Fts3Expr **ppOr = apOr;
115749116366
115750
- fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
116367
+ fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
115751116368
nToken = pTC-aTC;
115752116369
nOr = ppOr-apOr;
115753116370
115754116371
if( rc==SQLITE_OK ){
115755116372
rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
@@ -115760,25 +116377,50 @@
115760116377
115761116378
sqlite3_free(aTC);
115762116379
}
115763116380
}
115764116381
115765
- fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
116382
+ fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
115766116383
return rc;
115767116384
}
115768116385
115769
-static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
116386
+/*
116387
+** Invalidate the current position list for phrase pPhrase.
116388
+*/
116389
+static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
115770116390
if( pPhrase->doclist.bFreeList ){
115771116391
sqlite3_free(pPhrase->doclist.pList);
115772116392
}
115773116393
pPhrase->doclist.pList = 0;
115774116394
pPhrase->doclist.nList = 0;
115775116395
pPhrase->doclist.bFreeList = 0;
115776116396
}
115777116397
115778
-static int fts3EvalNearTrim2(
115779
- int nNear,
116398
+/*
116399
+** This function is called to edit the position list associated with
116400
+** the phrase object passed as the fifth argument according to a NEAR
116401
+** condition. For example:
116402
+**
116403
+** abc NEAR/5 "def ghi"
116404
+**
116405
+** Parameter nNear is passed the NEAR distance of the expression (5 in
116406
+** the example above). When this function is called, *paPoslist points to
116407
+** the position list, and *pnToken is the number of phrase tokens in, the
116408
+** phrase on the other side of the NEAR operator to pPhrase. For example,
116409
+** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
116410
+** the position list associated with phrase "abc".
116411
+**
116412
+** All positions in the pPhrase position list that are not sufficiently
116413
+** close to a position in the *paPoslist position list are removed. If this
116414
+** leaves 0 positions, zero is returned. Otherwise, non-zero.
116415
+**
116416
+** Before returning, *paPoslist is set to point to the position lsit
116417
+** associated with pPhrase. And *pnToken is set to the number of tokens in
116418
+** pPhrase.
116419
+*/
116420
+static int fts3EvalNearTrim(
116421
+ int nNear, /* NEAR distance. As in "NEAR/nNear". */
115780116422
char *aTmp, /* Temporary space to use */
115781116423
char **paPoslist, /* IN/OUT: Position list */
115782116424
int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
115783116425
Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
115784116426
){
@@ -115806,10 +116448,176 @@
115806116448
}
115807116449
115808116450
return res;
115809116451
}
115810116452
116453
+/*
116454
+** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
116455
+** Otherwise, it advances the expression passed as the second argument to
116456
+** point to the next matching row in the database. Expressions iterate through
116457
+** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
116458
+** or descending if it is non-zero.
116459
+**
116460
+** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
116461
+** successful, the following variables in pExpr are set:
116462
+**
116463
+** Fts3Expr.bEof (non-zero if EOF - there is no next row)
116464
+** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row)
116465
+**
116466
+** If the expression is of type FTSQUERY_PHRASE, and the expression is not
116467
+** at EOF, then the following variables are populated with the position list
116468
+** for the phrase for the visited row:
116469
+**
116470
+** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes)
116471
+** FTs3Expr.pPhrase->doclist.pList (pointer to position list)
116472
+**
116473
+** It says above that this function advances the expression to the next
116474
+** matching row. This is usually true, but there are the following exceptions:
116475
+**
116476
+** 1. Deferred tokens are not taken into account. If a phrase consists
116477
+** entirely of deferred tokens, it is assumed to match every row in
116478
+** the db. In this case the position-list is not populated at all.
116479
+**
116480
+** Or, if a phrase contains one or more deferred tokens and one or
116481
+** more non-deferred tokens, then the expression is advanced to the
116482
+** next possible match, considering only non-deferred tokens. In other
116483
+** words, if the phrase is "A B C", and "B" is deferred, the expression
116484
+** is advanced to the next row that contains an instance of "A * C",
116485
+** where "*" may match any single token. The position list in this case
116486
+** is populated as for "A * C" before returning.
116487
+**
116488
+** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
116489
+** advanced to point to the next row that matches "x AND y".
116490
+**
116491
+** See fts3EvalTestDeferredAndNear() for details on testing if a row is
116492
+** really a match, taking into account deferred tokens and NEAR operators.
116493
+*/
116494
+static void fts3EvalNextRow(
116495
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
116496
+ Fts3Expr *pExpr, /* Expr. to advance to next matching row */
116497
+ int *pRc /* IN/OUT: Error code */
116498
+){
116499
+ if( *pRc==SQLITE_OK ){
116500
+ int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */
116501
+ assert( pExpr->bEof==0 );
116502
+ pExpr->bStart = 1;
116503
+
116504
+ switch( pExpr->eType ){
116505
+ case FTSQUERY_NEAR:
116506
+ case FTSQUERY_AND: {
116507
+ Fts3Expr *pLeft = pExpr->pLeft;
116508
+ Fts3Expr *pRight = pExpr->pRight;
116509
+ assert( !pLeft->bDeferred || !pRight->bDeferred );
116510
+
116511
+ if( pLeft->bDeferred ){
116512
+ /* LHS is entirely deferred. So we assume it matches every row.
116513
+ ** Advance the RHS iterator to find the next row visited. */
116514
+ fts3EvalNextRow(pCsr, pRight, pRc);
116515
+ pExpr->iDocid = pRight->iDocid;
116516
+ pExpr->bEof = pRight->bEof;
116517
+ }else if( pRight->bDeferred ){
116518
+ /* RHS is entirely deferred. So we assume it matches every row.
116519
+ ** Advance the LHS iterator to find the next row visited. */
116520
+ fts3EvalNextRow(pCsr, pLeft, pRc);
116521
+ pExpr->iDocid = pLeft->iDocid;
116522
+ pExpr->bEof = pLeft->bEof;
116523
+ }else{
116524
+ /* Neither the RHS or LHS are deferred. */
116525
+ fts3EvalNextRow(pCsr, pLeft, pRc);
116526
+ fts3EvalNextRow(pCsr, pRight, pRc);
116527
+ while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
116528
+ sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
116529
+ if( iDiff==0 ) break;
116530
+ if( iDiff<0 ){
116531
+ fts3EvalNextRow(pCsr, pLeft, pRc);
116532
+ }else{
116533
+ fts3EvalNextRow(pCsr, pRight, pRc);
116534
+ }
116535
+ }
116536
+ pExpr->iDocid = pLeft->iDocid;
116537
+ pExpr->bEof = (pLeft->bEof || pRight->bEof);
116538
+ }
116539
+ break;
116540
+ }
116541
+
116542
+ case FTSQUERY_OR: {
116543
+ Fts3Expr *pLeft = pExpr->pLeft;
116544
+ Fts3Expr *pRight = pExpr->pRight;
116545
+ sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
116546
+
116547
+ assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
116548
+ assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
116549
+
116550
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
116551
+ fts3EvalNextRow(pCsr, pLeft, pRc);
116552
+ }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
116553
+ fts3EvalNextRow(pCsr, pRight, pRc);
116554
+ }else{
116555
+ fts3EvalNextRow(pCsr, pLeft, pRc);
116556
+ fts3EvalNextRow(pCsr, pRight, pRc);
116557
+ }
116558
+
116559
+ pExpr->bEof = (pLeft->bEof && pRight->bEof);
116560
+ iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
116561
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
116562
+ pExpr->iDocid = pLeft->iDocid;
116563
+ }else{
116564
+ pExpr->iDocid = pRight->iDocid;
116565
+ }
116566
+
116567
+ break;
116568
+ }
116569
+
116570
+ case FTSQUERY_NOT: {
116571
+ Fts3Expr *pLeft = pExpr->pLeft;
116572
+ Fts3Expr *pRight = pExpr->pRight;
116573
+
116574
+ if( pRight->bStart==0 ){
116575
+ fts3EvalNextRow(pCsr, pRight, pRc);
116576
+ assert( *pRc!=SQLITE_OK || pRight->bStart );
116577
+ }
116578
+
116579
+ fts3EvalNextRow(pCsr, pLeft, pRc);
116580
+ if( pLeft->bEof==0 ){
116581
+ while( !*pRc
116582
+ && !pRight->bEof
116583
+ && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
116584
+ ){
116585
+ fts3EvalNextRow(pCsr, pRight, pRc);
116586
+ }
116587
+ }
116588
+ pExpr->iDocid = pLeft->iDocid;
116589
+ pExpr->bEof = pLeft->bEof;
116590
+ break;
116591
+ }
116592
+
116593
+ default: {
116594
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
116595
+ fts3EvalInvalidatePoslist(pPhrase);
116596
+ *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
116597
+ pExpr->iDocid = pPhrase->doclist.iDocid;
116598
+ break;
116599
+ }
116600
+ }
116601
+ }
116602
+}
116603
+
116604
+/*
116605
+** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
116606
+** cluster, then this function returns 1 immediately.
116607
+**
116608
+** Otherwise, it checks if the current row really does match the NEAR
116609
+** expression, using the data currently stored in the position lists
116610
+** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
116611
+**
116612
+** If the current row is a match, the position list associated with each
116613
+** phrase in the NEAR expression is edited in place to contain only those
116614
+** phrase instances sufficiently close to their peers to satisfy all NEAR
116615
+** constraints. In this case it returns 1. If the NEAR expression does not
116616
+** match the current row, 0 is returned. The position lists may or may not
116617
+** be edited if 0 is returned.
116618
+*/
115811116619
static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
115812116620
int res = 1;
115813116621
115814116622
/* The following block runs if pExpr is the root of a NEAR query.
115815116623
** For example, the query:
@@ -115827,11 +116635,11 @@
115827116635
** | |
115828116636
** "w" "x"
115829116637
**
115830116638
** The right-hand child of a NEAR node is always a phrase. The
115831116639
** left-hand child may be either a phrase or a NEAR node. There are
115832
- ** no exceptions to this.
116640
+ ** no exceptions to this - it's the way the parser in fts3_expr.c works.
115833116641
*/
115834116642
if( *pRc==SQLITE_OK
115835116643
&& pExpr->eType==FTSQUERY_NEAR
115836116644
&& pExpr->bEof==0
115837116645
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
@@ -115854,21 +116662,21 @@
115854116662
int nToken = p->pPhrase->nToken;
115855116663
115856116664
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
115857116665
Fts3Phrase *pPhrase = p->pRight->pPhrase;
115858116666
int nNear = p->nNear;
115859
- res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
116667
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115860116668
}
115861116669
115862116670
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
115863116671
nToken = pExpr->pRight->pPhrase->nToken;
115864116672
for(p=pExpr->pLeft; p && res; p=p->pLeft){
115865116673
int nNear = p->pParent->nNear;
115866116674
Fts3Phrase *pPhrase = (
115867116675
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
115868116676
);
115869
- res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
116677
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115870116678
}
115871116679
}
115872116680
115873116681
sqlite3_free(aTmp);
115874116682
}
@@ -115875,132 +116683,33 @@
115875116683
115876116684
return res;
115877116685
}
115878116686
115879116687
/*
115880
-** This macro is used by the fts3EvalNext() function. The two arguments are
115881
-** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
115882
-** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
115883
-** it returns (i2 - i1). This allows the same code to be used for merging
115884
-** doclists in ascending or descending order.
116688
+** This function is a helper function for fts3EvalTestDeferredAndNear().
116689
+** Assuming no error occurs or has occurred, It returns non-zero if the
116690
+** expression passed as the second argument matches the row that pCsr
116691
+** currently points to, or zero if it does not.
116692
+**
116693
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
116694
+** If an error occurs during execution of this function, *pRc is set to
116695
+** the appropriate SQLite error code. In this case the returned value is
116696
+** undefined.
115885116697
*/
115886
-#define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
115887
-
115888
-static void fts3EvalNext(
115889
- Fts3Cursor *pCsr,
115890
- Fts3Expr *pExpr,
115891
- int *pRc
115892
-){
115893
- if( *pRc==SQLITE_OK ){
115894
- assert( pExpr->bEof==0 );
115895
- pExpr->bStart = 1;
115896
-
115897
- switch( pExpr->eType ){
115898
- case FTSQUERY_NEAR:
115899
- case FTSQUERY_AND: {
115900
- Fts3Expr *pLeft = pExpr->pLeft;
115901
- Fts3Expr *pRight = pExpr->pRight;
115902
- assert( !pLeft->bDeferred || !pRight->bDeferred );
115903
- if( pLeft->bDeferred ){
115904
- fts3EvalNext(pCsr, pRight, pRc);
115905
- pExpr->iDocid = pRight->iDocid;
115906
- pExpr->bEof = pRight->bEof;
115907
- }else if( pRight->bDeferred ){
115908
- fts3EvalNext(pCsr, pLeft, pRc);
115909
- pExpr->iDocid = pLeft->iDocid;
115910
- pExpr->bEof = pLeft->bEof;
115911
- }else{
115912
- fts3EvalNext(pCsr, pLeft, pRc);
115913
- fts3EvalNext(pCsr, pRight, pRc);
115914
-
115915
- while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
115916
- sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115917
- if( iDiff==0 ) break;
115918
- if( iDiff<0 ){
115919
- fts3EvalNext(pCsr, pLeft, pRc);
115920
- }else{
115921
- fts3EvalNext(pCsr, pRight, pRc);
115922
- }
115923
- }
115924
-
115925
- pExpr->iDocid = pLeft->iDocid;
115926
- pExpr->bEof = (pLeft->bEof || pRight->bEof);
115927
- }
115928
- break;
115929
- }
115930
-
115931
- case FTSQUERY_OR: {
115932
- Fts3Expr *pLeft = pExpr->pLeft;
115933
- Fts3Expr *pRight = pExpr->pRight;
115934
- sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115935
-
115936
- assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
115937
- assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
115938
-
115939
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115940
- fts3EvalNext(pCsr, pLeft, pRc);
115941
- }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
115942
- fts3EvalNext(pCsr, pRight, pRc);
115943
- }else{
115944
- fts3EvalNext(pCsr, pLeft, pRc);
115945
- fts3EvalNext(pCsr, pRight, pRc);
115946
- }
115947
-
115948
- pExpr->bEof = (pLeft->bEof && pRight->bEof);
115949
- iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115950
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115951
- pExpr->iDocid = pLeft->iDocid;
115952
- }else{
115953
- pExpr->iDocid = pRight->iDocid;
115954
- }
115955
-
115956
- break;
115957
- }
115958
-
115959
- case FTSQUERY_NOT: {
115960
- Fts3Expr *pLeft = pExpr->pLeft;
115961
- Fts3Expr *pRight = pExpr->pRight;
115962
-
115963
- if( pRight->bStart==0 ){
115964
- fts3EvalNext(pCsr, pRight, pRc);
115965
- assert( *pRc!=SQLITE_OK || pRight->bStart );
115966
- }
115967
-
115968
- fts3EvalNext(pCsr, pLeft, pRc);
115969
- if( pLeft->bEof==0 ){
115970
- while( !*pRc
115971
- && !pRight->bEof
115972
- && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
115973
- ){
115974
- fts3EvalNext(pCsr, pRight, pRc);
115975
- }
115976
- }
115977
- pExpr->iDocid = pLeft->iDocid;
115978
- pExpr->bEof = pLeft->bEof;
115979
- break;
115980
- }
115981
-
115982
- default: {
115983
- Fts3Phrase *pPhrase = pExpr->pPhrase;
115984
- fts3EvalZeroPoslist(pPhrase);
115985
- *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
115986
- pExpr->iDocid = pPhrase->doclist.iDocid;
115987
- break;
115988
- }
115989
- }
115990
- }
115991
-}
115992
-
115993
-static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
115994
- int bHit = 1;
116698
+static int fts3EvalTestExpr(
116699
+ Fts3Cursor *pCsr, /* FTS cursor handle */
116700
+ Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
116701
+ int *pRc /* IN/OUT: Error code */
116702
+){
116703
+ int bHit = 1; /* Return value */
115995116704
if( *pRc==SQLITE_OK ){
115996116705
switch( pExpr->eType ){
115997116706
case FTSQUERY_NEAR:
115998116707
case FTSQUERY_AND:
115999116708
bHit = (
116000
- fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
116001
- && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
116709
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
116710
+ && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
116002116711
&& fts3EvalNearTest(pExpr, pRc)
116003116712
);
116004116713
116005116714
/* If the NEAR expression does not match any rows, zero the doclist for
116006116715
** all phrases involved in the NEAR. This is because the snippet(),
@@ -116022,31 +116731,31 @@
116022116731
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
116023116732
){
116024116733
Fts3Expr *p;
116025116734
for(p=pExpr; p->pPhrase==0; p=p->pLeft){
116026116735
if( p->pRight->iDocid==pCsr->iPrevId ){
116027
- fts3EvalZeroPoslist(p->pRight->pPhrase);
116736
+ fts3EvalInvalidatePoslist(p->pRight->pPhrase);
116028116737
}
116029116738
}
116030116739
if( p->iDocid==pCsr->iPrevId ){
116031
- fts3EvalZeroPoslist(p->pPhrase);
116740
+ fts3EvalInvalidatePoslist(p->pPhrase);
116032116741
}
116033116742
}
116034116743
116035116744
break;
116036116745
116037116746
case FTSQUERY_OR: {
116038
- int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
116039
- int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
116747
+ int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
116748
+ int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
116040116749
bHit = bHit1 || bHit2;
116041116750
break;
116042116751
}
116043116752
116044116753
case FTSQUERY_NOT:
116045116754
bHit = (
116046
- fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
116047
- && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
116755
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
116756
+ && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
116048116757
);
116049116758
break;
116050116759
116051116760
default: {
116052116761
if( pCsr->pDeferred
@@ -116053,11 +116762,11 @@
116053116762
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
116054116763
){
116055116764
Fts3Phrase *pPhrase = pExpr->pPhrase;
116056116765
assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
116057116766
if( pExpr->bDeferred ){
116058
- fts3EvalZeroPoslist(pPhrase);
116767
+ fts3EvalInvalidatePoslist(pPhrase);
116059116768
}
116060116769
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
116061116770
bHit = (pPhrase->doclist.pList!=0);
116062116771
pExpr->iDocid = pCsr->iPrevId;
116063116772
}else{
@@ -116069,31 +116778,53 @@
116069116778
}
116070116779
return bHit;
116071116780
}
116072116781
116073116782
/*
116074
-** Return 1 if both of the following are true:
116783
+** This function is called as the second part of each xNext operation when
116784
+** iterating through the results of a full-text query. At this point the
116785
+** cursor points to a row that matches the query expression, with the
116786
+** following caveats:
116787
+**
116788
+** * Up until this point, "NEAR" operators in the expression have been
116789
+** treated as "AND".
116790
+**
116791
+** * Deferred tokens have not yet been considered.
116792
+**
116793
+** If *pRc is not SQLITE_OK when this function is called, it immediately
116794
+** returns 0. Otherwise, it tests whether or not after considering NEAR
116795
+** operators and deferred tokens the current row is still a match for the
116796
+** expression. It returns 1 if both of the following are true:
116075116797
**
116076116798
** 1. *pRc is SQLITE_OK when this function returns, and
116077116799
**
116078116800
** 2. After scanning the current FTS table row for the deferred tokens,
116079
-** it is determined that the row does not match the query.
116801
+** it is determined that the row does *not* match the query.
116080116802
**
116081116803
** Or, if no error occurs and it seems the current row does match the FTS
116082116804
** query, return 0.
116083116805
*/
116084
-static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
116806
+static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
116085116807
int rc = *pRc;
116086116808
int bMiss = 0;
116087116809
if( rc==SQLITE_OK ){
116810
+
116811
+ /* If there are one or more deferred tokens, load the current row into
116812
+ ** memory and scan it to determine the position list for each deferred
116813
+ ** token. Then, see if this row is really a match, considering deferred
116814
+ ** tokens and NEAR operators (neither of which were taken into account
116815
+ ** earlier, by fts3EvalNextRow()).
116816
+ */
116088116817
if( pCsr->pDeferred ){
116089116818
rc = fts3CursorSeek(0, pCsr);
116090116819
if( rc==SQLITE_OK ){
116091116820
rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
116092116821
}
116093116822
}
116094
- bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
116823
+ bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
116824
+
116825
+ /* Free the position-lists accumulated for each deferred token above. */
116095116826
sqlite3Fts3FreeDeferredDoclists(pCsr);
116096116827
*pRc = rc;
116097116828
}
116098116829
return (rc==SQLITE_OK && bMiss);
116099116830
}
@@ -116100,11 +116831,11 @@
116100116831
116101116832
/*
116102116833
** Advance to the next document that matches the FTS expression in
116103116834
** Fts3Cursor.pExpr.
116104116835
*/
116105
-SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
116836
+static int fts3EvalNext(Fts3Cursor *pCsr){
116106116837
int rc = SQLITE_OK; /* Return Code */
116107116838
Fts3Expr *pExpr = pCsr->pExpr;
116108116839
assert( pCsr->isEof==0 );
116109116840
if( pExpr==0 ){
116110116841
pCsr->isEof = 1;
@@ -116112,23 +116843,23 @@
116112116843
do {
116113116844
if( pCsr->isRequireSeek==0 ){
116114116845
sqlite3_reset(pCsr->pStmt);
116115116846
}
116116116847
assert( sqlite3_data_count(pCsr->pStmt)==0 );
116117
- fts3EvalNext(pCsr, pExpr, &rc);
116848
+ fts3EvalNextRow(pCsr, pExpr, &rc);
116118116849
pCsr->isEof = pExpr->bEof;
116119116850
pCsr->isRequireSeek = 1;
116120116851
pCsr->isMatchinfoNeeded = 1;
116121116852
pCsr->iPrevId = pExpr->iDocid;
116122
- }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
116853
+ }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
116123116854
}
116124116855
return rc;
116125116856
}
116126116857
116127116858
/*
116128116859
** Restart interation for expression pExpr so that the next call to
116129
-** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental
116860
+** fts3EvalNext() visits the first row. Do not allow incremental
116130116861
** loading or merging of phrase doclists for this iteration.
116131116862
**
116132116863
** If *pRc is other than SQLITE_OK when this function is called, it is
116133116864
** a no-op. If an error occurs within this function, *pRc is set to an
116134116865
** SQLite error code before returning.
@@ -116140,11 +116871,11 @@
116140116871
){
116141116872
if( pExpr && *pRc==SQLITE_OK ){
116142116873
Fts3Phrase *pPhrase = pExpr->pPhrase;
116143116874
116144116875
if( pPhrase ){
116145
- fts3EvalZeroPoslist(pPhrase);
116876
+ fts3EvalInvalidatePoslist(pPhrase);
116146116877
if( pPhrase->bIncr ){
116147116878
assert( pPhrase->nToken==1 );
116148116879
assert( pPhrase->aToken[0].pSegcsr );
116149116880
sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
116150116881
*pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
@@ -116256,18 +116987,18 @@
116256116987
/* Ensure the %_content statement is reset. */
116257116988
if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
116258116989
assert( sqlite3_data_count(pCsr->pStmt)==0 );
116259116990
116260116991
/* Advance to the next document */
116261
- fts3EvalNext(pCsr, pRoot, &rc);
116992
+ fts3EvalNextRow(pCsr, pRoot, &rc);
116262116993
pCsr->isEof = pRoot->bEof;
116263116994
pCsr->isRequireSeek = 1;
116264116995
pCsr->isMatchinfoNeeded = 1;
116265116996
pCsr->iPrevId = pRoot->iDocid;
116266116997
}while( pCsr->isEof==0
116267116998
&& pRoot->eType==FTSQUERY_NEAR
116268
- && fts3EvalLoadDeferred(pCsr, &rc)
116999
+ && fts3EvalTestDeferredAndNear(pCsr, &rc)
116269117000
);
116270117001
116271117002
if( rc==SQLITE_OK && pCsr->isEof==0 ){
116272117003
fts3EvalUpdateCounts(pRoot);
116273117004
}
@@ -116285,14 +117016,14 @@
116285117016
**
116286117017
** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
116287117018
*/
116288117019
fts3EvalRestart(pCsr, pRoot, &rc);
116289117020
do {
116290
- fts3EvalNext(pCsr, pRoot, &rc);
117021
+ fts3EvalNextRow(pCsr, pRoot, &rc);
116291117022
assert( pRoot->bEof==0 );
116292117023
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
116293
- fts3EvalLoadDeferred(pCsr, &rc);
117024
+ fts3EvalTestDeferredAndNear(pCsr, &rc);
116294117025
}
116295117026
}
116296117027
return rc;
116297117028
}
116298117029
@@ -116419,18 +117150,32 @@
116419117150
*/
116420117151
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
116421117152
if( pPhrase ){
116422117153
int i;
116423117154
sqlite3_free(pPhrase->doclist.aAll);
116424
- fts3EvalZeroPoslist(pPhrase);
117155
+ fts3EvalInvalidatePoslist(pPhrase);
116425117156
memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116426117157
for(i=0; i<pPhrase->nToken; i++){
116427117158
fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
116428117159
pPhrase->aToken[i].pSegcsr = 0;
116429117160
}
116430117161
}
116431117162
}
117163
+
117164
+#if !SQLITE_CORE
117165
+/*
117166
+** Initialize API pointer table, if required.
117167
+*/
117168
+SQLITE_API int sqlite3_extension_init(
117169
+ sqlite3 *db,
117170
+ char **pzErrMsg,
117171
+ const sqlite3_api_routines *pApi
117172
+){
117173
+ SQLITE_EXTENSION_INIT2(pApi)
117174
+ return sqlite3Fts3Init(db);
117175
+}
117176
+#endif
116432117177
116433117178
#endif
116434117179
116435117180
/************** End of fts3.c ************************************************/
116436117181
/************** Begin file fts3_aux.c ****************************************/
@@ -118917,14 +119662,10 @@
118917119662
** (in which case SQLITE_CORE is not defined), or
118918119663
**
118919119664
** * The FTS3 module is being built into the core of
118920119665
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
118921119666
*/
118922
-#ifndef SQLITE_CORE
118923
- SQLITE_EXTENSION_INIT1
118924
-#endif
118925
-
118926119667
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
118927119668
118928119669
118929119670
/*
118930119671
** Implementation of the SQL scalar function for accessing the underlying
118931119672
--- 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.
@@ -648,13 +648,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-24 11:29:51 9b191bb4c7c1e1b12b188c0b3eee1f8f587887c8"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -1282,20 +1282,37 @@
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
@@ -9558,10 +9575,11 @@
9558 #define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
9559 #define SQLITE_IndexCover 0x10 /* Disable index covering table */
9560 #define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
9561 #define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
9562 #define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */
 
9563 #define SQLITE_OptMask 0xff /* Mask of all disablable opts */
9564
9565 /*
9566 ** Possible values for the sqlite.magic field.
9567 ** The numbers are obtained at random and have no special meaning, other
@@ -10449,10 +10467,11 @@
10449 Table *pTab; /* An SQL table corresponding to zName */
10450 Select *pSelect; /* A SELECT statement used in place of a table name */
10451 u8 isPopulated; /* Temporary table associated with SELECT is populated */
10452 u8 jointype; /* Type of join between this able and the previous */
10453 u8 notIndexed; /* True if there is a NOT INDEXED clause */
 
10454 #ifndef SQLITE_OMIT_EXPLAIN
10455 u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
10456 #endif
10457 int iCursor; /* The VDBE cursor number used to access this table */
10458 Expr *pOn; /* The ON clause of a join */
@@ -10568,10 +10587,11 @@
10568 struct WhereInfo {
10569 Parse *pParse; /* Parsing and code generating context */
10570 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
10571 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
10572 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
 
10573 SrcList *pTabList; /* List of tables in the join */
10574 int iTop; /* The very beginning of the WHERE loop */
10575 int iContinue; /* Jump here to continue with next record */
10576 int iBreak; /* Jump here to break out of the loop */
10577 int nLevel; /* Number of nested loop */
@@ -10579,10 +10599,13 @@
10579 double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
10580 double nRowOut; /* Estimated number of output rows */
10581 WhereLevel a[1]; /* Information about each nest loop in WHERE */
10582 };
10583
 
 
 
10584 /*
10585 ** A NameContext defines a context in which to resolve table and column
10586 ** names. The context consists of a list of tables (the pSrcList) field and
10587 ** a list of named expression (pEList). The named expression list may
10588 ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
@@ -11340,11 +11363,11 @@
11340 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
11341 SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
11342 #endif
11343 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
11344 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11345 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
11346 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
11347 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
11348 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
11349 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
11350 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
@@ -15841,11 +15864,11 @@
15841 ** Free an outstanding memory allocation.
15842 **
15843 ** This function assumes that the necessary mutexes, if any, are
15844 ** already held by the caller. Hence "Unsafe".
15845 */
15846 void memsys3FreeUnsafe(void *pOld){
15847 Mem3Block *p = (Mem3Block*)pOld;
15848 int i;
15849 u32 size, x;
15850 assert( sqlite3_mutex_held(mem3.mutex) );
15851 assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
@@ -15916,21 +15939,21 @@
15916 }
15917
15918 /*
15919 ** Free memory.
15920 */
15921 void memsys3Free(void *pPrior){
15922 assert( pPrior );
15923 memsys3Enter();
15924 memsys3FreeUnsafe(pPrior);
15925 memsys3Leave();
15926 }
15927
15928 /*
15929 ** Change the size of an existing memory allocation
15930 */
15931 void *memsys3Realloc(void *pPrior, int nBytes){
15932 int nOld;
15933 void *p;
15934 if( pPrior==0 ){
15935 return sqlite3_malloc(nBytes);
15936 }
@@ -25143,11 +25166,13 @@
25143 case EINVAL:
25144 case ENOTCONN:
25145 case ENODEV:
25146 case ENXIO:
25147 case ENOENT:
 
25148 case ESTALE:
 
25149 case ENOSYS:
25150 /* these should force the client to close the file and reconnect */
25151
25152 default:
25153 return sqliteIOErr;
@@ -31820,10 +31845,58 @@
31820 iLine, iErrno, zFunc, zPath, zMsg
31821 );
31822
31823 return errcode;
31824 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31825
31826 #if SQLITE_OS_WINCE
31827 /*************************************************************************
31828 ** This section contains code for WinCE only.
31829 */
@@ -32238,22 +32311,25 @@
32238 int amt, /* Number of bytes to read */
32239 sqlite3_int64 offset /* Begin reading at this offset */
32240 ){
32241 winFile *pFile = (winFile*)id; /* file handle */
32242 DWORD nRead; /* Number of bytes actually read from file */
 
32243
32244 assert( id!=0 );
32245 SimulateIOError(return SQLITE_IOERR_READ);
32246 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
32247
32248 if( seekWinFile(pFile, offset) ){
32249 return SQLITE_FULL;
32250 }
32251 if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
 
32252 pFile->lastErrno = GetLastError();
32253 return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
32254 }
 
32255 if( nRead<(DWORD)amt ){
32256 /* Unread parts of the buffer must be zero-filled */
32257 memset(&((char*)pBuf)[nRead], 0, amt-nRead);
32258 return SQLITE_IOERR_SHORT_READ;
32259 }
@@ -32271,10 +32347,11 @@
32271 int amt, /* Number of bytes to write */
32272 sqlite3_int64 offset /* Offset into the file to begin writing at */
32273 ){
32274 int rc; /* True if error has occured, else false */
32275 winFile *pFile = (winFile*)id; /* File handle */
 
32276
32277 assert( amt>0 );
32278 assert( pFile );
32279 SimulateIOError(return SQLITE_IOERR_WRITE);
32280 SimulateDiskfullError(return SQLITE_FULL);
@@ -32285,11 +32362,16 @@
32285 if( rc==0 ){
32286 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
32287 int nRem = amt; /* Number of bytes yet to be written */
32288 DWORD nWrite; /* Bytes written by each WriteFile() call */
32289
32290 while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
 
 
 
 
 
32291 aRem += nWrite;
32292 nRem -= nWrite;
32293 }
32294 if( nRem>0 ){
32295 pFile->lastErrno = GetLastError();
@@ -32301,10 +32383,12 @@
32301 if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
32302 || ( pFile->lastErrno==ERROR_DISK_FULL )){
32303 return SQLITE_FULL;
32304 }
32305 return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
 
 
32306 }
32307 return SQLITE_OK;
32308 }
32309
32310 /*
@@ -32716,10 +32800,24 @@
32716 SimulateIOErrorBenign(0);
32717 return SQLITE_OK;
32718 }
32719 case SQLITE_FCNTL_SYNC_OMITTED: {
32720 return SQLITE_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32721 }
32722 }
32723 return SQLITE_NOTFOUND;
32724 }
32725
@@ -33734,19 +33832,17 @@
33734 ** file open, we will be unable to delete it. To work around this
33735 ** problem, we delay 100 milliseconds and try to delete again. Up
33736 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
33737 ** up and returning an error.
33738 */
33739 #define MX_DELETION_ATTEMPTS 5
33740 static int winDelete(
33741 sqlite3_vfs *pVfs, /* Not used on win32 */
33742 const char *zFilename, /* Name of file to delete */
33743 int syncDir /* Not used on win32 */
33744 ){
33745 int cnt = 0;
33746 DWORD rc;
33747 DWORD error = 0;
33748 void *zConverted;
33749 UNUSED_PARAMETER(pVfs);
33750 UNUSED_PARAMETER(syncDir);
33751
33752 SimulateIOError(return SQLITE_IOERR_DELETE);
@@ -33753,38 +33849,34 @@
33753 zConverted = convertUtf8Filename(zFilename);
33754 if( zConverted==0 ){
33755 return SQLITE_NOMEM;
33756 }
33757 if( isNT() ){
33758 do{
33759 DeleteFileW(zConverted);
33760 }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
33761 || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33762 && (++cnt < MX_DELETION_ATTEMPTS)
33763 && (Sleep(100), 1) );
33764 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
33765 ** Since the ASCII version of these Windows API do not exist for WINCE,
33766 ** it's important to not reference them for WINCE builds.
33767 */
33768 #if SQLITE_OS_WINCE==0
33769 }else{
33770 do{
33771 DeleteFileA(zConverted);
33772 }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
33773 || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
33774 && (++cnt < MX_DELETION_ATTEMPTS)
33775 && (Sleep(100), 1) );
33776 #endif
33777 }
 
 
 
 
 
33778 free(zConverted);
33779 OSTRACE(("DELETE \"%s\" %s\n", zFilename,
33780 ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
33781 "ok" : "failed" ));
33782
33783 return ( (rc == INVALID_FILE_ATTRIBUTES)
33784 && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
33785 winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
33786 }
33787
33788 /*
33789 ** Check the existance and status of a file.
33790 */
@@ -59049,10 +59141,11 @@
59049 nMem = 10;
59050 }
59051 memset(zCsr, 0, zEnd-zCsr);
59052 zCsr += (zCsr - (u8*)0)&7;
59053 assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
 
59054
59055 /* Memory for registers, parameters, cursor, etc, is allocated in two
59056 ** passes. On the first pass, we try to reuse unused space at the
59057 ** end of the opcode array. If we are unable to satisfy all memory
59058 ** requirements by reusing the opcode array tail, then the second
@@ -61277,11 +61370,11 @@
61277 sqlite3_mutex_enter(db->mutex);
61278 while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
61279 && cnt++ < SQLITE_MAX_SCHEMA_RETRY
61280 && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
61281 sqlite3_reset(pStmt);
61282 v->expired = 0;
61283 }
61284 if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
61285 /* This case occurs after failing to recompile an sql statement.
61286 ** The error message from the SQL compiler has already been loaded
61287 ** into the database handle. This block copies the error message
@@ -65968,11 +66061,11 @@
65968 ** automatically created table with root-page 1 (an BLOB_INTKEY table).
65969 */
65970 if( pOp->p4.pKeyInfo ){
65971 int pgno;
65972 assert( pOp->p4type==P4_KEYINFO );
65973 rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY);
65974 if( rc==SQLITE_OK ){
65975 assert( pgno==MASTER_ROOT+1 );
65976 rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
65977 (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
65978 u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
@@ -71007,15 +71100,29 @@
71007 /* Recursively resolve names in all subqueries
71008 */
71009 for(i=0; i<p->pSrc->nSrc; i++){
71010 struct SrcList_item *pItem = &p->pSrc->a[i];
71011 if( pItem->pSelect ){
 
 
71012 const char *zSavedContext = pParse->zAuthContext;
 
 
 
 
 
 
 
 
71013 if( pItem->zName ) pParse->zAuthContext = pItem->zName;
71014 sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
71015 pParse->zAuthContext = zSavedContext;
71016 if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
 
 
 
 
71017 }
71018 }
71019
71020 /* If there are no aggregate functions in the result-set, and no GROUP BY
71021 ** expression, do not allow aggregates in any of the other expressions.
@@ -72119,10 +72226,11 @@
72119 pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
72120 pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
72121 pNewItem->jointype = pOldItem->jointype;
72122 pNewItem->iCursor = pOldItem->iCursor;
72123 pNewItem->isPopulated = pOldItem->isPopulated;
 
72124 pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
72125 pNewItem->notIndexed = pOldItem->notIndexed;
72126 pNewItem->pIndex = pOldItem->pIndex;
72127 pTab = pNewItem->pTab = pOldItem->pTab;
72128 if( pTab ){
@@ -80126,11 +80234,11 @@
80126 if( pStart ){
80127 assert( pEnd!=0 );
80128 /* A named index with an explicit CREATE INDEX statement */
80129 zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
80130 onError==OE_None ? "" : " UNIQUE",
80131 pEnd->z - pName->z + 1,
80132 pName->z);
80133 }else{
80134 /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
80135 /* zStmt = sqlite3MPrintf(""); */
80136 zStmt = 0;
@@ -81921,11 +82029,13 @@
81921 int regRowid; /* Actual register containing rowids */
81922
81923 /* Collect rowids of every row to be deleted.
81924 */
81925 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
81926 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
 
 
81927 if( pWInfo==0 ) goto delete_from_cleanup;
81928 regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
81929 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
81930 if( db->flags & SQLITE_CountRows ){
81931 sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
@@ -84368,11 +84478,11 @@
84368
84369 /* Create VDBE to loop through the entries in pSrc that match the WHERE
84370 ** clause. If the constraint is not deferred, throw an exception for
84371 ** each row found. Otherwise, for deferred constraints, increment the
84372 ** deferred constraint counter by nIncr for each row selected. */
84373 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0);
84374 if( nIncr>0 && pFKey->isDeferred==0 ){
84375 sqlite3ParseToplevel(pParse)->mayAbort = 1;
84376 }
84377 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
84378 if( pWInfo ){
@@ -87235,10 +87345,13 @@
87235 int (*strnicmp)(const char*,const char*,int);
87236 int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
87237 int (*wal_autocheckpoint)(sqlite3*,int);
87238 int (*wal_checkpoint)(sqlite3*,const char*);
87239 void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
 
 
 
87240 };
87241
87242 /*
87243 ** The following macros redefine the API routines so that they are
87244 ** redirected throught the global sqlite3_api structure.
@@ -87435,10 +87548,13 @@
87435 #define sqlite3_strnicmp sqlite3_api->strnicmp
87436 #define sqlite3_unlock_notify sqlite3_api->unlock_notify
87437 #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
87438 #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
87439 #define sqlite3_wal_hook sqlite3_api->wal_hook
 
 
 
87440 #endif /* SQLITE_CORE */
87441
87442 #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
87443 #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
87444
@@ -87509,10 +87625,12 @@
87509
87510 #ifdef SQLITE_OMIT_VIRTUALTABLE
87511 # define sqlite3_create_module 0
87512 # define sqlite3_create_module_v2 0
87513 # define sqlite3_declare_vtab 0
 
 
87514 #endif
87515
87516 #ifdef SQLITE_OMIT_SHARED_CACHE
87517 # define sqlite3_enable_shared_cache 0
87518 #endif
@@ -87532,10 +87650,11 @@
87532 #define sqlite3_blob_bytes 0
87533 #define sqlite3_blob_close 0
87534 #define sqlite3_blob_open 0
87535 #define sqlite3_blob_read 0
87536 #define sqlite3_blob_write 0
 
87537 #endif
87538
87539 /*
87540 ** The following structure contains pointers to all SQLite API routines.
87541 ** A pointer to this structure is passed into extensions when they are
@@ -87797,10 +87916,13 @@
87797 #else
87798 0,
87799 0,
87800 0,
87801 #endif
 
 
 
87802 };
87803
87804 /*
87805 ** Attempt to load an SQLite extension library contained in the file
87806 ** zFile. The entry point is zProc. zProc may be 0 in which case a
@@ -94186,10 +94308,11 @@
94186 Expr *pHaving; /* The HAVING clause. May be NULL */
94187 int isDistinct; /* True if the DISTINCT keyword is present */
94188 int distinct; /* Table to use for the distinct set */
94189 int rc = 1; /* Value to return from this function */
94190 int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
 
94191 AggInfo sAggInfo; /* Information used by aggregate queries */
94192 int iEnd; /* Address of the end of the query */
94193 sqlite3 *db; /* The database connection */
94194
94195 #ifndef SQLITE_OMIT_EXPLAIN
@@ -94312,20 +94435,10 @@
94312 explainSetInteger(pParse->iSelectId, iRestoreSelectId);
94313 return rc;
94314 }
94315 #endif
94316
94317 /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
94318 ** GROUP BY might use an index, DISTINCT never does.
94319 */
94320 assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
94321 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
94322 p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
94323 pGroupBy = p->pGroupBy;
94324 p->selFlags &= ~SF_Distinct;
94325 }
94326
94327 /* If there is both a GROUP BY and an ORDER BY clause and they are
94328 ** identical, then disable the ORDER BY clause since the GROUP BY
94329 ** will cause elements to come out in the correct order. This is
94330 ** an optimization - the correct answer should result regardless.
94331 ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
@@ -94333,10 +94446,34 @@
94333 */
94334 if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
94335 && (db->flags & SQLITE_GroupByOrder)==0 ){
94336 pOrderBy = 0;
94337 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94338
94339 /* If there is an ORDER BY clause, then this sorting
94340 ** index might end up being unused if the data can be
94341 ** extracted in pre-sorted order. If that is the case, then the
94342 ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
@@ -94369,26 +94506,25 @@
94369
94370 /* Open a virtual index to use for the distinct set.
94371 */
94372 if( p->selFlags & SF_Distinct ){
94373 KeyInfo *pKeyInfo;
94374 assert( isAgg || pGroupBy );
94375 distinct = pParse->nTab++;
94376 pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
94377 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
94378 (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
94379 sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
94380 }else{
94381 distinct = -1;
94382 }
94383
94384 /* Aggregate and non-aggregate queries are handled differently */
94385 if( !isAgg && pGroupBy==0 ){
94386 /* This case is for non-aggregate queries
94387 ** Begin the database scan
94388 */
94389 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
94390 if( pWInfo==0 ) goto select_end;
94391 if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
94392
94393 /* If sorting index that was created by a prior OP_OpenEphemeral
94394 ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -94397,14 +94533,56 @@
94397 if( addrSortIndex>=0 && pOrderBy==0 ){
94398 sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
94399 p->addrOpenEphm[2] = -1;
94400 }
94401
94402 /* Use the standard inner loop
94403 */
94404 assert(!isDistinct);
94405 selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94406 pWInfo->iContinue, pWInfo->iBreak);
94407
94408 /* End the database scan loop.
94409 */
94410 sqlite3WhereEnd(pWInfo);
@@ -94510,11 +94688,11 @@
94510 ** This might involve two separate loops with an OP_Sort in between, or
94511 ** it might be a single loop that uses an index to extract information
94512 ** in the right order to begin with.
94513 */
94514 sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
94515 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
94516 if( pWInfo==0 ) goto select_end;
94517 if( pGroupBy==0 ){
94518 /* The optimizer is able to deliver rows in group by order so
94519 ** we do not have to sort. The OP_OpenEphemeral table will be
94520 ** cancelled later because we still need to use the pKeyInfo
@@ -94772,11 +94950,11 @@
94772 /* This case runs if the aggregate has no GROUP BY clause. The
94773 ** processing is much simpler since there is only a single row
94774 ** of output.
94775 */
94776 resetAccumulator(pParse, &sAggInfo);
94777 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
94778 if( pWInfo==0 ){
94779 sqlite3ExprListDelete(db, pDel);
94780 goto select_end;
94781 }
94782 updateAccumulator(pParse, &sAggInfo);
@@ -95248,19 +95426,32 @@
95248 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
95249 if( iDb<0 ){
95250 goto trigger_cleanup;
95251 }
95252 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95253
95254 /* If the trigger name was unqualified, and the table is a temp table,
95255 ** then set iDb to 1 to create the trigger in the temporary database.
95256 ** If sqlite3SrcListLookup() returns 0, indicating the table does not
95257 ** exist, the error is caught by the block below.
95258 */
95259 if( !pTableName || db->mallocFailed ){
95260 goto trigger_cleanup;
95261 }
95262 pTab = sqlite3SrcListLookup(pParse, pTableName);
95263 if( db->init.busy==0 && pName2->n==0 && pTab
95264 && pTab->pSchema==db->aDb[1].pSchema ){
95265 iDb = 1;
95266 }
@@ -96554,11 +96745,13 @@
96554 }
96555
96556 /* Begin the database scan
96557 */
96558 sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
96559 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
 
 
96560 if( pWInfo==0 ) goto update_cleanup;
96561 okOnePass = pWInfo->okOnePass;
96562
96563 /* Remember the rowid of every item to be updated.
96564 */
@@ -98580,10 +98773,11 @@
98580 #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
98581 #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
98582 #define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
98583 #define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
98584 #define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
 
98585
98586 /*
98587 ** Initialize a preallocated WhereClause structure.
98588 */
98589 static void whereClauseInit(
@@ -99724,10 +99918,166 @@
99724 }
99725 }
99726 return 0;
99727 }
99728
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99729
99730 /*
99731 ** This routine decides if pIdx can be used to satisfy the ORDER BY
99732 ** clause. If it can, it returns 1. If pIdx cannot satisfy the
99733 ** ORDER BY clause, this routine returns 0.
@@ -99760,11 +100110,14 @@
99760 int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
99761 int nTerm; /* Number of ORDER BY terms */
99762 struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
99763 sqlite3 *db = pParse->db;
99764
99765 assert( pOrderBy!=0 );
 
 
 
99766 nTerm = pOrderBy->nExpr;
99767 assert( nTerm>0 );
99768
99769 /* Argument pIdx must either point to a 'real' named index structure,
99770 ** or an index structure allocated on the stack by bestBtreeIndex() to
@@ -100073,10 +100426,14 @@
100073 double costTempIdx; /* per-query cost of the transient index */
100074 WhereTerm *pTerm; /* A single term of the WHERE clause */
100075 WhereTerm *pWCEnd; /* End of pWC->a[] */
100076 Table *pTable; /* Table tht might be indexed */
100077
 
 
 
 
100078 if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
100079 /* Automatic indices are disabled at run-time */
100080 return;
100081 }
100082 if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
@@ -100084,10 +100441,14 @@
100084 return;
100085 }
100086 if( pSrc->notIndexed ){
100087 /* The NOT INDEXED clause appears in the SQL. */
100088 return;
 
 
 
 
100089 }
100090
100091 assert( pParse->nQueryLoop >= (double)1 );
100092 pTable = pSrc->pTab;
100093 nTableRow = pTable->nRowEst;
@@ -101016,10 +101377,11 @@
101016 WhereClause *pWC, /* The WHERE clause */
101017 struct SrcList_item *pSrc, /* The FROM clause term to search */
101018 Bitmask notReady, /* Mask of cursors not available for indexing */
101019 Bitmask notValid, /* Cursors not available for any purpose */
101020 ExprList *pOrderBy, /* The ORDER BY clause */
 
101021 WhereCost *pCost /* Lowest cost query plan */
101022 ){
101023 int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
101024 Index *pProbe; /* An index we are evaluating */
101025 Index *pIdx; /* Copy of pProbe, or zero for IPK index */
@@ -101156,11 +101518,12 @@
101156 int nEq; /* Number of == or IN terms matching index */
101157 int bInEst = 0; /* True if "x IN (SELECT...)" seen */
101158 int nInMul = 1; /* Number of distinct equalities to lookup */
101159 int estBound = 100; /* Estimated reduction in search space */
101160 int nBound = 0; /* Number of range constraints seen */
101161 int bSort = 0; /* True if external sort required */
 
101162 int bLookup = 0; /* True if not a covering index */
101163 WhereTerm *pTerm; /* A single term of the WHERE clause */
101164 #ifdef SQLITE_ENABLE_STAT2
101165 WhereTerm *pFirstTerm = 0; /* First term matching the index */
101166 #endif
@@ -101220,21 +101583,24 @@
101220
101221 /* If there is an ORDER BY clause and the index being considered will
101222 ** naturally scan rows in the required order, set the appropriate flags
101223 ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
101224 ** will scan rows in a different order, set the bSort variable. */
101225 if( pOrderBy ){
101226 if( (wsFlags & WHERE_COLUMN_IN)==0
101227 && pProbe->bUnordered==0
101228 && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
101229 nEq, wsFlags, &rev)
101230 ){
101231 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
101232 wsFlags |= (rev ? WHERE_REVERSE : 0);
101233 }else{
101234 bSort = 1;
101235 }
 
 
 
101236 }
101237
101238 /* If currently calculating the cost of using an index (not the IPK
101239 ** index), determine if all required column data may be obtained without
101240 ** using the main table (i.e. if the index is a covering
@@ -101265,16 +101631,17 @@
101265 nRow = aiRowEst[0]/2;
101266 nInMul = (int)(nRow / aiRowEst[nEq]);
101267 }
101268
101269 #ifdef SQLITE_ENABLE_STAT2
101270 /* If the constraint is of the form x=VALUE and histogram
 
101271 ** data is available for column x, then it might be possible
101272 ** to get a better estimate on the number of rows based on
101273 ** VALUE and how common that value is according to the histogram.
101274 */
101275 if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
101276 if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
101277 testcase( pFirstTerm->eOperator==WO_EQ );
101278 testcase( pFirstTerm->eOperator==WO_ISNULL );
101279 whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
101280 }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
@@ -101347,10 +101714,13 @@
101347 ** difference and select C of 3.0.
101348 */
101349 if( bSort ){
101350 cost += nRow*estLog(nRow)*3;
101351 }
 
 
 
101352
101353 /**** Cost of using this index has now been computed ****/
101354
101355 /* If there are additional constraints on this table that cannot
101356 ** be used with the current index, but which might lower the number
@@ -101492,11 +101862,11 @@
101492 }
101493 sqlite3DbFree(pParse->db, p);
101494 }else
101495 #endif
101496 {
101497 bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
101498 }
101499 }
101500
101501 /*
101502 ** Disable a term in the WHERE clause. Except, do not disable the term
@@ -102454,11 +102824,11 @@
102454 for(ii=0; ii<pOrWc->nTerm; ii++){
102455 WhereTerm *pOrTerm = &pOrWc->a[ii];
102456 if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
102457 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
102458 /* Loop through table entries that match term pOrTerm. */
102459 pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
102460 WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
102461 WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
102462 if( pSubWInfo ){
102463 explainOneScan(
102464 pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -102695,10 +103065,11 @@
102695 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
102696 Parse *pParse, /* The parser context */
102697 SrcList *pTabList, /* A list of all tables to be scanned */
102698 Expr *pWhere, /* The WHERE clause */
102699 ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
 
102700 u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
102701 ){
102702 int i; /* Loop counter */
102703 int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
102704 int nTabList; /* Number of elements in pTabList */
@@ -102754,10 +103125,14 @@
102754 pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
102755 pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
102756 pWInfo->wctrlFlags = wctrlFlags;
102757 pWInfo->savedNQueryLoop = pParse->nQueryLoop;
102758 pMaskSet = (WhereMaskSet*)&pWC[1];
 
 
 
 
102759
102760 /* Split the WHERE clause into separate subexpressions where each
102761 ** subexpression is separated by an AND operator.
102762 */
102763 initMaskSet(pMaskSet);
@@ -102821,10 +103196,19 @@
102821 */
102822 exprAnalyzeAll(pTabList, pWC);
102823 if( db->mallocFailed ){
102824 goto whereBeginError;
102825 }
 
 
 
 
 
 
 
 
 
102826
102827 /* Chose the best index to use for each table in the FROM clause.
102828 **
102829 ** This loop fills in the following fields:
102830 **
@@ -102905,10 +103289,11 @@
102905 Bitmask mask; /* Mask of tables not yet ready */
102906 for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
102907 int doNotReorder; /* True if this table should not be reordered */
102908 WhereCost sCost; /* Cost information from best[Virtual]Index() */
102909 ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
 
102910
102911 doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
102912 if( j!=iFrom && doNotReorder ) break;
102913 m = getMask(pMaskSet, pTabItem->iCursor);
102914 if( (m & notReady)==0 ){
@@ -102915,10 +103300,11 @@
102915 if( j==iFrom ) iFrom++;
102916 continue;
102917 }
102918 mask = (isOptimal ? m : notReady);
102919 pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
 
102920 if( pTabItem->pIndex==0 ) nUnconstrained++;
102921
102922 WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
102923 j, isOptimal));
102924 assert( pTabItem->pTab );
@@ -102929,11 +103315,11 @@
102929 &sCost, pp);
102930 }else
102931 #endif
102932 {
102933 bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
102934 &sCost);
102935 }
102936 assert( isOptimal || (sCost.used&notReady)==0 );
102937
102938 /* If an INDEXED BY clause is present, then the plan must use that
102939 ** index if it uses any index at all */
@@ -102989,10 +103375,14 @@
102989 WHERETRACE(("*** Optimizer selects table %d for loop %d"
102990 " with cost=%g and nRow=%g\n",
102991 bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
102992 if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
102993 *ppOrderBy = 0;
 
 
 
 
102994 }
102995 andFlags &= bestPlan.plan.wsFlags;
102996 pLevel->plan = bestPlan.plan;
102997 testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
102998 testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
@@ -111519,11 +111909,17 @@
111519 */
111520 #if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
111521 # define SQLITE_ENABLE_FTS3
111522 #endif
111523
111524 #ifdef SQLITE_ENABLE_FTS3
 
 
 
 
 
 
111525 /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
111526 /************** Begin file fts3_tokenizer.h **********************************/
111527 /*
111528 ** 2006 July 10
111529 **
@@ -112052,11 +112448,11 @@
112052
112053 sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
112054 int bFreeList; /* True if pList should be sqlite3_free()d */
112055 char *pList; /* Pointer to position list following iDocid */
112056 int nList; /* Length of position list */
112057 } doclist;
112058
112059 /*
112060 ** A "phrase" is a sequence of one or more tokens that must match in
112061 ** sequence. A single token is the base case and the most common case.
112062 ** For a sequence of tokens contained in double-quotes (i.e. "one two three")
@@ -112252,23 +112648,12 @@
112252 #endif
112253
112254 /* fts3_aux.c */
112255 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
112256
112257 SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
112258 Fts3Cursor *pCsr, /* Virtual table cursor handle */
112259 const char *zTerm, /* Term to query for */
112260 int nTerm, /* Size of zTerm in bytes */
112261 int isPrefix, /* True for a prefix search */
112262 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
112263 );
112264
112265 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
112266
112267 SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
112268 SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
112269
112270 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
112271 Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
112272 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
112273 Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
112274 SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
@@ -112275,11 +112660,11 @@
112275 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
112276 SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
112277
112278 SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
112279
112280 #endif /* SQLITE_ENABLE_FTS3 */
112281 #endif /* _FTSINT_H */
112282
112283 /************** End of fts3Int.h *********************************************/
112284 /************** Continuing where we left off in fts3.c ***********************/
112285 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
@@ -112291,10 +112676,15 @@
112291
112292 #ifndef SQLITE_CORE
112293 SQLITE_EXTENSION_INIT1
112294 #endif
112295
 
 
 
 
 
112296 /*
112297 ** Write a 64-bit variable-length integer to memory starting at p[0].
112298 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
112299 ** The number of bytes written is returned.
112300 */
@@ -112799,31 +113189,60 @@
112799 }
112800 sqlite3_free(zFree);
112801 return zRet;
112802 }
112803
 
 
 
 
 
 
 
 
 
 
 
 
 
112804 static int fts3GobbleInt(const char **pp, int *pnOut){
112805 const char *p = *pp;
112806 int nInt = 0;
 
112807 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
112808 nInt = nInt * 10 + (p[0] - '0');
112809 }
112810 if( p==*pp ) return SQLITE_ERROR;
112811 *pnOut = nInt;
112812 *pp = p;
112813 return SQLITE_OK;
112814 }
112815
112816
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112817 static int fts3PrefixParameter(
112818 const char *zParam, /* ABC in prefix=ABC parameter to parse */
112819 int *pnIndex, /* OUT: size of *apIndex[] array */
112820 struct Fts3Index **apIndex, /* OUT: Array of indexes for this table */
112821 struct Fts3Index **apFree /* OUT: Free this with sqlite3_free() */
112822 ){
112823 struct Fts3Index *aIndex;
112824 int nIndex = 1;
112825
112826 if( zParam && zParam[0] ){
112827 const char *p;
112828 nIndex++;
112829 for(p=zParam; *p; p++){
@@ -112830,11 +113249,11 @@
112830 if( *p==',' ) nIndex++;
112831 }
112832 }
112833
112834 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
112835 *apIndex = *apFree = aIndex;
112836 *pnIndex = nIndex;
112837 if( !aIndex ){
112838 return SQLITE_NOMEM;
112839 }
112840
@@ -112887,12 +113306,11 @@
112887 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
112888 const char **aCol; /* Array of column names */
112889 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
112890
112891 int nIndex; /* Size of aIndex[] array */
112892 struct Fts3Index *aIndex; /* Array of indexes for this table */
112893 struct Fts3Index *aFree = 0; /* Free this before returning */
112894
112895 /* The results of parsing supported FTS4 key=value options: */
112896 int bNoDocsize = 0; /* True to omit %_docsize table */
112897 int bDescIdx = 0; /* True to store descending indexes */
112898 char *zPrefix = 0; /* Prefix parameter value (or NULL) */
@@ -113025,11 +113443,11 @@
113025 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
113026 if( rc!=SQLITE_OK ) goto fts3_init_out;
113027 }
113028 assert( pTokenizer );
113029
113030 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
113031 if( rc==SQLITE_ERROR ){
113032 assert( zPrefix );
113033 *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
113034 }
113035 if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -113112,11 +113530,11 @@
113112 /* Declare the table schema to SQLite. */
113113 fts3DeclareVtab(&rc, p);
113114
113115 fts3_init_out:
113116 sqlite3_free(zPrefix);
113117 sqlite3_free(aFree);
113118 sqlite3_free(zCompress);
113119 sqlite3_free(zUncompress);
113120 sqlite3_free((void *)aCol);
113121 if( rc!=SQLITE_OK ){
113122 if( p ){
@@ -113703,12 +114121,10 @@
113703 *pp1 = p1 + 1;
113704 *pp2 = p2 + 1;
113705 }
113706
113707 /*
113708 ** nToken==1 searches for adjacent positions.
113709 **
113710 ** This function is used to merge two position lists into one. When it is
113711 ** called, *pp1 and *pp2 must both point to position lists. A position-list is
113712 ** the part of a doclist that follows each document id. For example, if a row
113713 ** contains:
113714 **
@@ -113724,10 +114140,12 @@
113724 ** If isSaveLeft is 0, an entry is added to the output position list for
113725 ** each position in *pp2 for which there exists one or more positions in
113726 ** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
113727 ** when the *pp1 token appears before the *pp2 token, but not more than nToken
113728 ** slots before it.
 
 
113729 */
113730 static int fts3PoslistPhraseMerge(
113731 char **pp, /* IN/OUT: Preallocated output buffer */
113732 int nToken, /* Maximum difference in token positions */
113733 int isSaveLeft, /* Save the left position */
@@ -113890,26 +114308,38 @@
113890
113891 return res;
113892 }
113893
113894 /*
113895 ** A pointer to an instance of this structure is used as the context
113896 ** argument to sqlite3Fts3SegReaderIterate()
 
113897 */
113898 typedef struct TermSelect TermSelect;
113899 struct TermSelect {
113900 int isReqPos;
113901 char *aaOutput[16]; /* Malloc'd output buffer */
113902 int anOutput[16]; /* Size of output in bytes */
113903 };
113904
113905
 
 
 
 
 
 
 
 
 
 
 
 
113906 static void fts3GetDeltaVarint3(
113907 char **pp,
113908 char *pEnd,
113909 int bDescIdx,
113910 sqlite3_int64 *pVal
113911 ){
113912 if( *pp>=pEnd ){
113913 *pp = 0;
113914 }else{
113915 sqlite3_int64 iVal;
@@ -113920,10 +114350,25 @@
113920 *pVal += iVal;
113921 }
113922 }
113923 }
113924
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113925 static void fts3PutDeltaVarint3(
113926 char **pp, /* IN/OUT: Output pointer */
113927 int bDescIdx, /* True for descending docids */
113928 sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
113929 int *pbFirst, /* IN/OUT: True after first int written */
@@ -113940,14 +114385,38 @@
113940 *pp += sqlite3Fts3PutVarint(*pp, iWrite);
113941 *piPrev = iVal;
113942 *pbFirst = 1;
113943 }
113944
113945 #define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))
113946
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113947 static int fts3DoclistOrMerge(
113948 int bDescIdx, /* True if arguments are desc */
113949 char *a1, int n1, /* First doclist */
113950 char *a2, int n2, /* Second doclist */
113951 char **paOut, int *pnOut /* OUT: Malloc'd doclist */
113952 ){
113953 sqlite3_int64 i1 = 0;
@@ -113968,35 +114437,47 @@
113968
113969 p = aOut;
113970 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
113971 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
113972 while( p1 || p2 ){
113973 sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
113974
113975 if( p2 && p1 && iDiff==0 ){
113976 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113977 fts3PoslistMerge(&p, &p1, &p2);
113978 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113979 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113980 }else if( !p2 || (p1 && iDiff<0) ){
113981 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
113982 fts3PoslistCopy(&p, &p1);
113983 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
113984 }else{
113985 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
113986 fts3PoslistCopy(&p, &p2);
113987 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
113988 }
113989 }
113990
113991 *paOut = aOut;
113992 *pnOut = (p-aOut);
113993 return SQLITE_OK;
113994 }
113995
 
 
 
 
 
 
 
 
 
 
 
 
113996 static void fts3DoclistPhraseMerge(
113997 int bDescIdx, /* True if arguments are desc */
113998 int nDist, /* Distance from left to right (1=adjacent) */
113999 char *aLeft, int nLeft, /* Left doclist */
114000 char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
114001 ){
114002 sqlite3_int64 i1 = 0;
@@ -114015,30 +114496,30 @@
114015 p = aOut;
114016 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
114017 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
114018
114019 while( p1 && p2 ){
114020 sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
114021 if( iDiff==0 ){
114022 char *pSave = p;
114023 sqlite3_int64 iPrevSave = iPrev;
114024 int bFirstOutSave = bFirstOut;
114025
114026 fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
114027 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
114028 p = pSave;
114029 iPrev = iPrevSave;
114030 bFirstOut = bFirstOutSave;
114031 }
114032 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
114033 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
114034 }else if( iDiff<0 ){
114035 fts3PoslistCopy(0, &p1);
114036 fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
114037 }else{
114038 fts3PoslistCopy(0, &p2);
114039 fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
114040 }
114041 }
114042
114043 *pnRight = p - aOut;
114044 }
@@ -114051,11 +114532,11 @@
114051 **
114052 ** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
114053 ** the responsibility of the caller to free any doclists left in the
114054 ** TermSelect.aaOutput[] array.
114055 */
114056 static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
114057 char *aOut = 0;
114058 int nOut = 0;
114059 int i;
114060
114061 /* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -114092,28 +114573,29 @@
114092 pTS->anOutput[0] = nOut;
114093 return SQLITE_OK;
114094 }
114095
114096 /*
114097 ** This function is used as the sqlite3Fts3SegReaderIterate() callback when
114098 ** querying the full-text index for a doclist associated with a term or
114099 ** term-prefix.
 
 
 
 
 
 
 
 
 
114100 */
114101 static int fts3TermSelectCb(
114102 Fts3Table *p, /* Virtual table object */
114103 void *pContext, /* Pointer to TermSelect structure */
114104 char *zTerm,
114105 int nTerm,
114106 char *aDoclist,
114107 int nDoclist
114108 ){
114109 TermSelect *pTS = (TermSelect *)pContext;
114110
114111 UNUSED_PARAMETER(p);
114112 UNUSED_PARAMETER(zTerm);
114113 UNUSED_PARAMETER(nTerm);
114114
114115 if( pTS->aaOutput[0]==0 ){
114116 /* If this is the first term selected, copy the doclist to the output
114117 ** buffer using memcpy(). */
114118 pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
114119 pTS->anOutput[0] = nDoclist;
@@ -114180,23 +114662,30 @@
114180 }
114181 pCsr->apSegment[pCsr->nSegment++] = pNew;
114182 return SQLITE_OK;
114183 }
114184
 
 
 
 
 
 
 
114185 static int fts3SegReaderCursor(
114186 Fts3Table *p, /* FTS3 table handle */
114187 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114188 int iLevel, /* Level of segments to scan */
114189 const char *zTerm, /* Term to query for */
114190 int nTerm, /* Size of zTerm in bytes */
114191 int isPrefix, /* True for a prefix search */
114192 int isScan, /* True to scan from zTerm to EOF */
114193 Fts3MultiSegReader *pCsr /* Cursor object to populate */
114194 ){
114195 int rc = SQLITE_OK;
114196 int rc2;
114197 sqlite3_stmt *pStmt = 0;
114198
114199 /* If iLevel is less than 0 and this is not a scan, include a seg-reader
114200 ** for the pending-terms. If this is a scan, then this call must be being
114201 ** made by an fts4aux module, not an FTS table. In this case calling
114202 ** Fts3SegReaderPending might segfault, as the data structures used by
@@ -114281,28 +114770,46 @@
114281 return fts3SegReaderCursor(
114282 p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
114283 );
114284 }
114285
 
 
 
 
 
 
114286 static int fts3SegReaderCursorAddZero(
114287 Fts3Table *p,
114288 const char *zTerm,
114289 int nTerm,
114290 Fts3MultiSegReader *pCsr
114291 ){
114292 return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
114293 }
114294
114295
114296 SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
 
 
 
 
 
 
 
 
 
 
 
 
114297 Fts3Cursor *pCsr, /* Virtual table cursor handle */
114298 const char *zTerm, /* Term to query for */
114299 int nTerm, /* Size of zTerm in bytes */
114300 int isPrefix, /* True for a prefix search */
114301 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
114302 ){
114303 Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114304 int rc = SQLITE_NOMEM; /* Return code */
114305
114306 pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
114307 if( pSegcsr ){
114308 int i;
@@ -114342,62 +114849,53 @@
114342
114343 *ppSegcsr = pSegcsr;
114344 return rc;
114345 }
114346
 
 
 
114347 static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
114348 sqlite3Fts3SegReaderFinish(pSegcsr);
114349 sqlite3_free(pSegcsr);
114350 }
114351
114352 /*
114353 ** This function retreives the doclist for the specified term (or term
114354 ** prefix) from the database.
114355 **
114356 ** The returned doclist may be in one of two formats, depending on the
114357 ** value of parameter isReqPos. If isReqPos is zero, then the doclist is
114358 ** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
114359 ** is non-zero, then the returned list is in the same format as is stored
114360 ** in the database without the found length specifier at the start of on-disk
114361 ** doclists.
114362 */
114363 static int fts3TermSelect(
114364 Fts3Table *p, /* Virtual table handle */
114365 Fts3PhraseToken *pTok, /* Token to query for */
114366 int iColumn, /* Column to query (or -ve for all columns) */
114367 int isReqPos, /* True to include position lists in output */
114368 int *pnOut, /* OUT: Size of buffer at *ppOut */
114369 char **ppOut /* OUT: Malloced result buffer */
114370 ){
114371 int rc; /* Return code */
114372 Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114373 TermSelect tsc; /* Context object for fts3TermSelectCb() */
114374 Fts3SegFilter filter; /* Segment term filter configuration */
114375
114376 pSegcsr = pTok->pSegcsr;
114377 memset(&tsc, 0, sizeof(TermSelect));
114378 tsc.isReqPos = isReqPos;
114379
114380 filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
114381 | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
114382 | (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
114383 | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
114384 filter.iCol = iColumn;
114385 filter.zTerm = pTok->z;
114386 filter.nTerm = pTok->n;
114387
114388 rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
114389 while( SQLITE_OK==rc
114390 && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
114391 ){
114392 rc = fts3TermSelectCb(p, (void *)&tsc,
114393 pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
114394 );
114395 }
114396
114397 if( rc==SQLITE_OK ){
114398 rc = fts3TermSelectMerge(p, &tsc);
114399 }
114400 if( rc==SQLITE_OK ){
114401 *ppOut = tsc.aaOutput[0];
114402 *pnOut = tsc.anOutput[0];
114403 }else{
@@ -114419,28 +114917,19 @@
114419 ** If the isPoslist argument is true, then it is assumed that the doclist
114420 ** contains a position-list following each docid. Otherwise, it is assumed
114421 ** that the doclist is simply a list of docids stored as delta encoded
114422 ** varints.
114423 */
114424 static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
114425 int nDoc = 0; /* Return value */
114426 if( aList ){
114427 char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
114428 char *p = aList; /* Cursor */
114429 if( !isPoslist ){
114430 /* The number of docids in the list is the same as the number of
114431 ** varints. In FTS3 a varint consists of a single byte with the 0x80
114432 ** bit cleared and zero or more bytes with the 0x80 bit set. So to
114433 ** count the varints in the buffer, just count the number of bytes
114434 ** with the 0x80 bit clear. */
114435 while( p<aEnd ) nDoc += (((*p++)&0x80)==0);
114436 }else{
114437 while( p<aEnd ){
114438 nDoc++;
114439 while( (*p++)&0x80 ); /* Skip docid varint */
114440 fts3PoslistCopy(0, &p); /* Skip over position list */
114441 }
114442 }
114443 }
114444
114445 return nDoc;
114446 }
@@ -114466,11 +114955,11 @@
114466 }else{
114467 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114468 rc = SQLITE_OK;
114469 }
114470 }else{
114471 rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
114472 }
114473 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
114474 return rc;
114475 }
114476
@@ -114543,11 +115032,11 @@
114543 }
114544
114545 rc = sqlite3Fts3ReadLock(p);
114546 if( rc!=SQLITE_OK ) return rc;
114547
114548 rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
114549
114550 sqlite3Fts3SegmentsClose(p);
114551 if( rc!=SQLITE_OK ) return rc;
114552 pCsr->pNextId = pCsr->aDoclist;
114553 pCsr->iPrevId = 0;
@@ -114950,26 +115439,43 @@
114950 p->zDb, p->zName, zName
114951 );
114952 return rc;
114953 }
114954
 
 
 
 
 
114955 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
114956 UNUSED_PARAMETER(iSavepoint);
114957 assert( ((Fts3Table *)pVtab)->inTransaction );
114958 assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
114959 TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
114960 return fts3SyncMethod(pVtab);
114961 }
 
 
 
 
 
 
114962 static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
114963 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
114964 UNUSED_PARAMETER(iSavepoint);
114965 UNUSED_PARAMETER(pVtab);
114966 assert( p->inTransaction );
114967 assert( p->mxSavepoint >= iSavepoint );
114968 TESTONLY( p->mxSavepoint = iSavepoint-1 );
114969 return SQLITE_OK;
114970 }
 
 
 
 
 
 
114971 static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
114972 Fts3Table *p = (Fts3Table*)pVtab;
114973 UNUSED_PARAMETER(iSavepoint);
114974 assert( p->inTransaction );
114975 assert( p->mxSavepoint >= iSavepoint );
@@ -115114,22 +115620,10 @@
115114 sqlite3Fts3HashClear(pHash);
115115 sqlite3_free(pHash);
115116 }
115117 return rc;
115118 }
115119
115120 #if !SQLITE_CORE
115121 SQLITE_API int sqlite3_extension_init(
115122 sqlite3 *db,
115123 char **pzErrMsg,
115124 const sqlite3_api_routines *pApi
115125 ){
115126 SQLITE_EXTENSION_INIT2(pApi)
115127 return sqlite3Fts3Init(db);
115128 }
115129 #endif
115130
115131
115132 /*
115133 ** Allocate an Fts3MultiSegReader for each token in the expression headed
115134 ** by pExpr.
115135 **
@@ -115143,24 +115637,24 @@
115143 ** there exists prefix b-tree of the right length) then it may be traversed
115144 ** and merged incrementally. Otherwise, it has to be merged into an in-memory
115145 ** doclist and then traversed.
115146 */
115147 static void fts3EvalAllocateReaders(
115148 Fts3Cursor *pCsr,
115149 Fts3Expr *pExpr,
115150 int *pnToken, /* OUT: Total number of tokens in phrase. */
115151 int *pnOr, /* OUT: Total number of OR nodes in expr. */
115152 int *pRc
115153 ){
115154 if( pExpr && SQLITE_OK==*pRc ){
115155 if( pExpr->eType==FTSQUERY_PHRASE ){
115156 int i;
115157 int nToken = pExpr->pPhrase->nToken;
115158 *pnToken += nToken;
115159 for(i=0; i<nToken; i++){
115160 Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
115161 int rc = sqlite3Fts3TermSegReaderCursor(pCsr,
115162 pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115163 );
115164 if( rc!=SQLITE_OK ){
115165 *pRc = rc;
115166 return;
@@ -115174,16 +115668,24 @@
115174 fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
115175 }
115176 }
115177 }
115178
 
 
 
 
 
 
 
 
115179 static void fts3EvalPhraseMergeToken(
115180 Fts3Table *pTab,
115181 Fts3Phrase *p,
115182 int iToken,
115183 char *pList,
115184 int nList
115185 ){
115186 assert( iToken!=p->iDoclistToken );
115187
115188 if( pList==0 ){
115189 sqlite3_free(p->doclist.aAll);
@@ -115228,13 +115730,19 @@
115228 }
115229
115230 if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
115231 }
115232
 
 
 
 
 
 
115233 static int fts3EvalPhraseLoad(
115234 Fts3Cursor *pCsr,
115235 Fts3Phrase *p
115236 ){
115237 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115238 int iToken;
115239 int rc = SQLITE_OK;
115240
@@ -115243,11 +115751,11 @@
115243 assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
115244
115245 if( pToken->pSegcsr ){
115246 int nThis = 0;
115247 char *pThis = 0;
115248 rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
115249 if( rc==SQLITE_OK ){
115250 fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
115251 }
115252 }
115253 assert( pToken->pSegcsr==0 );
@@ -115254,18 +115762,26 @@
115254 }
115255
115256 return rc;
115257 }
115258
 
 
 
 
 
 
 
 
 
 
115259 static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
115260 int iToken;
115261 int rc = SQLITE_OK;
115262
115263 int nMaxUndeferred = pPhrase->iDoclistToken;
115264 char *aPoslist = 0;
115265 int nPoslist = 0;
115266 int iPrev = -1;
115267
115268 assert( pPhrase->doclist.bFreeList==0 );
115269
115270 for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
115271 Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -115307,10 +115823,11 @@
115307 iPrev = iToken;
115308 }
115309 }
115310
115311 if( iPrev>=0 ){
 
115312 if( nMaxUndeferred<0 ){
115313 pPhrase->doclist.pList = aPoslist;
115314 pPhrase->doclist.nList = nPoslist;
115315 pPhrase->doclist.iDocid = pCsr->iPrevId;
115316 pPhrase->doclist.bFreeList = 1;
@@ -115355,13 +115872,19 @@
115355 /*
115356 ** This function is called for each Fts3Phrase in a full-text query
115357 ** expression to initialize the mechanism for returning rows. Once this
115358 ** function has been called successfully on an Fts3Phrase, it may be
115359 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
 
 
 
 
 
 
115360 */
115361 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
115362 int rc;
115363 Fts3PhraseToken *pFirst = &p->aToken[0];
115364 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115365
115366 if( pCsr->bDesc==pTab->bDescIdx
115367 && bOptOk==1
@@ -115385,11 +115908,17 @@
115385 return rc;
115386 }
115387
115388 /*
115389 ** This function is used to iterate backwards (from the end to start)
115390 ** through doclists.
 
 
 
 
 
 
115391 */
115392 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
115393 int bDescIdx, /* True if the doclist is desc */
115394 char *aDoclist, /* Pointer to entire doclist */
115395 int nDoclist, /* Length of aDoclist in bytes */
@@ -115450,13 +115979,13 @@
115450 ** If there is no "next" entry and no error occurs, then *pbEof is set to
115451 ** 1 before returning. Otherwise, if no error occurs and the iterator is
115452 ** successfully advanced, *pbEof is set to 0.
115453 */
115454 static int fts3EvalPhraseNext(
115455 Fts3Cursor *pCsr,
115456 Fts3Phrase *p,
115457 u8 *pbEof
115458 ){
115459 int rc = SQLITE_OK;
115460 Fts3Doclist *pDL = &p->doclist;
115461 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115462
@@ -115498,14 +116027,14 @@
115498 fts3PoslistCopy(0, &pIter);
115499 pDL->nList = (pIter - pDL->pList);
115500
115501 /* pIter now points just past the 0x00 that terminates the position-
115502 ** list for document pDL->iDocid. However, if this position-list was
115503 ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
115504 ** point to the start of the next docid value. The following line deals
115505 ** with this case by advancing pIter past the zero-padding added by
115506 ** fts3EvalNearTrim2(). */
115507 while( pIter<pEnd && *pIter==0 ) pIter++;
115508
115509 pDL->pNextDocid = pIter;
115510 assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
115511 *pbEof = 0;
@@ -115513,15 +116042,31 @@
115513 }
115514
115515 return rc;
115516 }
115517
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115518 static void fts3EvalStartReaders(
115519 Fts3Cursor *pCsr,
115520 Fts3Expr *pExpr,
115521 int bOptOk,
115522 int *pRc
115523 ){
115524 if( pExpr && SQLITE_OK==*pRc ){
115525 if( pExpr->eType==FTSQUERY_PHRASE ){
115526 int i;
115527 int nToken = pExpr->pPhrase->nToken;
@@ -115536,27 +116081,46 @@
115536 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
115537 }
115538 }
115539 }
115540
 
 
 
 
 
 
 
 
 
 
 
 
115541 typedef struct Fts3TokenAndCost Fts3TokenAndCost;
115542 struct Fts3TokenAndCost {
115543 Fts3Phrase *pPhrase; /* The phrase the token belongs to */
115544 int iToken; /* Position of token in phrase */
115545 Fts3PhraseToken *pToken; /* The token itself */
115546 Fts3Expr *pRoot;
115547 int nOvfl;
115548 int iCol; /* The column the token must match */
115549 };
115550
 
 
 
 
 
 
 
115551 static void fts3EvalTokenCosts(
115552 Fts3Cursor *pCsr,
115553 Fts3Expr *pRoot,
115554 Fts3Expr *pExpr,
115555 Fts3TokenAndCost **ppTC,
115556 Fts3Expr ***ppOr,
115557 int *pRc
115558 ){
115559 if( *pRc==SQLITE_OK && pExpr ){
115560 if( pExpr->eType==FTSQUERY_PHRASE ){
115561 Fts3Phrase *pPhrase = pExpr->pPhrase;
115562 int i;
@@ -115584,23 +116148,34 @@
115584 fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
115585 }
115586 }
115587 }
115588
 
 
 
 
 
 
 
 
 
 
 
115589 static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
115590 if( pCsr->nRowAvg==0 ){
115591 /* The average document size, which is required to calculate the cost
115592 ** of each doclist, has not yet been determined. Read the required
115593 ** data from the %_stat table to calculate it.
115594 **
115595 ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
115596 ** varints, where nCol is the number of columns in the FTS3 table.
115597 ** The first varint is the number of documents currently stored in
115598 ** the table. The following nCol varints contain the total amount of
115599 ** data stored in all rows of each column of the table, from left
115600 ** to right.
115601 */
115602 int rc;
115603 Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
115604 sqlite3_stmt *pStmt;
115605 sqlite3_int64 nDoc = 0;
115606 sqlite3_int64 nByte = 0;
@@ -115631,109 +116206,151 @@
115631
115632 *pnPage = pCsr->nRowAvg;
115633 return SQLITE_OK;
115634 }
115635
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115636 static int fts3EvalSelectDeferred(
115637 Fts3Cursor *pCsr,
115638 Fts3Expr *pRoot,
115639 Fts3TokenAndCost *aTC,
115640 int nTC
115641 ){
115642 int nDocSize = 0;
115643 int nDocEst = 0;
115644 int rc = SQLITE_OK;
115645 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115646 int ii;
 
 
 
 
115647
115648 int nOvfl = 0;
115649 int nTerm = 0;
115650
 
 
 
115651 for(ii=0; ii<nTC; ii++){
115652 if( aTC[ii].pRoot==pRoot ){
115653 nOvfl += aTC[ii].nOvfl;
115654 nTerm++;
115655 }
115656 }
115657 if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
115658
 
115659 rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
115660
115661 for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
115662 int jj;
115663 Fts3TokenAndCost *pTC = 0;
115664
115665 for(jj=0; jj<nTC; jj++){
115666 if( aTC[jj].pToken && aTC[jj].pRoot==pRoot
115667 && (!pTC || aTC[jj].nOvfl<pTC->nOvfl)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115668 ){
115669 pTC = &aTC[jj];
115670 }
115671 }
115672 assert( pTC );
115673
115674 /* At this point pTC points to the cheapest remaining token. */
115675 if( ii==0 ){
115676 if( pTC->nOvfl ){
115677 nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
115678 }else{
 
 
 
 
 
 
 
 
 
 
115679 Fts3PhraseToken *pToken = pTC->pToken;
115680 int nList = 0;
115681 char *pList = 0;
115682 rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
115683 assert( rc==SQLITE_OK || pList==0 );
115684
115685 if( rc==SQLITE_OK ){
115686 nDocEst = fts3DoclistCountDocids(1, pList, nList);
115687 fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
 
 
 
 
115688 }
115689 }
115690 }else{
115691 if( pTC->nOvfl>=(nDocEst*nDocSize) ){
115692 Fts3PhraseToken *pToken = pTC->pToken;
115693 rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
115694 fts3SegReaderCursorFree(pToken->pSegcsr);
115695 pToken->pSegcsr = 0;
115696 }
115697 nDocEst = 1 + (nDocEst/4);
115698 }
115699 pTC->pToken = 0;
115700 }
115701
115702 return rc;
115703 }
115704
115705 SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
 
 
 
 
 
 
 
 
 
 
 
 
115706 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115707 int rc = SQLITE_OK;
115708 int nToken = 0;
115709 int nOr = 0;
115710
115711 /* Allocate a MultiSegReader for each token in the expression. */
115712 fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
115713
115714 /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
115715 ** This call will eventually also be responsible for determining which
115716 ** tokens are 'deferred' until the document text is loaded into memory.
115717 **
115718 ** Each token in each phrase is dealt with using one of the following
115719 ** three strategies:
115720 **
115721 ** 1. Entire doclist loaded into memory as part of the
115722 ** fts3EvalStartReaders() call.
115723 **
115724 ** 2. Doclist loaded into memory incrementally, as part of each
115725 ** sqlite3Fts3EvalNext() call.
115726 **
115727 ** 3. Token doclist is never loaded. Instead, documents are loaded into
115728 ** memory and scanned for the token as part of the sqlite3Fts3EvalNext()
115729 ** call. This is known as a "deferred" token.
115730 */
115731
115732 /* If bOptOk is true, check if there are any tokens that should be deferred.
115733 */
115734 if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
115735 Fts3TokenAndCost *aTC;
115736 Fts3Expr **apOr;
115737 aTC = (Fts3TokenAndCost *)sqlite3_malloc(
115738 sizeof(Fts3TokenAndCost) * nToken
115739 + sizeof(Fts3Expr *) * nOr * 2
@@ -115745,11 +116362,11 @@
115745 }else{
115746 int ii;
115747 Fts3TokenAndCost *pTC = aTC;
115748 Fts3Expr **ppOr = apOr;
115749
115750 fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
115751 nToken = pTC-aTC;
115752 nOr = ppOr-apOr;
115753
115754 if( rc==SQLITE_OK ){
115755 rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
@@ -115760,25 +116377,50 @@
115760
115761 sqlite3_free(aTC);
115762 }
115763 }
115764
115765 fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
115766 return rc;
115767 }
115768
115769 static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
 
 
 
115770 if( pPhrase->doclist.bFreeList ){
115771 sqlite3_free(pPhrase->doclist.pList);
115772 }
115773 pPhrase->doclist.pList = 0;
115774 pPhrase->doclist.nList = 0;
115775 pPhrase->doclist.bFreeList = 0;
115776 }
115777
115778 static int fts3EvalNearTrim2(
115779 int nNear,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115780 char *aTmp, /* Temporary space to use */
115781 char **paPoslist, /* IN/OUT: Position list */
115782 int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
115783 Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
115784 ){
@@ -115806,10 +116448,176 @@
115806 }
115807
115808 return res;
115809 }
115810
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115811 static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
115812 int res = 1;
115813
115814 /* The following block runs if pExpr is the root of a NEAR query.
115815 ** For example, the query:
@@ -115827,11 +116635,11 @@
115827 ** | |
115828 ** "w" "x"
115829 **
115830 ** The right-hand child of a NEAR node is always a phrase. The
115831 ** left-hand child may be either a phrase or a NEAR node. There are
115832 ** no exceptions to this.
115833 */
115834 if( *pRc==SQLITE_OK
115835 && pExpr->eType==FTSQUERY_NEAR
115836 && pExpr->bEof==0
115837 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
@@ -115854,21 +116662,21 @@
115854 int nToken = p->pPhrase->nToken;
115855
115856 for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
115857 Fts3Phrase *pPhrase = p->pRight->pPhrase;
115858 int nNear = p->nNear;
115859 res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115860 }
115861
115862 aPoslist = pExpr->pRight->pPhrase->doclist.pList;
115863 nToken = pExpr->pRight->pPhrase->nToken;
115864 for(p=pExpr->pLeft; p && res; p=p->pLeft){
115865 int nNear = p->pParent->nNear;
115866 Fts3Phrase *pPhrase = (
115867 p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
115868 );
115869 res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
115870 }
115871 }
115872
115873 sqlite3_free(aTmp);
115874 }
@@ -115875,132 +116683,33 @@
115875
115876 return res;
115877 }
115878
115879 /*
115880 ** This macro is used by the fts3EvalNext() function. The two arguments are
115881 ** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
115882 ** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
115883 ** it returns (i2 - i1). This allows the same code to be used for merging
115884 ** doclists in ascending or descending order.
 
 
 
 
115885 */
115886 #define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
115887
115888 static void fts3EvalNext(
115889 Fts3Cursor *pCsr,
115890 Fts3Expr *pExpr,
115891 int *pRc
115892 ){
115893 if( *pRc==SQLITE_OK ){
115894 assert( pExpr->bEof==0 );
115895 pExpr->bStart = 1;
115896
115897 switch( pExpr->eType ){
115898 case FTSQUERY_NEAR:
115899 case FTSQUERY_AND: {
115900 Fts3Expr *pLeft = pExpr->pLeft;
115901 Fts3Expr *pRight = pExpr->pRight;
115902 assert( !pLeft->bDeferred || !pRight->bDeferred );
115903 if( pLeft->bDeferred ){
115904 fts3EvalNext(pCsr, pRight, pRc);
115905 pExpr->iDocid = pRight->iDocid;
115906 pExpr->bEof = pRight->bEof;
115907 }else if( pRight->bDeferred ){
115908 fts3EvalNext(pCsr, pLeft, pRc);
115909 pExpr->iDocid = pLeft->iDocid;
115910 pExpr->bEof = pLeft->bEof;
115911 }else{
115912 fts3EvalNext(pCsr, pLeft, pRc);
115913 fts3EvalNext(pCsr, pRight, pRc);
115914
115915 while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
115916 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115917 if( iDiff==0 ) break;
115918 if( iDiff<0 ){
115919 fts3EvalNext(pCsr, pLeft, pRc);
115920 }else{
115921 fts3EvalNext(pCsr, pRight, pRc);
115922 }
115923 }
115924
115925 pExpr->iDocid = pLeft->iDocid;
115926 pExpr->bEof = (pLeft->bEof || pRight->bEof);
115927 }
115928 break;
115929 }
115930
115931 case FTSQUERY_OR: {
115932 Fts3Expr *pLeft = pExpr->pLeft;
115933 Fts3Expr *pRight = pExpr->pRight;
115934 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115935
115936 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
115937 assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
115938
115939 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115940 fts3EvalNext(pCsr, pLeft, pRc);
115941 }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
115942 fts3EvalNext(pCsr, pRight, pRc);
115943 }else{
115944 fts3EvalNext(pCsr, pLeft, pRc);
115945 fts3EvalNext(pCsr, pRight, pRc);
115946 }
115947
115948 pExpr->bEof = (pLeft->bEof && pRight->bEof);
115949 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
115950 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
115951 pExpr->iDocid = pLeft->iDocid;
115952 }else{
115953 pExpr->iDocid = pRight->iDocid;
115954 }
115955
115956 break;
115957 }
115958
115959 case FTSQUERY_NOT: {
115960 Fts3Expr *pLeft = pExpr->pLeft;
115961 Fts3Expr *pRight = pExpr->pRight;
115962
115963 if( pRight->bStart==0 ){
115964 fts3EvalNext(pCsr, pRight, pRc);
115965 assert( *pRc!=SQLITE_OK || pRight->bStart );
115966 }
115967
115968 fts3EvalNext(pCsr, pLeft, pRc);
115969 if( pLeft->bEof==0 ){
115970 while( !*pRc
115971 && !pRight->bEof
115972 && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
115973 ){
115974 fts3EvalNext(pCsr, pRight, pRc);
115975 }
115976 }
115977 pExpr->iDocid = pLeft->iDocid;
115978 pExpr->bEof = pLeft->bEof;
115979 break;
115980 }
115981
115982 default: {
115983 Fts3Phrase *pPhrase = pExpr->pPhrase;
115984 fts3EvalZeroPoslist(pPhrase);
115985 *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
115986 pExpr->iDocid = pPhrase->doclist.iDocid;
115987 break;
115988 }
115989 }
115990 }
115991 }
115992
115993 static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
115994 int bHit = 1;
115995 if( *pRc==SQLITE_OK ){
115996 switch( pExpr->eType ){
115997 case FTSQUERY_NEAR:
115998 case FTSQUERY_AND:
115999 bHit = (
116000 fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
116001 && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
116002 && fts3EvalNearTest(pExpr, pRc)
116003 );
116004
116005 /* If the NEAR expression does not match any rows, zero the doclist for
116006 ** all phrases involved in the NEAR. This is because the snippet(),
@@ -116022,31 +116731,31 @@
116022 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
116023 ){
116024 Fts3Expr *p;
116025 for(p=pExpr; p->pPhrase==0; p=p->pLeft){
116026 if( p->pRight->iDocid==pCsr->iPrevId ){
116027 fts3EvalZeroPoslist(p->pRight->pPhrase);
116028 }
116029 }
116030 if( p->iDocid==pCsr->iPrevId ){
116031 fts3EvalZeroPoslist(p->pPhrase);
116032 }
116033 }
116034
116035 break;
116036
116037 case FTSQUERY_OR: {
116038 int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
116039 int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
116040 bHit = bHit1 || bHit2;
116041 break;
116042 }
116043
116044 case FTSQUERY_NOT:
116045 bHit = (
116046 fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
116047 && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
116048 );
116049 break;
116050
116051 default: {
116052 if( pCsr->pDeferred
@@ -116053,11 +116762,11 @@
116053 && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
116054 ){
116055 Fts3Phrase *pPhrase = pExpr->pPhrase;
116056 assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
116057 if( pExpr->bDeferred ){
116058 fts3EvalZeroPoslist(pPhrase);
116059 }
116060 *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
116061 bHit = (pPhrase->doclist.pList!=0);
116062 pExpr->iDocid = pCsr->iPrevId;
116063 }else{
@@ -116069,31 +116778,53 @@
116069 }
116070 return bHit;
116071 }
116072
116073 /*
116074 ** Return 1 if both of the following are true:
 
 
 
 
 
 
 
 
 
 
 
 
 
116075 **
116076 ** 1. *pRc is SQLITE_OK when this function returns, and
116077 **
116078 ** 2. After scanning the current FTS table row for the deferred tokens,
116079 ** it is determined that the row does not match the query.
116080 **
116081 ** Or, if no error occurs and it seems the current row does match the FTS
116082 ** query, return 0.
116083 */
116084 static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
116085 int rc = *pRc;
116086 int bMiss = 0;
116087 if( rc==SQLITE_OK ){
 
 
 
 
 
 
 
116088 if( pCsr->pDeferred ){
116089 rc = fts3CursorSeek(0, pCsr);
116090 if( rc==SQLITE_OK ){
116091 rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
116092 }
116093 }
116094 bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
 
 
116095 sqlite3Fts3FreeDeferredDoclists(pCsr);
116096 *pRc = rc;
116097 }
116098 return (rc==SQLITE_OK && bMiss);
116099 }
@@ -116100,11 +116831,11 @@
116100
116101 /*
116102 ** Advance to the next document that matches the FTS expression in
116103 ** Fts3Cursor.pExpr.
116104 */
116105 SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
116106 int rc = SQLITE_OK; /* Return Code */
116107 Fts3Expr *pExpr = pCsr->pExpr;
116108 assert( pCsr->isEof==0 );
116109 if( pExpr==0 ){
116110 pCsr->isEof = 1;
@@ -116112,23 +116843,23 @@
116112 do {
116113 if( pCsr->isRequireSeek==0 ){
116114 sqlite3_reset(pCsr->pStmt);
116115 }
116116 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116117 fts3EvalNext(pCsr, pExpr, &rc);
116118 pCsr->isEof = pExpr->bEof;
116119 pCsr->isRequireSeek = 1;
116120 pCsr->isMatchinfoNeeded = 1;
116121 pCsr->iPrevId = pExpr->iDocid;
116122 }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
116123 }
116124 return rc;
116125 }
116126
116127 /*
116128 ** Restart interation for expression pExpr so that the next call to
116129 ** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental
116130 ** loading or merging of phrase doclists for this iteration.
116131 **
116132 ** If *pRc is other than SQLITE_OK when this function is called, it is
116133 ** a no-op. If an error occurs within this function, *pRc is set to an
116134 ** SQLite error code before returning.
@@ -116140,11 +116871,11 @@
116140 ){
116141 if( pExpr && *pRc==SQLITE_OK ){
116142 Fts3Phrase *pPhrase = pExpr->pPhrase;
116143
116144 if( pPhrase ){
116145 fts3EvalZeroPoslist(pPhrase);
116146 if( pPhrase->bIncr ){
116147 assert( pPhrase->nToken==1 );
116148 assert( pPhrase->aToken[0].pSegcsr );
116149 sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
116150 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
@@ -116256,18 +116987,18 @@
116256 /* Ensure the %_content statement is reset. */
116257 if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
116258 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116259
116260 /* Advance to the next document */
116261 fts3EvalNext(pCsr, pRoot, &rc);
116262 pCsr->isEof = pRoot->bEof;
116263 pCsr->isRequireSeek = 1;
116264 pCsr->isMatchinfoNeeded = 1;
116265 pCsr->iPrevId = pRoot->iDocid;
116266 }while( pCsr->isEof==0
116267 && pRoot->eType==FTSQUERY_NEAR
116268 && fts3EvalLoadDeferred(pCsr, &rc)
116269 );
116270
116271 if( rc==SQLITE_OK && pCsr->isEof==0 ){
116272 fts3EvalUpdateCounts(pRoot);
116273 }
@@ -116285,14 +117016,14 @@
116285 **
116286 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
116287 */
116288 fts3EvalRestart(pCsr, pRoot, &rc);
116289 do {
116290 fts3EvalNext(pCsr, pRoot, &rc);
116291 assert( pRoot->bEof==0 );
116292 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
116293 fts3EvalLoadDeferred(pCsr, &rc);
116294 }
116295 }
116296 return rc;
116297 }
116298
@@ -116419,18 +117150,32 @@
116419 */
116420 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
116421 if( pPhrase ){
116422 int i;
116423 sqlite3_free(pPhrase->doclist.aAll);
116424 fts3EvalZeroPoslist(pPhrase);
116425 memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
116426 for(i=0; i<pPhrase->nToken; i++){
116427 fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
116428 pPhrase->aToken[i].pSegcsr = 0;
116429 }
116430 }
116431 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116432
116433 #endif
116434
116435 /************** End of fts3.c ************************************************/
116436 /************** Begin file fts3_aux.c ****************************************/
@@ -118917,14 +119662,10 @@
118917 ** (in which case SQLITE_CORE is not defined), or
118918 **
118919 ** * The FTS3 module is being built into the core of
118920 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
118921 */
118922 #ifndef SQLITE_CORE
118923 SQLITE_EXTENSION_INIT1
118924 #endif
118925
118926 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
118927
118928
118929 /*
118930 ** Implementation of the SQL scalar function for accessing the underlying
118931
--- 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.
@@ -648,13 +648,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.8"
654 #define SQLITE_VERSION_NUMBER 3007008
655 #define SQLITE_SOURCE_ID "2011-07-19 18:29:00 ed5f0aad6b21066bacd01521e82c22e96991f400"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -1282,20 +1282,37 @@
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 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
1289 ** retry counts and intervals for certain disk I/O operations for the
1290 ** windows [VFS] in order to work to provide robustness against
1291 ** anti-virus programs. By default, the windows VFS will retry file read,
1292 ** file write, and file delete opertions up to 10 times, with a delay
1293 ** of 25 milliseconds before the first retry and with the delay increasing
1294 ** by an additional 25 milliseconds with each subsequent retry. This
1295 ** opcode allows those to values (10 retries and 25 milliseconds of delay)
1296 ** to be adjusted. The values are changed for all database connections
1297 ** within the same process. The argument is a pointer to an array of two
1298 ** integers where the first integer i the new retry count and the second
1299 ** integer is the delay. If either integer is negative, then the setting
1300 ** is not changed but instead the prior value of that setting is written
1301 ** into the array entry, allowing the current retry settings to be
1302 ** interrogated. The zDbName parameter is ignored.
1303 **
1304 */
1305 #define SQLITE_FCNTL_LOCKSTATE 1
1306 #define SQLITE_GET_LOCKPROXYFILE 2
1307 #define SQLITE_SET_LOCKPROXYFILE 3
1308 #define SQLITE_LAST_ERRNO 4
1309 #define SQLITE_FCNTL_SIZE_HINT 5
1310 #define SQLITE_FCNTL_CHUNK_SIZE 6
1311 #define SQLITE_FCNTL_FILE_POINTER 7
1312 #define SQLITE_FCNTL_SYNC_OMITTED 8
1313 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
1314
1315 /*
1316 ** CAPI3REF: Mutex Handle
1317 **
1318 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -9558,10 +9575,11 @@
9575 #define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
9576 #define SQLITE_IndexCover 0x10 /* Disable index covering table */
9577 #define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
9578 #define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
9579 #define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */
9580 #define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */
9581 #define SQLITE_OptMask 0xff /* Mask of all disablable opts */
9582
9583 /*
9584 ** Possible values for the sqlite.magic field.
9585 ** The numbers are obtained at random and have no special meaning, other
@@ -10449,10 +10467,11 @@
10467 Table *pTab; /* An SQL table corresponding to zName */
10468 Select *pSelect; /* A SELECT statement used in place of a table name */
10469 u8 isPopulated; /* Temporary table associated with SELECT is populated */
10470 u8 jointype; /* Type of join between this able and the previous */
10471 u8 notIndexed; /* True if there is a NOT INDEXED clause */
10472 u8 isCorrelated; /* True if sub-query is correlated */
10473 #ifndef SQLITE_OMIT_EXPLAIN
10474 u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
10475 #endif
10476 int iCursor; /* The VDBE cursor number used to access this table */
10477 Expr *pOn; /* The ON clause of a join */
@@ -10568,10 +10587,11 @@
10587 struct WhereInfo {
10588 Parse *pParse; /* Parsing and code generating context */
10589 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
10590 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
10591 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
10592 u8 eDistinct;
10593 SrcList *pTabList; /* List of tables in the join */
10594 int iTop; /* The very beginning of the WHERE loop */
10595 int iContinue; /* Jump here to continue with next record */
10596 int iBreak; /* Jump here to break out of the loop */
10597 int nLevel; /* Number of nested loop */
@@ -10579,10 +10599,13 @@
10599 double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
10600 double nRowOut; /* Estimated number of output rows */
10601 WhereLevel a[1]; /* Information about each nest loop in WHERE */
10602 };
10603
10604 #define WHERE_DISTINCT_UNIQUE 1
10605 #define WHERE_DISTINCT_ORDERED 2
10606
10607 /*
10608 ** A NameContext defines a context in which to resolve table and column
10609 ** names. The context consists of a list of tables (the pSrcList) field and
10610 ** a list of named expression (pEList). The named expression list may
10611 ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
@@ -11340,11 +11363,11 @@
11363 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
11364 SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
11365 #endif
11366 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
11367 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11368 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
11369 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
11370 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
11371 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
11372 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
11373 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
@@ -15841,11 +15864,11 @@
15864 ** Free an outstanding memory allocation.
15865 **
15866 ** This function assumes that the necessary mutexes, if any, are
15867 ** already held by the caller. Hence "Unsafe".
15868 */
15869 static void memsys3FreeUnsafe(void *pOld){
15870 Mem3Block *p = (Mem3Block*)pOld;
15871 int i;
15872 u32 size, x;
15873 assert( sqlite3_mutex_held(mem3.mutex) );
15874 assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
@@ -15916,21 +15939,21 @@
15939 }
15940
15941 /*
15942 ** Free memory.
15943 */
15944 static void memsys3Free(void *pPrior){
15945 assert( pPrior );
15946 memsys3Enter();
15947 memsys3FreeUnsafe(pPrior);
15948 memsys3Leave();
15949 }
15950
15951 /*
15952 ** Change the size of an existing memory allocation
15953 */
15954 static void *memsys3Realloc(void *pPrior, int nBytes){
15955 int nOld;
15956 void *p;
15957 if( pPrior==0 ){
15958 return sqlite3_malloc(nBytes);
15959 }
@@ -25143,11 +25166,13 @@
25166 case EINVAL:
25167 case ENOTCONN:
25168 case ENODEV:
25169 case ENXIO:
25170 case ENOENT:
25171 #ifdef ESTALE /* ESTALE is not defined on Interix systems */
25172 case ESTALE:
25173 #endif
25174 case ENOSYS:
25175 /* these should force the client to close the file and reconnect */
25176
25177 default:
25178 return sqliteIOErr;
@@ -31820,10 +31845,58 @@
31845 iLine, iErrno, zFunc, zPath, zMsg
31846 );
31847
31848 return errcode;
31849 }
31850
31851 /*
31852 ** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
31853 ** will be retried following a locking error - probably caused by
31854 ** antivirus software. Also the initial delay before the first retry.
31855 ** The delay increases linearly with each retry.
31856 */
31857 #ifndef SQLITE_WIN32_IOERR_RETRY
31858 # define SQLITE_WIN32_IOERR_RETRY 10
31859 #endif
31860 #ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
31861 # define SQLITE_WIN32_IOERR_RETRY_DELAY 25
31862 #endif
31863 static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
31864 static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
31865
31866 /*
31867 ** If a ReadFile() or WriteFile() error occurs, invoke this routine
31868 ** to see if it should be retried. Return TRUE to retry. Return FALSE
31869 ** to give up with an error.
31870 */
31871 static int retryIoerr(int *pnRetry){
31872 DWORD e;
31873 if( *pnRetry>=win32IoerrRetry ){
31874 return 0;
31875 }
31876 e = GetLastError();
31877 if( e==ERROR_ACCESS_DENIED ||
31878 e==ERROR_LOCK_VIOLATION ||
31879 e==ERROR_SHARING_VIOLATION ){
31880 Sleep(win32IoerrRetryDelay*(1+*pnRetry));
31881 ++*pnRetry;
31882 return 1;
31883 }
31884 return 0;
31885 }
31886
31887 /*
31888 ** Log a I/O error retry episode.
31889 */
31890 static void logIoerr(int nRetry){
31891 if( nRetry ){
31892 sqlite3_log(SQLITE_IOERR,
31893 "delayed %dms for lock/sharing conflict",
31894 win32IoerrRetryDelay*nRetry*(nRetry+1)/2
31895 );
31896 }
31897 }
31898
31899 #if SQLITE_OS_WINCE
31900 /*************************************************************************
31901 ** This section contains code for WinCE only.
31902 */
@@ -32238,22 +32311,25 @@
32311 int amt, /* Number of bytes to read */
32312 sqlite3_int64 offset /* Begin reading at this offset */
32313 ){
32314 winFile *pFile = (winFile*)id; /* file handle */
32315 DWORD nRead; /* Number of bytes actually read from file */
32316 int nRetry = 0; /* Number of retrys */
32317
32318 assert( id!=0 );
32319 SimulateIOError(return SQLITE_IOERR_READ);
32320 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
32321
32322 if( seekWinFile(pFile, offset) ){
32323 return SQLITE_FULL;
32324 }
32325 while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
32326 if( retryIoerr(&nRetry) ) continue;
32327 pFile->lastErrno = GetLastError();
32328 return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
32329 }
32330 logIoerr(nRetry);
32331 if( nRead<(DWORD)amt ){
32332 /* Unread parts of the buffer must be zero-filled */
32333 memset(&((char*)pBuf)[nRead], 0, amt-nRead);
32334 return SQLITE_IOERR_SHORT_READ;
32335 }
@@ -32271,10 +32347,11 @@
32347 int amt, /* Number of bytes to write */
32348 sqlite3_int64 offset /* Offset into the file to begin writing at */
32349 ){
32350 int rc; /* True if error has occured, else false */
32351 winFile *pFile = (winFile*)id; /* File handle */
32352 int nRetry = 0; /* Number of retries */
32353
32354 assert( amt>0 );
32355 assert( pFile );
32356 SimulateIOError(return SQLITE_IOERR_WRITE);
32357 SimulateDiskfullError(return SQLITE_FULL);
@@ -32285,11 +32362,16 @@
32362 if( rc==0 ){
32363 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
32364 int nRem = amt; /* Number of bytes yet to be written */
32365 DWORD nWrite; /* Bytes written by each WriteFile() call */
32366
32367 while( nRem>0 ){
32368 if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
32369 if( retryIoerr(&nRetry) ) continue;
32370 break;
32371 }
32372 if( nWrite<=0 ) break;
32373 aRem += nWrite;
32374 nRem -= nWrite;
32375 }
32376 if( nRem>0 ){
32377 pFile->lastErrno = GetLastError();
@@ -32301,10 +32383,12 @@
32383 if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
32384 || ( pFile->lastErrno==ERROR_DISK_FULL )){
32385 return SQLITE_FULL;
32386 }
32387 return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
32388 }else{
32389 logIoerr(nRetry);
32390 }
32391 return SQLITE_OK;
32392 }
32393
32394 /*
@@ -32716,10 +32800,24 @@
32800 SimulateIOErrorBenign(0);
32801 return SQLITE_OK;
32802 }
32803 case SQLITE_FCNTL_SYNC_OMITTED: {
32804 return SQLITE_OK;
32805 }
32806 case SQLITE_FCNTL_WIN32_AV_RETRY: {
32807 int *a = (int*)pArg;
32808 if( a[0]>0 ){
32809 win32IoerrRetry = a[0];
32810 }else{
32811 a[0] = win32IoerrRetry;
32812 }
32813 if( a[1]>0 ){
32814 win32IoerrRetryDelay = a[1];
32815 }else{
32816 a[1] = win32IoerrRetryDelay;
32817 }
32818 return SQLITE_OK;
32819 }
32820 }
32821 return SQLITE_NOTFOUND;
32822 }
32823
@@ -33734,19 +33832,17 @@
33832 ** file open, we will be unable to delete it. To work around this
33833 ** problem, we delay 100 milliseconds and try to delete again. Up
33834 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
33835 ** up and returning an error.
33836 */
 
33837 static int winDelete(
33838 sqlite3_vfs *pVfs, /* Not used on win32 */
33839 const char *zFilename, /* Name of file to delete */
33840 int syncDir /* Not used on win32 */
33841 ){
33842 int cnt = 0;
33843 int rc;
 
33844 void *zConverted;
33845 UNUSED_PARAMETER(pVfs);
33846 UNUSED_PARAMETER(syncDir);
33847
33848 SimulateIOError(return SQLITE_IOERR_DELETE);
@@ -33753,38 +33849,34 @@
33849 zConverted = convertUtf8Filename(zFilename);
33850 if( zConverted==0 ){
33851 return SQLITE_NOMEM;
33852 }
33853 if( isNT() ){
33854 rc = 1;
33855 while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
33856 (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}
33857 rc = rc ? SQLITE_OK : SQLITE_ERROR;
 
 
33858 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
33859 ** Since the ASCII version of these Windows API do not exist for WINCE,
33860 ** it's important to not reference them for WINCE builds.
33861 */
33862 #if SQLITE_OS_WINCE==0
33863 }else{
33864 rc = 1;
33865 while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
33866 (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}
33867 rc = rc ? SQLITE_OK : SQLITE_ERROR;
 
 
33868 #endif
33869 }
33870 if( rc ){
33871 rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
33872 }else{
33873 logIoerr(cnt);
33874 }
33875 free(zConverted);
33876 OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
33877 return rc;
 
 
 
 
 
33878 }
33879
33880 /*
33881 ** Check the existance and status of a file.
33882 */
@@ -59049,10 +59141,11 @@
59141 nMem = 10;
59142 }
59143 memset(zCsr, 0, zEnd-zCsr);
59144 zCsr += (zCsr - (u8*)0)&7;
59145 assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
59146 p->expired = 0;
59147
59148 /* Memory for registers, parameters, cursor, etc, is allocated in two
59149 ** passes. On the first pass, we try to reuse unused space at the
59150 ** end of the opcode array. If we are unable to satisfy all memory
59151 ** requirements by reusing the opcode array tail, then the second
@@ -61277,11 +61370,11 @@
61370 sqlite3_mutex_enter(db->mutex);
61371 while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
61372 && cnt++ < SQLITE_MAX_SCHEMA_RETRY
61373 && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
61374 sqlite3_reset(pStmt);
61375 assert( v->expired==0 );
61376 }
61377 if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
61378 /* This case occurs after failing to recompile an sql statement.
61379 ** The error message from the SQL compiler has already been loaded
61380 ** into the database handle. This block copies the error message
@@ -65968,11 +66061,11 @@
66061 ** automatically created table with root-page 1 (an BLOB_INTKEY table).
66062 */
66063 if( pOp->p4.pKeyInfo ){
66064 int pgno;
66065 assert( pOp->p4type==P4_KEYINFO );
66066 rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
66067 if( rc==SQLITE_OK ){
66068 assert( pgno==MASTER_ROOT+1 );
66069 rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
66070 (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
66071 u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
@@ -71007,15 +71100,29 @@
71100 /* Recursively resolve names in all subqueries
71101 */
71102 for(i=0; i<p->pSrc->nSrc; i++){
71103 struct SrcList_item *pItem = &p->pSrc->a[i];
71104 if( pItem->pSelect ){
71105 NameContext *pNC; /* Used to iterate name contexts */
71106 int nRef = 0; /* Refcount for pOuterNC and outer contexts */
71107 const char *zSavedContext = pParse->zAuthContext;
71108
71109 /* Count the total number of references to pOuterNC and all of its
71110 ** parent contexts. After resolving references to expressions in
71111 ** pItem->pSelect, check if this value has changed. If so, then
71112 ** SELECT statement pItem->pSelect must be correlated. Set the
71113 ** pItem->isCorrelated flag if this is the case. */
71114 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
71115
71116 if( pItem->zName ) pParse->zAuthContext = pItem->zName;
71117 sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
71118 pParse->zAuthContext = zSavedContext;
71119 if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
71120
71121 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
71122 assert( pItem->isCorrelated==0 && nRef<=0 );
71123 pItem->isCorrelated = (nRef!=0);
71124 }
71125 }
71126
71127 /* If there are no aggregate functions in the result-set, and no GROUP BY
71128 ** expression, do not allow aggregates in any of the other expressions.
@@ -72119,10 +72226,11 @@
72226 pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
72227 pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
72228 pNewItem->jointype = pOldItem->jointype;
72229 pNewItem->iCursor = pOldItem->iCursor;
72230 pNewItem->isPopulated = pOldItem->isPopulated;
72231 pNewItem->isCorrelated = pOldItem->isCorrelated;
72232 pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
72233 pNewItem->notIndexed = pOldItem->notIndexed;
72234 pNewItem->pIndex = pOldItem->pIndex;
72235 pTab = pNewItem->pTab = pOldItem->pTab;
72236 if( pTab ){
@@ -80126,11 +80234,11 @@
80234 if( pStart ){
80235 assert( pEnd!=0 );
80236 /* A named index with an explicit CREATE INDEX statement */
80237 zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
80238 onError==OE_None ? "" : " UNIQUE",
80239 (int)(pEnd->z - pName->z) + 1,
80240 pName->z);
80241 }else{
80242 /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
80243 /* zStmt = sqlite3MPrintf(""); */
80244 zStmt = 0;
@@ -81921,11 +82029,13 @@
82029 int regRowid; /* Actual register containing rowids */
82030
82031 /* Collect rowids of every row to be deleted.
82032 */
82033 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
82034 pWInfo = sqlite3WhereBegin(
82035 pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
82036 );
82037 if( pWInfo==0 ) goto delete_from_cleanup;
82038 regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
82039 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
82040 if( db->flags & SQLITE_CountRows ){
82041 sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
@@ -84368,11 +84478,11 @@
84478
84479 /* Create VDBE to loop through the entries in pSrc that match the WHERE
84480 ** clause. If the constraint is not deferred, throw an exception for
84481 ** each row found. Otherwise, for deferred constraints, increment the
84482 ** deferred constraint counter by nIncr for each row selected. */
84483 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
84484 if( nIncr>0 && pFKey->isDeferred==0 ){
84485 sqlite3ParseToplevel(pParse)->mayAbort = 1;
84486 }
84487 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
84488 if( pWInfo ){
@@ -87235,10 +87345,13 @@
87345 int (*strnicmp)(const char*,const char*,int);
87346 int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
87347 int (*wal_autocheckpoint)(sqlite3*,int);
87348 int (*wal_checkpoint)(sqlite3*,const char*);
87349 void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
87350 int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
87351 int (*vtab_config)(sqlite3*,int op,...);
87352 int (*vtab_on_conflict)(sqlite3*);
87353 };
87354
87355 /*
87356 ** The following macros redefine the API routines so that they are
87357 ** redirected throught the global sqlite3_api structure.
@@ -87435,10 +87548,13 @@
87548 #define sqlite3_strnicmp sqlite3_api->strnicmp
87549 #define sqlite3_unlock_notify sqlite3_api->unlock_notify
87550 #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
87551 #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
87552 #define sqlite3_wal_hook sqlite3_api->wal_hook
87553 #define sqlite3_blob_reopen sqlite3_api->blob_reopen
87554 #define sqlite3_vtab_config sqlite3_api->vtab_config
87555 #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
87556 #endif /* SQLITE_CORE */
87557
87558 #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
87559 #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
87560
@@ -87509,10 +87625,12 @@
87625
87626 #ifdef SQLITE_OMIT_VIRTUALTABLE
87627 # define sqlite3_create_module 0
87628 # define sqlite3_create_module_v2 0
87629 # define sqlite3_declare_vtab 0
87630 # define sqlite3_vtab_config 0
87631 # define sqlite3_vtab_on_conflict 0
87632 #endif
87633
87634 #ifdef SQLITE_OMIT_SHARED_CACHE
87635 # define sqlite3_enable_shared_cache 0
87636 #endif
@@ -87532,10 +87650,11 @@
87650 #define sqlite3_blob_bytes 0
87651 #define sqlite3_blob_close 0
87652 #define sqlite3_blob_open 0
87653 #define sqlite3_blob_read 0
87654 #define sqlite3_blob_write 0
87655 #define sqlite3_blob_reopen 0
87656 #endif
87657
87658 /*
87659 ** The following structure contains pointers to all SQLite API routines.
87660 ** A pointer to this structure is passed into extensions when they are
@@ -87797,10 +87916,13 @@
87916 #else
87917 0,
87918 0,
87919 0,
87920 #endif
87921 sqlite3_blob_reopen,
87922 sqlite3_vtab_config,
87923 sqlite3_vtab_on_conflict,
87924 };
87925
87926 /*
87927 ** Attempt to load an SQLite extension library contained in the file
87928 ** zFile. The entry point is zProc. zProc may be 0 in which case a
@@ -94186,10 +94308,11 @@
94308 Expr *pHaving; /* The HAVING clause. May be NULL */
94309 int isDistinct; /* True if the DISTINCT keyword is present */
94310 int distinct; /* Table to use for the distinct set */
94311 int rc = 1; /* Value to return from this function */
94312 int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
94313 int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
94314 AggInfo sAggInfo; /* Information used by aggregate queries */
94315 int iEnd; /* Address of the end of the query */
94316 sqlite3 *db; /* The database connection */
94317
94318 #ifndef SQLITE_OMIT_EXPLAIN
@@ -94312,20 +94435,10 @@
94435 explainSetInteger(pParse->iSelectId, iRestoreSelectId);
94436 return rc;
94437 }
94438 #endif
94439
 
 
 
 
 
 
 
 
 
 
94440 /* If there is both a GROUP BY and an ORDER BY clause and they are
94441 ** identical, then disable the ORDER BY clause since the GROUP BY
94442 ** will cause elements to come out in the correct order. This is
94443 ** an optimization - the correct answer should result regardless.
94444 ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
@@ -94333,10 +94446,34 @@
94446 */
94447 if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
94448 && (db->flags & SQLITE_GroupByOrder)==0 ){
94449 pOrderBy = 0;
94450 }
94451
94452 /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
94453 ** if the select-list is the same as the ORDER BY list, then this query
94454 ** can be rewritten as a GROUP BY. In other words, this:
94455 **
94456 ** SELECT DISTINCT xyz FROM ... ORDER BY xyz
94457 **
94458 ** is transformed to:
94459 **
94460 ** SELECT xyz FROM ... GROUP BY xyz
94461 **
94462 ** The second form is preferred as a single index (or temp-table) may be
94463 ** used for both the ORDER BY and DISTINCT processing. As originally
94464 ** written the query must use a temp-table for at least one of the ORDER
94465 ** BY and DISTINCT, and an index or separate temp-table for the other.
94466 */
94467 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
94468 && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
94469 ){
94470 p->selFlags &= ~SF_Distinct;
94471 p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
94472 pGroupBy = p->pGroupBy;
94473 pOrderBy = 0;
94474 }
94475
94476 /* If there is an ORDER BY clause, then this sorting
94477 ** index might end up being unused if the data can be
94478 ** extracted in pre-sorted order. If that is the case, then the
94479 ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
@@ -94369,26 +94506,25 @@
94506
94507 /* Open a virtual index to use for the distinct set.
94508 */
94509 if( p->selFlags & SF_Distinct ){
94510 KeyInfo *pKeyInfo;
 
94511 distinct = pParse->nTab++;
94512 pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
94513 addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
94514 (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
94515 sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
94516 }else{
94517 distinct = addrDistinctIndex = -1;
94518 }
94519
94520 /* Aggregate and non-aggregate queries are handled differently */
94521 if( !isAgg && pGroupBy==0 ){
94522 ExprList *pDist = (isDistinct ? p->pEList : 0);
94523
94524 /* Begin the database scan. */
94525 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
94526 if( pWInfo==0 ) goto select_end;
94527 if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
94528
94529 /* If sorting index that was created by a prior OP_OpenEphemeral
94530 ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -94397,14 +94533,56 @@
94533 if( addrSortIndex>=0 && pOrderBy==0 ){
94534 sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
94535 p->addrOpenEphm[2] = -1;
94536 }
94537
94538 if( pWInfo->eDistinct ){
94539 VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
94540
94541 assert( addrDistinctIndex>0 );
94542 pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
94543
94544 assert( isDistinct );
94545 assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
94546 || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
94547 );
94548 distinct = -1;
94549 if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
94550 int iJump;
94551 int iExpr;
94552 int iFlag = ++pParse->nMem;
94553 int iBase = pParse->nMem+1;
94554 int iBase2 = iBase + pEList->nExpr;
94555 pParse->nMem += (pEList->nExpr*2);
94556
94557 /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
94558 ** OP_Integer initializes the "first row" flag. */
94559 pOp->opcode = OP_Integer;
94560 pOp->p1 = 1;
94561 pOp->p2 = iFlag;
94562
94563 sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
94564 iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
94565 sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
94566 for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
94567 CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
94568 sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
94569 sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
94570 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
94571 }
94572 sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
94573
94574 sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
94575 assert( sqlite3VdbeCurrentAddr(v)==iJump );
94576 sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
94577 }else{
94578 pOp->opcode = OP_Noop;
94579 }
94580 }
94581
94582 /* Use the standard inner loop. */
94583 selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
94584 pWInfo->iContinue, pWInfo->iBreak);
94585
94586 /* End the database scan loop.
94587 */
94588 sqlite3WhereEnd(pWInfo);
@@ -94510,11 +94688,11 @@
94688 ** This might involve two separate loops with an OP_Sort in between, or
94689 ** it might be a single loop that uses an index to extract information
94690 ** in the right order to begin with.
94691 */
94692 sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
94693 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
94694 if( pWInfo==0 ) goto select_end;
94695 if( pGroupBy==0 ){
94696 /* The optimizer is able to deliver rows in group by order so
94697 ** we do not have to sort. The OP_OpenEphemeral table will be
94698 ** cancelled later because we still need to use the pKeyInfo
@@ -94772,11 +94950,11 @@
94950 /* This case runs if the aggregate has no GROUP BY clause. The
94951 ** processing is much simpler since there is only a single row
94952 ** of output.
94953 */
94954 resetAccumulator(pParse, &sAggInfo);
94955 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
94956 if( pWInfo==0 ){
94957 sqlite3ExprListDelete(db, pDel);
94958 goto select_end;
94959 }
94960 updateAccumulator(pParse, &sAggInfo);
@@ -95248,19 +95426,32 @@
95426 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
95427 if( iDb<0 ){
95428 goto trigger_cleanup;
95429 }
95430 }
95431 if( !pTableName || db->mallocFailed ){
95432 goto trigger_cleanup;
95433 }
95434
95435 /* A long-standing parser bug is that this syntax was allowed:
95436 **
95437 ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
95438 ** ^^^^^^^^
95439 **
95440 ** To maintain backwards compatibility, ignore the database
95441 ** name on pTableName if we are reparsing our of SQLITE_MASTER.
95442 */
95443 if( db->init.busy && iDb!=1 ){
95444 sqlite3DbFree(db, pTableName->a[0].zDatabase);
95445 pTableName->a[0].zDatabase = 0;
95446 }
95447
95448 /* If the trigger name was unqualified, and the table is a temp table,
95449 ** then set iDb to 1 to create the trigger in the temporary database.
95450 ** If sqlite3SrcListLookup() returns 0, indicating the table does not
95451 ** exist, the error is caught by the block below.
95452 */
 
 
 
95453 pTab = sqlite3SrcListLookup(pParse, pTableName);
95454 if( db->init.busy==0 && pName2->n==0 && pTab
95455 && pTab->pSchema==db->aDb[1].pSchema ){
95456 iDb = 1;
95457 }
@@ -96554,11 +96745,13 @@
96745 }
96746
96747 /* Begin the database scan
96748 */
96749 sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
96750 pWInfo = sqlite3WhereBegin(
96751 pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
96752 );
96753 if( pWInfo==0 ) goto update_cleanup;
96754 okOnePass = pWInfo->okOnePass;
96755
96756 /* Remember the rowid of every item to be updated.
96757 */
@@ -98580,10 +98773,11 @@
98773 #define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
98774 #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
98775 #define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
98776 #define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
98777 #define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
98778 #define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
98779
98780 /*
98781 ** Initialize a preallocated WhereClause structure.
98782 */
98783 static void whereClauseInit(
@@ -99724,10 +99918,166 @@
99918 }
99919 }
99920 return 0;
99921 }
99922
99923 /*
99924 ** This function searches the expression list passed as the second argument
99925 ** for an expression of type TK_COLUMN that refers to the same column and
99926 ** uses the same collation sequence as the iCol'th column of index pIdx.
99927 ** Argument iBase is the cursor number used for the table that pIdx refers
99928 ** to.
99929 **
99930 ** If such an expression is found, its index in pList->a[] is returned. If
99931 ** no expression is found, -1 is returned.
99932 */
99933 static int findIndexCol(
99934 Parse *pParse, /* Parse context */
99935 ExprList *pList, /* Expression list to search */
99936 int iBase, /* Cursor for table associated with pIdx */
99937 Index *pIdx, /* Index to match column of */
99938 int iCol /* Column of index to match */
99939 ){
99940 int i;
99941 const char *zColl = pIdx->azColl[iCol];
99942
99943 for(i=0; i<pList->nExpr; i++){
99944 Expr *p = pList->a[i].pExpr;
99945 if( p->op==TK_COLUMN
99946 && p->iColumn==pIdx->aiColumn[iCol]
99947 && p->iTable==iBase
99948 ){
99949 CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
99950 if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
99951 return i;
99952 }
99953 }
99954 }
99955
99956 return -1;
99957 }
99958
99959 /*
99960 ** This routine determines if pIdx can be used to assist in processing a
99961 ** DISTINCT qualifier. In other words, it tests whether or not using this
99962 ** index for the outer loop guarantees that rows with equal values for
99963 ** all expressions in the pDistinct list are delivered grouped together.
99964 **
99965 ** For example, the query
99966 **
99967 ** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
99968 **
99969 ** can benefit from any index on columns "b" and "c".
99970 */
99971 static int isDistinctIndex(
99972 Parse *pParse, /* Parsing context */
99973 WhereClause *pWC, /* The WHERE clause */
99974 Index *pIdx, /* The index being considered */
99975 int base, /* Cursor number for the table pIdx is on */
99976 ExprList *pDistinct, /* The DISTINCT expressions */
99977 int nEqCol /* Number of index columns with == */
99978 ){
99979 Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
99980 int i; /* Iterator variable */
99981
99982 if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
99983 testcase( pDistinct->nExpr==BMS-1 );
99984
99985 /* Loop through all the expressions in the distinct list. If any of them
99986 ** are not simple column references, return early. Otherwise, test if the
99987 ** WHERE clause contains a "col=X" clause. If it does, the expression
99988 ** can be ignored. If it does not, and the column does not belong to the
99989 ** same table as index pIdx, return early. Finally, if there is no
99990 ** matching "col=X" expression and the column is on the same table as pIdx,
99991 ** set the corresponding bit in variable mask.
99992 */
99993 for(i=0; i<pDistinct->nExpr; i++){
99994 WhereTerm *pTerm;
99995 Expr *p = pDistinct->a[i].pExpr;
99996 if( p->op!=TK_COLUMN ) return 0;
99997 pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
99998 if( pTerm ){
99999 Expr *pX = pTerm->pExpr;
100000 CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
100001 CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
100002 if( p1==p2 ) continue;
100003 }
100004 if( p->iTable!=base ) return 0;
100005 mask |= (((Bitmask)1) << i);
100006 }
100007
100008 for(i=nEqCol; mask && i<pIdx->nColumn; i++){
100009 int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
100010 if( iExpr<0 ) break;
100011 mask &= ~(((Bitmask)1) << iExpr);
100012 }
100013
100014 return (mask==0);
100015 }
100016
100017
100018 /*
100019 ** Return true if the DISTINCT expression-list passed as the third argument
100020 ** is redundant. A DISTINCT list is redundant if the database contains a
100021 ** UNIQUE index that guarantees that the result of the query will be distinct
100022 ** anyway.
100023 */
100024 static int isDistinctRedundant(
100025 Parse *pParse,
100026 SrcList *pTabList,
100027 WhereClause *pWC,
100028 ExprList *pDistinct
100029 ){
100030 Table *pTab;
100031 Index *pIdx;
100032 int i;
100033 int iBase;
100034
100035 /* If there is more than one table or sub-select in the FROM clause of
100036 ** this query, then it will not be possible to show that the DISTINCT
100037 ** clause is redundant. */
100038 if( pTabList->nSrc!=1 ) return 0;
100039 iBase = pTabList->a[0].iCursor;
100040 pTab = pTabList->a[0].pTab;
100041
100042 /* If any of the expressions is an IPK column on table iBase, then return
100043 ** true. Note: The (p->iTable==iBase) part of this test may be false if the
100044 ** current SELECT is a correlated sub-query.
100045 */
100046 for(i=0; i<pDistinct->nExpr; i++){
100047 Expr *p = pDistinct->a[i].pExpr;
100048 if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
100049 }
100050
100051 /* Loop through all indices on the table, checking each to see if it makes
100052 ** the DISTINCT qualifier redundant. It does so if:
100053 **
100054 ** 1. The index is itself UNIQUE, and
100055 **
100056 ** 2. All of the columns in the index are either part of the pDistinct
100057 ** list, or else the WHERE clause contains a term of the form "col=X",
100058 ** where X is a constant value. The collation sequences of the
100059 ** comparison and select-list expressions must match those of the index.
100060 */
100061 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
100062 if( pIdx->onError==OE_None ) continue;
100063 for(i=0; i<pIdx->nColumn; i++){
100064 int iCol = pIdx->aiColumn[i];
100065 if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx)
100066 && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
100067 ){
100068 break;
100069 }
100070 }
100071 if( i==pIdx->nColumn ){
100072 /* This index implies that the DISTINCT qualifier is redundant. */
100073 return 1;
100074 }
100075 }
100076
100077 return 0;
100078 }
100079
100080 /*
100081 ** This routine decides if pIdx can be used to satisfy the ORDER BY
100082 ** clause. If it can, it returns 1. If pIdx cannot satisfy the
100083 ** ORDER BY clause, this routine returns 0.
@@ -99760,11 +100110,14 @@
100110 int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
100111 int nTerm; /* Number of ORDER BY terms */
100112 struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
100113 sqlite3 *db = pParse->db;
100114
100115 if( !pOrderBy ) return 0;
100116 if( wsFlags & WHERE_COLUMN_IN ) return 0;
100117 if( pIdx->bUnordered ) return 0;
100118
100119 nTerm = pOrderBy->nExpr;
100120 assert( nTerm>0 );
100121
100122 /* Argument pIdx must either point to a 'real' named index structure,
100123 ** or an index structure allocated on the stack by bestBtreeIndex() to
@@ -100073,10 +100426,14 @@
100426 double costTempIdx; /* per-query cost of the transient index */
100427 WhereTerm *pTerm; /* A single term of the WHERE clause */
100428 WhereTerm *pWCEnd; /* End of pWC->a[] */
100429 Table *pTable; /* Table tht might be indexed */
100430
100431 if( pParse->nQueryLoop<=(double)1 ){
100432 /* There is no point in building an automatic index for a single scan */
100433 return;
100434 }
100435 if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
100436 /* Automatic indices are disabled at run-time */
100437 return;
100438 }
100439 if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
@@ -100084,10 +100441,14 @@
100441 return;
100442 }
100443 if( pSrc->notIndexed ){
100444 /* The NOT INDEXED clause appears in the SQL. */
100445 return;
100446 }
100447 if( pSrc->isCorrelated ){
100448 /* The source is a correlated sub-query. No point in indexing it. */
100449 return;
100450 }
100451
100452 assert( pParse->nQueryLoop >= (double)1 );
100453 pTable = pSrc->pTab;
100454 nTableRow = pTable->nRowEst;
@@ -101016,10 +101377,11 @@
101377 WhereClause *pWC, /* The WHERE clause */
101378 struct SrcList_item *pSrc, /* The FROM clause term to search */
101379 Bitmask notReady, /* Mask of cursors not available for indexing */
101380 Bitmask notValid, /* Cursors not available for any purpose */
101381 ExprList *pOrderBy, /* The ORDER BY clause */
101382 ExprList *pDistinct, /* The select-list if query is DISTINCT */
101383 WhereCost *pCost /* Lowest cost query plan */
101384 ){
101385 int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
101386 Index *pProbe; /* An index we are evaluating */
101387 Index *pIdx; /* Copy of pProbe, or zero for IPK index */
@@ -101156,11 +101518,12 @@
101518 int nEq; /* Number of == or IN terms matching index */
101519 int bInEst = 0; /* True if "x IN (SELECT...)" seen */
101520 int nInMul = 1; /* Number of distinct equalities to lookup */
101521 int estBound = 100; /* Estimated reduction in search space */
101522 int nBound = 0; /* Number of range constraints seen */
101523 int bSort = !!pOrderBy; /* True if external sort required */
101524 int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */
101525 int bLookup = 0; /* True if not a covering index */
101526 WhereTerm *pTerm; /* A single term of the WHERE clause */
101527 #ifdef SQLITE_ENABLE_STAT2
101528 WhereTerm *pFirstTerm = 0; /* First term matching the index */
101529 #endif
@@ -101220,21 +101583,24 @@
101583
101584 /* If there is an ORDER BY clause and the index being considered will
101585 ** naturally scan rows in the required order, set the appropriate flags
101586 ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
101587 ** will scan rows in a different order, set the bSort variable. */
101588 if( isSortingIndex(
101589 pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
101590 ){
101591 bSort = 0;
101592 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
101593 wsFlags |= (rev ? WHERE_REVERSE : 0);
101594 }
101595
101596 /* If there is a DISTINCT qualifier and this index will scan rows in
101597 ** order of the DISTINCT expressions, clear bDist and set the appropriate
101598 ** flags in wsFlags. */
101599 if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
101600 bDist = 0;
101601 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
101602 }
101603
101604 /* If currently calculating the cost of using an index (not the IPK
101605 ** index), determine if all required column data may be obtained without
101606 ** using the main table (i.e. if the index is a covering
@@ -101265,16 +101631,17 @@
101631 nRow = aiRowEst[0]/2;
101632 nInMul = (int)(nRow / aiRowEst[nEq]);
101633 }
101634
101635 #ifdef SQLITE_ENABLE_STAT2
101636 /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
101637 ** and we do not think that values of x are unique and if histogram
101638 ** data is available for column x, then it might be possible
101639 ** to get a better estimate on the number of rows based on
101640 ** VALUE and how common that value is according to the histogram.
101641 */
101642 if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
101643 if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
101644 testcase( pFirstTerm->eOperator==WO_EQ );
101645 testcase( pFirstTerm->eOperator==WO_ISNULL );
101646 whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
101647 }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
@@ -101347,10 +101714,13 @@
101714 ** difference and select C of 3.0.
101715 */
101716 if( bSort ){
101717 cost += nRow*estLog(nRow)*3;
101718 }
101719 if( bDist ){
101720 cost += nRow*estLog(nRow)*3;
101721 }
101722
101723 /**** Cost of using this index has now been computed ****/
101724
101725 /* If there are additional constraints on this table that cannot
101726 ** be used with the current index, but which might lower the number
@@ -101492,11 +101862,11 @@
101862 }
101863 sqlite3DbFree(pParse->db, p);
101864 }else
101865 #endif
101866 {
101867 bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
101868 }
101869 }
101870
101871 /*
101872 ** Disable a term in the WHERE clause. Except, do not disable the term
@@ -102454,11 +102824,11 @@
102824 for(ii=0; ii<pOrWc->nTerm; ii++){
102825 WhereTerm *pOrTerm = &pOrWc->a[ii];
102826 if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
102827 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
102828 /* Loop through table entries that match term pOrTerm. */
102829 pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0, 0,
102830 WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
102831 WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
102832 if( pSubWInfo ){
102833 explainOneScan(
102834 pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
@@ -102695,10 +103065,11 @@
103065 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
103066 Parse *pParse, /* The parser context */
103067 SrcList *pTabList, /* A list of all tables to be scanned */
103068 Expr *pWhere, /* The WHERE clause */
103069 ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
103070 ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
103071 u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
103072 ){
103073 int i; /* Loop counter */
103074 int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
103075 int nTabList; /* Number of elements in pTabList */
@@ -102754,10 +103125,14 @@
103125 pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
103126 pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
103127 pWInfo->wctrlFlags = wctrlFlags;
103128 pWInfo->savedNQueryLoop = pParse->nQueryLoop;
103129 pMaskSet = (WhereMaskSet*)&pWC[1];
103130
103131 /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
103132 ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
103133 if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
103134
103135 /* Split the WHERE clause into separate subexpressions where each
103136 ** subexpression is separated by an AND operator.
103137 */
103138 initMaskSet(pMaskSet);
@@ -102821,10 +103196,19 @@
103196 */
103197 exprAnalyzeAll(pTabList, pWC);
103198 if( db->mallocFailed ){
103199 goto whereBeginError;
103200 }
103201
103202 /* Check if the DISTINCT qualifier, if there is one, is redundant.
103203 ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
103204 ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
103205 */
103206 if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
103207 pDistinct = 0;
103208 pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
103209 }
103210
103211 /* Chose the best index to use for each table in the FROM clause.
103212 **
103213 ** This loop fills in the following fields:
103214 **
@@ -102905,10 +103289,11 @@
103289 Bitmask mask; /* Mask of tables not yet ready */
103290 for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
103291 int doNotReorder; /* True if this table should not be reordered */
103292 WhereCost sCost; /* Cost information from best[Virtual]Index() */
103293 ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
103294 ExprList *pDist; /* DISTINCT clause for index to optimize */
103295
103296 doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
103297 if( j!=iFrom && doNotReorder ) break;
103298 m = getMask(pMaskSet, pTabItem->iCursor);
103299 if( (m & notReady)==0 ){
@@ -102915,10 +103300,11 @@
103300 if( j==iFrom ) iFrom++;
103301 continue;
103302 }
103303 mask = (isOptimal ? m : notReady);
103304 pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
103305 pDist = (i==0 ? pDistinct : 0);
103306 if( pTabItem->pIndex==0 ) nUnconstrained++;
103307
103308 WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
103309 j, isOptimal));
103310 assert( pTabItem->pTab );
@@ -102929,11 +103315,11 @@
103315 &sCost, pp);
103316 }else
103317 #endif
103318 {
103319 bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
103320 pDist, &sCost);
103321 }
103322 assert( isOptimal || (sCost.used&notReady)==0 );
103323
103324 /* If an INDEXED BY clause is present, then the plan must use that
103325 ** index if it uses any index at all */
@@ -102989,10 +103375,14 @@
103375 WHERETRACE(("*** Optimizer selects table %d for loop %d"
103376 " with cost=%g and nRow=%g\n",
103377 bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
103378 if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
103379 *ppOrderBy = 0;
103380 }
103381 if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
103382 assert( pWInfo->eDistinct==0 );
103383 pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
103384 }
103385 andFlags &= bestPlan.plan.wsFlags;
103386 pLevel->plan = bestPlan.plan;
103387 testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
103388 testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
@@ -111519,11 +111909,17 @@
111909 */
111910 #if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
111911 # define SQLITE_ENABLE_FTS3
111912 #endif
111913
111914 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
111915
111916 /* If not building as part of the core, include sqlite3ext.h. */
111917 #ifndef SQLITE_CORE
111918 SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
111919 #endif
111920
111921 /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
111922 /************** Begin file fts3_tokenizer.h **********************************/
111923 /*
111924 ** 2006 July 10
111925 **
@@ -112052,11 +112448,11 @@
112448
112449 sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
112450 int bFreeList; /* True if pList should be sqlite3_free()d */
112451 char *pList; /* Pointer to position list following iDocid */
112452 int nList; /* Length of position list */
112453 };
112454
112455 /*
112456 ** A "phrase" is a sequence of one or more tokens that must match in
112457 ** sequence. A single token is the base case and the most common case.
112458 ** For a sequence of tokens contained in double-quotes (i.e. "one two three")
@@ -112252,23 +112648,12 @@
112648 #endif
112649
112650 /* fts3_aux.c */
112651 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
112652
 
 
 
 
 
 
 
 
112653 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
112654
 
 
 
112655 SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
112656 Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
112657 SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
112658 Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
112659 SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol);
@@ -112275,11 +112660,11 @@
112660 SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
112661 SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
112662
112663 SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
112664
112665 #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
112666 #endif /* _FTSINT_H */
112667
112668 /************** End of fts3Int.h *********************************************/
112669 /************** Continuing where we left off in fts3.c ***********************/
112670 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
@@ -112291,10 +112676,15 @@
112676
112677 #ifndef SQLITE_CORE
112678 SQLITE_EXTENSION_INIT1
112679 #endif
112680
112681 static int fts3EvalNext(Fts3Cursor *pCsr);
112682 static int fts3EvalStart(Fts3Cursor *pCsr);
112683 static int fts3TermSegReaderCursor(
112684 Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
112685
112686 /*
112687 ** Write a 64-bit variable-length integer to memory starting at p[0].
112688 ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
112689 ** The number of bytes written is returned.
112690 */
@@ -112799,31 +113189,60 @@
113189 }
113190 sqlite3_free(zFree);
113191 return zRet;
113192 }
113193
113194 /*
113195 ** This function interprets the string at (*pp) as a non-negative integer
113196 ** value. It reads the integer and sets *pnOut to the value read, then
113197 ** sets *pp to point to the byte immediately following the last byte of
113198 ** the integer value.
113199 **
113200 ** Only decimal digits ('0'..'9') may be part of an integer value.
113201 **
113202 ** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
113203 ** the output value undefined. Otherwise SQLITE_OK is returned.
113204 **
113205 ** This function is used when parsing the "prefix=" FTS4 parameter.
113206 */
113207 static int fts3GobbleInt(const char **pp, int *pnOut){
113208 const char *p = *pp; /* Iterator pointer */
113209 int nInt = 0; /* Output value */
113210
113211 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
113212 nInt = nInt * 10 + (p[0] - '0');
113213 }
113214 if( p==*pp ) return SQLITE_ERROR;
113215 *pnOut = nInt;
113216 *pp = p;
113217 return SQLITE_OK;
113218 }
113219
113220 /*
113221 ** This function is called to allocate an array of Fts3Index structures
113222 ** representing the indexes maintained by the current FTS table. FTS tables
113223 ** always maintain the main "terms" index, but may also maintain one or
113224 ** more "prefix" indexes, depending on the value of the "prefix=" parameter
113225 ** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
113226 **
113227 ** Argument zParam is passed the value of the "prefix=" option if one was
113228 ** specified, or NULL otherwise.
113229 **
113230 ** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
113231 ** the allocated array. *pnIndex is set to the number of elements in the
113232 ** array. If an error does occur, an SQLite error code is returned.
113233 **
113234 ** Regardless of whether or not an error is returned, it is the responsibility
113235 ** of the caller to call sqlite3_free() on the output array to free it.
113236 */
113237 static int fts3PrefixParameter(
113238 const char *zParam, /* ABC in prefix=ABC parameter to parse */
113239 int *pnIndex, /* OUT: size of *apIndex[] array */
113240 struct Fts3Index **apIndex /* OUT: Array of indexes for this table */
 
113241 ){
113242 struct Fts3Index *aIndex; /* Allocated array */
113243 int nIndex = 1; /* Number of entries in array */
113244
113245 if( zParam && zParam[0] ){
113246 const char *p;
113247 nIndex++;
113248 for(p=zParam; *p; p++){
@@ -112830,11 +113249,11 @@
113249 if( *p==',' ) nIndex++;
113250 }
113251 }
113252
113253 aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
113254 *apIndex = aIndex;
113255 *pnIndex = nIndex;
113256 if( !aIndex ){
113257 return SQLITE_NOMEM;
113258 }
113259
@@ -112887,12 +113306,11 @@
113306 int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
113307 const char **aCol; /* Array of column names */
113308 sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
113309
113310 int nIndex; /* Size of aIndex[] array */
113311 struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
 
113312
113313 /* The results of parsing supported FTS4 key=value options: */
113314 int bNoDocsize = 0; /* True to omit %_docsize table */
113315 int bDescIdx = 0; /* True to store descending indexes */
113316 char *zPrefix = 0; /* Prefix parameter value (or NULL) */
@@ -113025,11 +113443,11 @@
113443 rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
113444 if( rc!=SQLITE_OK ) goto fts3_init_out;
113445 }
113446 assert( pTokenizer );
113447
113448 rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
113449 if( rc==SQLITE_ERROR ){
113450 assert( zPrefix );
113451 *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
113452 }
113453 if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -113112,11 +113530,11 @@
113530 /* Declare the table schema to SQLite. */
113531 fts3DeclareVtab(&rc, p);
113532
113533 fts3_init_out:
113534 sqlite3_free(zPrefix);
113535 sqlite3_free(aIndex);
113536 sqlite3_free(zCompress);
113537 sqlite3_free(zUncompress);
113538 sqlite3_free((void *)aCol);
113539 if( rc!=SQLITE_OK ){
113540 if( p ){
@@ -113703,12 +114121,10 @@
114121 *pp1 = p1 + 1;
114122 *pp2 = p2 + 1;
114123 }
114124
114125 /*
 
 
114126 ** This function is used to merge two position lists into one. When it is
114127 ** called, *pp1 and *pp2 must both point to position lists. A position-list is
114128 ** the part of a doclist that follows each document id. For example, if a row
114129 ** contains:
114130 **
@@ -113724,10 +114140,12 @@
114140 ** If isSaveLeft is 0, an entry is added to the output position list for
114141 ** each position in *pp2 for which there exists one or more positions in
114142 ** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
114143 ** when the *pp1 token appears before the *pp2 token, but not more than nToken
114144 ** slots before it.
114145 **
114146 ** e.g. nToken==1 searches for adjacent positions.
114147 */
114148 static int fts3PoslistPhraseMerge(
114149 char **pp, /* IN/OUT: Preallocated output buffer */
114150 int nToken, /* Maximum difference in token positions */
114151 int isSaveLeft, /* Save the left position */
@@ -113890,26 +114308,38 @@
114308
114309 return res;
114310 }
114311
114312 /*
114313 ** An instance of this function is used to merge together the (potentially
114314 ** large number of) doclists for each term that matches a prefix query.
114315 ** See function fts3TermSelectMerge() for details.
114316 */
114317 typedef struct TermSelect TermSelect;
114318 struct TermSelect {
114319 char *aaOutput[16]; /* Malloc'd output buffers */
114320 int anOutput[16]; /* Size each output buffer in bytes */
 
114321 };
114322
114323 /*
114324 ** This function is used to read a single varint from a buffer. Parameter
114325 ** pEnd points 1 byte past the end of the buffer. When this function is
114326 ** called, if *pp points to pEnd or greater, then the end of the buffer
114327 ** has been reached. In this case *pp is set to 0 and the function returns.
114328 **
114329 ** If *pp does not point to or past pEnd, then a single varint is read
114330 ** from *pp. *pp is then set to point 1 byte past the end of the read varint.
114331 **
114332 ** If bDescIdx is false, the value read is added to *pVal before returning.
114333 ** If it is true, the value read is subtracted from *pVal before this
114334 ** function returns.
114335 */
114336 static void fts3GetDeltaVarint3(
114337 char **pp, /* IN/OUT: Point to read varint from */
114338 char *pEnd, /* End of buffer */
114339 int bDescIdx, /* True if docids are descending */
114340 sqlite3_int64 *pVal /* IN/OUT: Integer value */
114341 ){
114342 if( *pp>=pEnd ){
114343 *pp = 0;
114344 }else{
114345 sqlite3_int64 iVal;
@@ -113920,10 +114350,25 @@
114350 *pVal += iVal;
114351 }
114352 }
114353 }
114354
114355 /*
114356 ** This function is used to write a single varint to a buffer. The varint
114357 ** is written to *pp. Before returning, *pp is set to point 1 byte past the
114358 ** end of the value written.
114359 **
114360 ** If *pbFirst is zero when this function is called, the value written to
114361 ** the buffer is that of parameter iVal.
114362 **
114363 ** If *pbFirst is non-zero when this function is called, then the value
114364 ** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
114365 ** (if bDescIdx is non-zero).
114366 **
114367 ** Before returning, this function always sets *pbFirst to 1 and *piPrev
114368 ** to the value of parameter iVal.
114369 */
114370 static void fts3PutDeltaVarint3(
114371 char **pp, /* IN/OUT: Output pointer */
114372 int bDescIdx, /* True for descending docids */
114373 sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
114374 int *pbFirst, /* IN/OUT: True after first int written */
@@ -113940,14 +114385,38 @@
114385 *pp += sqlite3Fts3PutVarint(*pp, iWrite);
114386 *piPrev = iVal;
114387 *pbFirst = 1;
114388 }
114389
 
114390
114391 /*
114392 ** This macro is used by various functions that merge doclists. The two
114393 ** arguments are 64-bit docid values. If the value of the stack variable
114394 ** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
114395 ** Otherwise, (i2-i1).
114396 **
114397 ** Using this makes it easier to write code that can merge doclists that are
114398 ** sorted in either ascending or descending order.
114399 */
114400 #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
114401
114402 /*
114403 ** This function does an "OR" merge of two doclists (output contains all
114404 ** positions contained in either argument doclist). If the docids in the
114405 ** input doclists are sorted in ascending order, parameter bDescDoclist
114406 ** should be false. If they are sorted in ascending order, it should be
114407 ** passed a non-zero value.
114408 **
114409 ** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
114410 ** containing the output doclist and SQLITE_OK is returned. In this case
114411 ** *pnOut is set to the number of bytes in the output doclist.
114412 **
114413 ** If an error occurs, an SQLite error code is returned. The output values
114414 ** are undefined in this case.
114415 */
114416 static int fts3DoclistOrMerge(
114417 int bDescDoclist, /* True if arguments are desc */
114418 char *a1, int n1, /* First doclist */
114419 char *a2, int n2, /* Second doclist */
114420 char **paOut, int *pnOut /* OUT: Malloc'd doclist */
114421 ){
114422 sqlite3_int64 i1 = 0;
@@ -113968,35 +114437,47 @@
114437
114438 p = aOut;
114439 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
114440 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
114441 while( p1 || p2 ){
114442 sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
114443
114444 if( p2 && p1 && iDiff==0 ){
114445 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
114446 fts3PoslistMerge(&p, &p1, &p2);
114447 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
114448 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
114449 }else if( !p2 || (p1 && iDiff<0) ){
114450 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
114451 fts3PoslistCopy(&p, &p1);
114452 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
114453 }else{
114454 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
114455 fts3PoslistCopy(&p, &p2);
114456 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
114457 }
114458 }
114459
114460 *paOut = aOut;
114461 *pnOut = (p-aOut);
114462 return SQLITE_OK;
114463 }
114464
114465 /*
114466 ** This function does a "phrase" merge of two doclists. In a phrase merge,
114467 ** the output contains a copy of each position from the right-hand input
114468 ** doclist for which there is a position in the left-hand input doclist
114469 ** exactly nDist tokens before it.
114470 **
114471 ** If the docids in the input doclists are sorted in ascending order,
114472 ** parameter bDescDoclist should be false. If they are sorted in ascending
114473 ** order, it should be passed a non-zero value.
114474 **
114475 ** The right-hand input doclist is overwritten by this function.
114476 */
114477 static void fts3DoclistPhraseMerge(
114478 int bDescDoclist, /* True if arguments are desc */
114479 int nDist, /* Distance from left to right (1=adjacent) */
114480 char *aLeft, int nLeft, /* Left doclist */
114481 char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
114482 ){
114483 sqlite3_int64 i1 = 0;
@@ -114015,30 +114496,30 @@
114496 p = aOut;
114497 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
114498 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
114499
114500 while( p1 && p2 ){
114501 sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
114502 if( iDiff==0 ){
114503 char *pSave = p;
114504 sqlite3_int64 iPrevSave = iPrev;
114505 int bFirstOutSave = bFirstOut;
114506
114507 fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
114508 if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
114509 p = pSave;
114510 iPrev = iPrevSave;
114511 bFirstOut = bFirstOutSave;
114512 }
114513 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
114514 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
114515 }else if( iDiff<0 ){
114516 fts3PoslistCopy(0, &p1);
114517 fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
114518 }else{
114519 fts3PoslistCopy(0, &p2);
114520 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
114521 }
114522 }
114523
114524 *pnRight = p - aOut;
114525 }
@@ -114051,11 +114532,11 @@
114532 **
114533 ** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
114534 ** the responsibility of the caller to free any doclists left in the
114535 ** TermSelect.aaOutput[] array.
114536 */
114537 static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
114538 char *aOut = 0;
114539 int nOut = 0;
114540 int i;
114541
114542 /* Loop through the doclists in the aaOutput[] array. Merge them all
@@ -114092,28 +114573,29 @@
114573 pTS->anOutput[0] = nOut;
114574 return SQLITE_OK;
114575 }
114576
114577 /*
114578 ** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
114579 ** as the first argument. The merge is an "OR" merge (see function
114580 ** fts3DoclistOrMerge() for details).
114581 **
114582 ** This function is called with the doclist for each term that matches
114583 ** a queried prefix. It merges all these doclists into one, the doclist
114584 ** for the specified prefix. Since there can be a very large number of
114585 ** doclists to merge, the merging is done pair-wise using the TermSelect
114586 ** object.
114587 **
114588 ** This function returns SQLITE_OK if the merge is successful, or an
114589 ** SQLite error code (SQLITE_NOMEM) if an error occurs.
114590 */
114591 static int fts3TermSelectMerge(
114592 Fts3Table *p, /* FTS table handle */
114593 TermSelect *pTS, /* TermSelect object to merge into */
114594 char *aDoclist, /* Pointer to doclist */
114595 int nDoclist /* Size of aDoclist in bytes */
 
 
114596 ){
 
 
 
 
 
 
114597 if( pTS->aaOutput[0]==0 ){
114598 /* If this is the first term selected, copy the doclist to the output
114599 ** buffer using memcpy(). */
114600 pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
114601 pTS->anOutput[0] = nDoclist;
@@ -114180,23 +114662,30 @@
114662 }
114663 pCsr->apSegment[pCsr->nSegment++] = pNew;
114664 return SQLITE_OK;
114665 }
114666
114667 /*
114668 ** Add seg-reader objects to the Fts3MultiSegReader object passed as the
114669 ** 8th argument.
114670 **
114671 ** This function returns SQLITE_OK if successful, or an SQLite error code
114672 ** otherwise.
114673 */
114674 static int fts3SegReaderCursor(
114675 Fts3Table *p, /* FTS3 table handle */
114676 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
114677 int iLevel, /* Level of segments to scan */
114678 const char *zTerm, /* Term to query for */
114679 int nTerm, /* Size of zTerm in bytes */
114680 int isPrefix, /* True for a prefix search */
114681 int isScan, /* True to scan from zTerm to EOF */
114682 Fts3MultiSegReader *pCsr /* Cursor object to populate */
114683 ){
114684 int rc = SQLITE_OK; /* Error code */
114685 sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
114686 int rc2; /* Result of sqlite3_reset() */
114687
114688 /* If iLevel is less than 0 and this is not a scan, include a seg-reader
114689 ** for the pending-terms. If this is a scan, then this call must be being
114690 ** made by an fts4aux module, not an FTS table. In this case calling
114691 ** Fts3SegReaderPending might segfault, as the data structures used by
@@ -114281,28 +114770,46 @@
114770 return fts3SegReaderCursor(
114771 p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
114772 );
114773 }
114774
114775 /*
114776 ** In addition to its current configuration, have the Fts3MultiSegReader
114777 ** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
114778 **
114779 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
114780 */
114781 static int fts3SegReaderCursorAddZero(
114782 Fts3Table *p, /* FTS virtual table handle */
114783 const char *zTerm, /* Term to scan doclist of */
114784 int nTerm, /* Number of bytes in zTerm */
114785 Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
114786 ){
114787 return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
114788 }
114789
114790 /*
114791 ** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
114792 ** if isPrefix is true, to scan the doclist for all terms for which
114793 ** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
114794 ** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
114795 ** an SQLite error code.
114796 **
114797 ** It is the responsibility of the caller to free this object by eventually
114798 ** passing it to fts3SegReaderCursorFree()
114799 **
114800 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
114801 ** Output parameter *ppSegcsr is set to 0 if an error occurs.
114802 */
114803 static int fts3TermSegReaderCursor(
114804 Fts3Cursor *pCsr, /* Virtual table cursor handle */
114805 const char *zTerm, /* Term to query for */
114806 int nTerm, /* Size of zTerm in bytes */
114807 int isPrefix, /* True for a prefix search */
114808 Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
114809 ){
114810 Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
114811 int rc = SQLITE_NOMEM; /* Return code */
114812
114813 pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
114814 if( pSegcsr ){
114815 int i;
@@ -114342,62 +114849,53 @@
114849
114850 *ppSegcsr = pSegcsr;
114851 return rc;
114852 }
114853
114854 /*
114855 ** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
114856 */
114857 static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
114858 sqlite3Fts3SegReaderFinish(pSegcsr);
114859 sqlite3_free(pSegcsr);
114860 }
114861
114862 /*
114863 ** This function retreives the doclist for the specified term (or term
114864 ** prefix) from the database.
 
 
 
 
 
 
 
114865 */
114866 static int fts3TermSelect(
114867 Fts3Table *p, /* Virtual table handle */
114868 Fts3PhraseToken *pTok, /* Token to query for */
114869 int iColumn, /* Column to query (or -ve for all columns) */
 
114870 int *pnOut, /* OUT: Size of buffer at *ppOut */
114871 char **ppOut /* OUT: Malloced result buffer */
114872 ){
114873 int rc; /* Return code */
114874 Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
114875 TermSelect tsc; /* Object for pair-wise doclist merging */
114876 Fts3SegFilter filter; /* Segment term filter configuration */
114877
114878 pSegcsr = pTok->pSegcsr;
114879 memset(&tsc, 0, sizeof(TermSelect));
 
114880
114881 filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
114882 | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
 
114883 | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
114884 filter.iCol = iColumn;
114885 filter.zTerm = pTok->z;
114886 filter.nTerm = pTok->n;
114887
114888 rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
114889 while( SQLITE_OK==rc
114890 && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
114891 ){
114892 rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
 
 
114893 }
114894
114895 if( rc==SQLITE_OK ){
114896 rc = fts3TermSelectFinishMerge(p, &tsc);
114897 }
114898 if( rc==SQLITE_OK ){
114899 *ppOut = tsc.aaOutput[0];
114900 *pnOut = tsc.anOutput[0];
114901 }else{
@@ -114419,28 +114917,19 @@
114917 ** If the isPoslist argument is true, then it is assumed that the doclist
114918 ** contains a position-list following each docid. Otherwise, it is assumed
114919 ** that the doclist is simply a list of docids stored as delta encoded
114920 ** varints.
114921 */
114922 static int fts3DoclistCountDocids(char *aList, int nList){
114923 int nDoc = 0; /* Return value */
114924 if( aList ){
114925 char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
114926 char *p = aList; /* Cursor */
114927 while( p<aEnd ){
114928 nDoc++;
114929 while( (*p++)&0x80 ); /* Skip docid varint */
114930 fts3PoslistCopy(0, &p); /* Skip over position list */
 
 
 
 
 
 
 
 
 
114931 }
114932 }
114933
114934 return nDoc;
114935 }
@@ -114466,11 +114955,11 @@
114955 }else{
114956 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114957 rc = SQLITE_OK;
114958 }
114959 }else{
114960 rc = fts3EvalNext((Fts3Cursor *)pCursor);
114961 }
114962 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
114963 return rc;
114964 }
114965
@@ -114543,11 +115032,11 @@
115032 }
115033
115034 rc = sqlite3Fts3ReadLock(p);
115035 if( rc!=SQLITE_OK ) return rc;
115036
115037 rc = fts3EvalStart(pCsr);
115038
115039 sqlite3Fts3SegmentsClose(p);
115040 if( rc!=SQLITE_OK ) return rc;
115041 pCsr->pNextId = pCsr->aDoclist;
115042 pCsr->iPrevId = 0;
@@ -114950,26 +115439,43 @@
115439 p->zDb, p->zName, zName
115440 );
115441 return rc;
115442 }
115443
115444 /*
115445 ** The xSavepoint() method.
115446 **
115447 ** Flush the contents of the pending-terms table to disk.
115448 */
115449 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
115450 UNUSED_PARAMETER(iSavepoint);
115451 assert( ((Fts3Table *)pVtab)->inTransaction );
115452 assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
115453 TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
115454 return fts3SyncMethod(pVtab);
115455 }
115456
115457 /*
115458 ** The xRelease() method.
115459 **
115460 ** This is a no-op.
115461 */
115462 static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
115463 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
115464 UNUSED_PARAMETER(iSavepoint);
115465 UNUSED_PARAMETER(pVtab);
115466 assert( p->inTransaction );
115467 assert( p->mxSavepoint >= iSavepoint );
115468 TESTONLY( p->mxSavepoint = iSavepoint-1 );
115469 return SQLITE_OK;
115470 }
115471
115472 /*
115473 ** The xRollbackTo() method.
115474 **
115475 ** Discard the contents of the pending terms table.
115476 */
115477 static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
115478 Fts3Table *p = (Fts3Table*)pVtab;
115479 UNUSED_PARAMETER(iSavepoint);
115480 assert( p->inTransaction );
115481 assert( p->mxSavepoint >= iSavepoint );
@@ -115114,22 +115620,10 @@
115620 sqlite3Fts3HashClear(pHash);
115621 sqlite3_free(pHash);
115622 }
115623 return rc;
115624 }
 
 
 
 
 
 
 
 
 
 
 
 
115625
115626 /*
115627 ** Allocate an Fts3MultiSegReader for each token in the expression headed
115628 ** by pExpr.
115629 **
@@ -115143,24 +115637,24 @@
115637 ** there exists prefix b-tree of the right length) then it may be traversed
115638 ** and merged incrementally. Otherwise, it has to be merged into an in-memory
115639 ** doclist and then traversed.
115640 */
115641 static void fts3EvalAllocateReaders(
115642 Fts3Cursor *pCsr, /* FTS cursor handle */
115643 Fts3Expr *pExpr, /* Allocate readers for this expression */
115644 int *pnToken, /* OUT: Total number of tokens in phrase. */
115645 int *pnOr, /* OUT: Total number of OR nodes in expr. */
115646 int *pRc /* IN/OUT: Error code */
115647 ){
115648 if( pExpr && SQLITE_OK==*pRc ){
115649 if( pExpr->eType==FTSQUERY_PHRASE ){
115650 int i;
115651 int nToken = pExpr->pPhrase->nToken;
115652 *pnToken += nToken;
115653 for(i=0; i<nToken; i++){
115654 Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
115655 int rc = fts3TermSegReaderCursor(pCsr,
115656 pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
115657 );
115658 if( rc!=SQLITE_OK ){
115659 *pRc = rc;
115660 return;
@@ -115174,16 +115668,24 @@
115668 fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
115669 }
115670 }
115671 }
115672
115673 /*
115674 ** Arguments pList/nList contain the doclist for token iToken of phrase p.
115675 ** It is merged into the main doclist stored in p->doclist.aAll/nAll.
115676 **
115677 ** This function assumes that pList points to a buffer allocated using
115678 ** sqlite3_malloc(). This function takes responsibility for eventually
115679 ** freeing the buffer.
115680 */
115681 static void fts3EvalPhraseMergeToken(
115682 Fts3Table *pTab, /* FTS Table pointer */
115683 Fts3Phrase *p, /* Phrase to merge pList/nList into */
115684 int iToken, /* Token pList/nList corresponds to */
115685 char *pList, /* Pointer to doclist */
115686 int nList /* Number of bytes in pList */
115687 ){
115688 assert( iToken!=p->iDoclistToken );
115689
115690 if( pList==0 ){
115691 sqlite3_free(p->doclist.aAll);
@@ -115228,13 +115730,19 @@
115730 }
115731
115732 if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
115733 }
115734
115735 /*
115736 ** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
115737 ** does not take deferred tokens into account.
115738 **
115739 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
115740 */
115741 static int fts3EvalPhraseLoad(
115742 Fts3Cursor *pCsr, /* FTS Cursor handle */
115743 Fts3Phrase *p /* Phrase object */
115744 ){
115745 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115746 int iToken;
115747 int rc = SQLITE_OK;
115748
@@ -115243,11 +115751,11 @@
115751 assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
115752
115753 if( pToken->pSegcsr ){
115754 int nThis = 0;
115755 char *pThis = 0;
115756 rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
115757 if( rc==SQLITE_OK ){
115758 fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
115759 }
115760 }
115761 assert( pToken->pSegcsr==0 );
@@ -115254,18 +115762,26 @@
115762 }
115763
115764 return rc;
115765 }
115766
115767 /*
115768 ** This function is called on each phrase after the position lists for
115769 ** any deferred tokens have been loaded into memory. It updates the phrases
115770 ** current position list to include only those positions that are really
115771 ** instances of the phrase (after considering deferred tokens). If this
115772 ** means that the phrase does not appear in the current row, doclist.pList
115773 ** and doclist.nList are both zeroed.
115774 **
115775 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
115776 */
115777 static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
115778 int iToken; /* Used to iterate through phrase tokens */
115779 int rc = SQLITE_OK; /* Return code */
115780 char *aPoslist = 0; /* Position list for deferred tokens */
115781 int nPoslist = 0; /* Number of bytes in aPoslist */
115782 int iPrev = -1; /* Token number of previous deferred token */
 
 
115783
115784 assert( pPhrase->doclist.bFreeList==0 );
115785
115786 for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
115787 Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -115307,10 +115823,11 @@
115823 iPrev = iToken;
115824 }
115825 }
115826
115827 if( iPrev>=0 ){
115828 int nMaxUndeferred = pPhrase->iDoclistToken;
115829 if( nMaxUndeferred<0 ){
115830 pPhrase->doclist.pList = aPoslist;
115831 pPhrase->doclist.nList = nPoslist;
115832 pPhrase->doclist.iDocid = pCsr->iPrevId;
115833 pPhrase->doclist.bFreeList = 1;
@@ -115355,13 +115872,19 @@
115872 /*
115873 ** This function is called for each Fts3Phrase in a full-text query
115874 ** expression to initialize the mechanism for returning rows. Once this
115875 ** function has been called successfully on an Fts3Phrase, it may be
115876 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
115877 **
115878 ** If parameter bOptOk is true, then the phrase may (or may not) use the
115879 ** incremental loading strategy. Otherwise, the entire doclist is loaded into
115880 ** memory within this call.
115881 **
115882 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
115883 */
115884 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
115885 int rc; /* Error code */
115886 Fts3PhraseToken *pFirst = &p->aToken[0];
115887 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115888
115889 if( pCsr->bDesc==pTab->bDescIdx
115890 && bOptOk==1
@@ -115385,11 +115908,17 @@
115908 return rc;
115909 }
115910
115911 /*
115912 ** This function is used to iterate backwards (from the end to start)
115913 ** through doclists. It is used by this module to iterate through phrase
115914 ** doclists in reverse and by the fts3_write.c module to iterate through
115915 ** pending-terms lists when writing to databases with "order=desc".
115916 **
115917 ** The doclist may be sorted in ascending (parameter bDescIdx==0) or
115918 ** descending (parameter bDescIdx==1) order of docid. Regardless, this
115919 ** function iterates from the end of the doclist to the beginning.
115920 */
115921 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
115922 int bDescIdx, /* True if the doclist is desc */
115923 char *aDoclist, /* Pointer to entire doclist */
115924 int nDoclist, /* Length of aDoclist in bytes */
@@ -115450,13 +115979,13 @@
115979 ** If there is no "next" entry and no error occurs, then *pbEof is set to
115980 ** 1 before returning. Otherwise, if no error occurs and the iterator is
115981 ** successfully advanced, *pbEof is set to 0.
115982 */
115983 static int fts3EvalPhraseNext(
115984 Fts3Cursor *pCsr, /* FTS Cursor handle */
115985 Fts3Phrase *p, /* Phrase object to advance to next docid */
115986 u8 *pbEof /* OUT: Set to 1 if EOF */
115987 ){
115988 int rc = SQLITE_OK;
115989 Fts3Doclist *pDL = &p->doclist;
115990 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
115991
@@ -115498,14 +116027,14 @@
116027 fts3PoslistCopy(0, &pIter);
116028 pDL->nList = (pIter - pDL->pList);
116029
116030 /* pIter now points just past the 0x00 that terminates the position-
116031 ** list for document pDL->iDocid. However, if this position-list was
116032 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
116033 ** point to the start of the next docid value. The following line deals
116034 ** with this case by advancing pIter past the zero-padding added by
116035 ** fts3EvalNearTrim(). */
116036 while( pIter<pEnd && *pIter==0 ) pIter++;
116037
116038 pDL->pNextDocid = pIter;
116039 assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
116040 *pbEof = 0;
@@ -115513,15 +116042,31 @@
116042 }
116043
116044 return rc;
116045 }
116046
116047 /*
116048 **
116049 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
116050 ** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
116051 ** expression. Also the Fts3Expr.bDeferred variable is set to true for any
116052 ** expressions for which all descendent tokens are deferred.
116053 **
116054 ** If parameter bOptOk is zero, then it is guaranteed that the
116055 ** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
116056 ** each phrase in the expression (subject to deferred token processing).
116057 ** Or, if bOptOk is non-zero, then one or more tokens within the expression
116058 ** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
116059 **
116060 ** If an error occurs within this function, *pRc is set to an SQLite error
116061 ** code before returning.
116062 */
116063 static void fts3EvalStartReaders(
116064 Fts3Cursor *pCsr, /* FTS Cursor handle */
116065 Fts3Expr *pExpr, /* Expression to initialize phrases in */
116066 int bOptOk, /* True to enable incremental loading */
116067 int *pRc /* IN/OUT: Error code */
116068 ){
116069 if( pExpr && SQLITE_OK==*pRc ){
116070 if( pExpr->eType==FTSQUERY_PHRASE ){
116071 int i;
116072 int nToken = pExpr->pPhrase->nToken;
@@ -115536,27 +116081,46 @@
116081 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
116082 }
116083 }
116084 }
116085
116086 /*
116087 ** An array of the following structures is assembled as part of the process
116088 ** of selecting tokens to defer before the query starts executing (as part
116089 ** of the xFilter() method). There is one element in the array for each
116090 ** token in the FTS expression.
116091 **
116092 ** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
116093 ** to phrases that are connected only by AND and NEAR operators (not OR or
116094 ** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
116095 ** separately. The root of a tokens AND/NEAR cluster is stored in
116096 ** Fts3TokenAndCost.pRoot.
116097 */
116098 typedef struct Fts3TokenAndCost Fts3TokenAndCost;
116099 struct Fts3TokenAndCost {
116100 Fts3Phrase *pPhrase; /* The phrase the token belongs to */
116101 int iToken; /* Position of token in phrase */
116102 Fts3PhraseToken *pToken; /* The token itself */
116103 Fts3Expr *pRoot; /* Root of NEAR/AND cluster */
116104 int nOvfl; /* Number of overflow pages to load doclist */
116105 int iCol; /* The column the token must match */
116106 };
116107
116108 /*
116109 ** This function is used to populate an allocated Fts3TokenAndCost array.
116110 **
116111 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
116112 ** Otherwise, if an error occurs during execution, *pRc is set to an
116113 ** SQLite error code.
116114 */
116115 static void fts3EvalTokenCosts(
116116 Fts3Cursor *pCsr, /* FTS Cursor handle */
116117 Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */
116118 Fts3Expr *pExpr, /* Expression to consider */
116119 Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */
116120 Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */
116121 int *pRc /* IN/OUT: Error code */
116122 ){
116123 if( *pRc==SQLITE_OK && pExpr ){
116124 if( pExpr->eType==FTSQUERY_PHRASE ){
116125 Fts3Phrase *pPhrase = pExpr->pPhrase;
116126 int i;
@@ -115584,23 +116148,34 @@
116148 fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
116149 }
116150 }
116151 }
116152
116153 /*
116154 ** Determine the average document (row) size in pages. If successful,
116155 ** write this value to *pnPage and return SQLITE_OK. Otherwise, return
116156 ** an SQLite error code.
116157 **
116158 ** The average document size in pages is calculated by first calculating
116159 ** determining the average size in bytes, B. If B is less than the amount
116160 ** of data that will fit on a single leaf page of an intkey table in
116161 ** this database, then the average docsize is 1. Otherwise, it is 1 plus
116162 ** the number of overflow pages consumed by a record B bytes in size.
116163 */
116164 static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
116165 if( pCsr->nRowAvg==0 ){
116166 /* The average document size, which is required to calculate the cost
116167 ** of each doclist, has not yet been determined. Read the required
116168 ** data from the %_stat table to calculate it.
116169 **
116170 ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
116171 ** varints, where nCol is the number of columns in the FTS3 table.
116172 ** The first varint is the number of documents currently stored in
116173 ** the table. The following nCol varints contain the total amount of
116174 ** data stored in all rows of each column of the table, from left
116175 ** to right.
116176 */
116177 int rc;
116178 Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
116179 sqlite3_stmt *pStmt;
116180 sqlite3_int64 nDoc = 0;
116181 sqlite3_int64 nByte = 0;
@@ -115631,109 +116206,151 @@
116206
116207 *pnPage = pCsr->nRowAvg;
116208 return SQLITE_OK;
116209 }
116210
116211 /*
116212 ** This function is called to select the tokens (if any) that will be
116213 ** deferred. The array aTC[] has already been populated when this is
116214 ** called.
116215 **
116216 ** This function is called once for each AND/NEAR cluster in the
116217 ** expression. Each invocation determines which tokens to defer within
116218 ** the cluster with root node pRoot. See comments above the definition
116219 ** of struct Fts3TokenAndCost for more details.
116220 **
116221 ** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
116222 ** called on each token to defer. Otherwise, an SQLite error code is
116223 ** returned.
116224 */
116225 static int fts3EvalSelectDeferred(
116226 Fts3Cursor *pCsr, /* FTS Cursor handle */
116227 Fts3Expr *pRoot, /* Consider tokens with this root node */
116228 Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */
116229 int nTC /* Number of entries in aTC[] */
116230 ){
 
 
 
116231 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116232 int nDocSize = 0; /* Number of pages per doc loaded */
116233 int rc = SQLITE_OK; /* Return code */
116234 int ii; /* Iterator variable for various purposes */
116235 int nOvfl = 0; /* Total overflow pages used by doclists */
116236 int nToken = 0; /* Total number of tokens in cluster */
116237
116238 int nMinEst = 0; /* The minimum count for any phrase so far. */
116239 int nLoad4 = 1; /* (Phrases that will be loaded)^4. */
116240
116241 /* Count the tokens in this AND/NEAR cluster. If none of the doclists
116242 ** associated with the tokens spill onto overflow pages, or if there is
116243 ** only 1 token, exit early. No tokens to defer in this case. */
116244 for(ii=0; ii<nTC; ii++){
116245 if( aTC[ii].pRoot==pRoot ){
116246 nOvfl += aTC[ii].nOvfl;
116247 nToken++;
116248 }
116249 }
116250 if( nOvfl==0 || nToken<2 ) return SQLITE_OK;
116251
116252 /* Obtain the average docsize (in pages). */
116253 rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
116254 assert( rc!=SQLITE_OK || nDocSize>0 );
116255
116256
116257 /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
116258 ** of the number of overflow pages that will be loaded by the pager layer
116259 ** to retrieve the entire doclist for the token from the full-text index.
116260 ** Load the doclists for tokens that are either:
116261 **
116262 ** a. The cheapest token in the entire query (i.e. the one visited by the
116263 ** first iteration of this loop), or
116264 **
116265 ** b. Part of a multi-token phrase.
116266 **
116267 ** After each token doclist is loaded, merge it with the others from the
116268 ** same phrase and count the number of documents that the merged doclist
116269 ** contains. Set variable "nMinEst" to the smallest number of documents in
116270 ** any phrase doclist for which 1 or more token doclists have been loaded.
116271 ** Let nOther be the number of other phrases for which it is certain that
116272 ** one or more tokens will not be deferred.
116273 **
116274 ** Then, for each token, defer it if loading the doclist would result in
116275 ** loading N or more overflow pages into memory, where N is computed as:
116276 **
116277 ** (nMinEst + 4^nOther - 1) / (4^nOther)
116278 */
116279 for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
116280 int iTC; /* Used to iterate through aTC[] array. */
116281 Fts3TokenAndCost *pTC = 0; /* Set to cheapest remaining token. */
116282
116283 /* Set pTC to point to the cheapest remaining token. */
116284 for(iTC=0; iTC<nTC; iTC++){
116285 if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
116286 && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
116287 ){
116288 pTC = &aTC[iTC];
116289 }
116290 }
116291 assert( pTC );
116292
116293 if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
116294 /* The number of overflow pages to load for this (and therefore all
116295 ** subsequent) tokens is greater than the estimated number of pages
116296 ** that will be loaded if all subsequent tokens are deferred.
116297 */
116298 Fts3PhraseToken *pToken = pTC->pToken;
116299 rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
116300 fts3SegReaderCursorFree(pToken->pSegcsr);
116301 pToken->pSegcsr = 0;
116302 }else{
116303 nLoad4 = nLoad4*4;
116304 if( ii==0 || pTC->pPhrase->nToken>1 ){
116305 /* Either this is the cheapest token in the entire query, or it is
116306 ** part of a multi-token phrase. Either way, the entire doclist will
116307 ** (eventually) be loaded into memory. It may as well be now. */
116308 Fts3PhraseToken *pToken = pTC->pToken;
116309 int nList = 0;
116310 char *pList = 0;
116311 rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
116312 assert( rc==SQLITE_OK || pList==0 );
 
116313 if( rc==SQLITE_OK ){
116314 int nCount;
116315 fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
116316 nCount = fts3DoclistCountDocids(
116317 pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
116318 );
116319 if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
116320 }
116321 }
 
 
 
 
 
 
 
 
116322 }
116323 pTC->pToken = 0;
116324 }
116325
116326 return rc;
116327 }
116328
116329 /*
116330 ** This function is called from within the xFilter method. It initializes
116331 ** the full-text query currently stored in pCsr->pExpr. To iterate through
116332 ** the results of a query, the caller does:
116333 **
116334 ** fts3EvalStart(pCsr);
116335 ** while( 1 ){
116336 ** fts3EvalNext(pCsr);
116337 ** if( pCsr->bEof ) break;
116338 ** ... return row pCsr->iPrevId to the caller ...
116339 ** }
116340 */
116341 static int fts3EvalStart(Fts3Cursor *pCsr){
116342 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
116343 int rc = SQLITE_OK;
116344 int nToken = 0;
116345 int nOr = 0;
116346
116347 /* Allocate a MultiSegReader for each token in the expression. */
116348 fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
116349
116350 /* Determine which, if any, tokens in the expression should be deferred. */
116351 if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116352 Fts3TokenAndCost *aTC;
116353 Fts3Expr **apOr;
116354 aTC = (Fts3TokenAndCost *)sqlite3_malloc(
116355 sizeof(Fts3TokenAndCost) * nToken
116356 + sizeof(Fts3Expr *) * nOr * 2
@@ -115745,11 +116362,11 @@
116362 }else{
116363 int ii;
116364 Fts3TokenAndCost *pTC = aTC;
116365 Fts3Expr **ppOr = apOr;
116366
116367 fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
116368 nToken = pTC-aTC;
116369 nOr = ppOr-apOr;
116370
116371 if( rc==SQLITE_OK ){
116372 rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
@@ -115760,25 +116377,50 @@
116377
116378 sqlite3_free(aTC);
116379 }
116380 }
116381
116382 fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
116383 return rc;
116384 }
116385
116386 /*
116387 ** Invalidate the current position list for phrase pPhrase.
116388 */
116389 static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
116390 if( pPhrase->doclist.bFreeList ){
116391 sqlite3_free(pPhrase->doclist.pList);
116392 }
116393 pPhrase->doclist.pList = 0;
116394 pPhrase->doclist.nList = 0;
116395 pPhrase->doclist.bFreeList = 0;
116396 }
116397
116398 /*
116399 ** This function is called to edit the position list associated with
116400 ** the phrase object passed as the fifth argument according to a NEAR
116401 ** condition. For example:
116402 **
116403 ** abc NEAR/5 "def ghi"
116404 **
116405 ** Parameter nNear is passed the NEAR distance of the expression (5 in
116406 ** the example above). When this function is called, *paPoslist points to
116407 ** the position list, and *pnToken is the number of phrase tokens in, the
116408 ** phrase on the other side of the NEAR operator to pPhrase. For example,
116409 ** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
116410 ** the position list associated with phrase "abc".
116411 **
116412 ** All positions in the pPhrase position list that are not sufficiently
116413 ** close to a position in the *paPoslist position list are removed. If this
116414 ** leaves 0 positions, zero is returned. Otherwise, non-zero.
116415 **
116416 ** Before returning, *paPoslist is set to point to the position lsit
116417 ** associated with pPhrase. And *pnToken is set to the number of tokens in
116418 ** pPhrase.
116419 */
116420 static int fts3EvalNearTrim(
116421 int nNear, /* NEAR distance. As in "NEAR/nNear". */
116422 char *aTmp, /* Temporary space to use */
116423 char **paPoslist, /* IN/OUT: Position list */
116424 int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
116425 Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
116426 ){
@@ -115806,10 +116448,176 @@
116448 }
116449
116450 return res;
116451 }
116452
116453 /*
116454 ** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
116455 ** Otherwise, it advances the expression passed as the second argument to
116456 ** point to the next matching row in the database. Expressions iterate through
116457 ** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
116458 ** or descending if it is non-zero.
116459 **
116460 ** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
116461 ** successful, the following variables in pExpr are set:
116462 **
116463 ** Fts3Expr.bEof (non-zero if EOF - there is no next row)
116464 ** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row)
116465 **
116466 ** If the expression is of type FTSQUERY_PHRASE, and the expression is not
116467 ** at EOF, then the following variables are populated with the position list
116468 ** for the phrase for the visited row:
116469 **
116470 ** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes)
116471 ** FTs3Expr.pPhrase->doclist.pList (pointer to position list)
116472 **
116473 ** It says above that this function advances the expression to the next
116474 ** matching row. This is usually true, but there are the following exceptions:
116475 **
116476 ** 1. Deferred tokens are not taken into account. If a phrase consists
116477 ** entirely of deferred tokens, it is assumed to match every row in
116478 ** the db. In this case the position-list is not populated at all.
116479 **
116480 ** Or, if a phrase contains one or more deferred tokens and one or
116481 ** more non-deferred tokens, then the expression is advanced to the
116482 ** next possible match, considering only non-deferred tokens. In other
116483 ** words, if the phrase is "A B C", and "B" is deferred, the expression
116484 ** is advanced to the next row that contains an instance of "A * C",
116485 ** where "*" may match any single token. The position list in this case
116486 ** is populated as for "A * C" before returning.
116487 **
116488 ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
116489 ** advanced to point to the next row that matches "x AND y".
116490 **
116491 ** See fts3EvalTestDeferredAndNear() for details on testing if a row is
116492 ** really a match, taking into account deferred tokens and NEAR operators.
116493 */
116494 static void fts3EvalNextRow(
116495 Fts3Cursor *pCsr, /* FTS Cursor handle */
116496 Fts3Expr *pExpr, /* Expr. to advance to next matching row */
116497 int *pRc /* IN/OUT: Error code */
116498 ){
116499 if( *pRc==SQLITE_OK ){
116500 int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */
116501 assert( pExpr->bEof==0 );
116502 pExpr->bStart = 1;
116503
116504 switch( pExpr->eType ){
116505 case FTSQUERY_NEAR:
116506 case FTSQUERY_AND: {
116507 Fts3Expr *pLeft = pExpr->pLeft;
116508 Fts3Expr *pRight = pExpr->pRight;
116509 assert( !pLeft->bDeferred || !pRight->bDeferred );
116510
116511 if( pLeft->bDeferred ){
116512 /* LHS is entirely deferred. So we assume it matches every row.
116513 ** Advance the RHS iterator to find the next row visited. */
116514 fts3EvalNextRow(pCsr, pRight, pRc);
116515 pExpr->iDocid = pRight->iDocid;
116516 pExpr->bEof = pRight->bEof;
116517 }else if( pRight->bDeferred ){
116518 /* RHS is entirely deferred. So we assume it matches every row.
116519 ** Advance the LHS iterator to find the next row visited. */
116520 fts3EvalNextRow(pCsr, pLeft, pRc);
116521 pExpr->iDocid = pLeft->iDocid;
116522 pExpr->bEof = pLeft->bEof;
116523 }else{
116524 /* Neither the RHS or LHS are deferred. */
116525 fts3EvalNextRow(pCsr, pLeft, pRc);
116526 fts3EvalNextRow(pCsr, pRight, pRc);
116527 while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
116528 sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
116529 if( iDiff==0 ) break;
116530 if( iDiff<0 ){
116531 fts3EvalNextRow(pCsr, pLeft, pRc);
116532 }else{
116533 fts3EvalNextRow(pCsr, pRight, pRc);
116534 }
116535 }
116536 pExpr->iDocid = pLeft->iDocid;
116537 pExpr->bEof = (pLeft->bEof || pRight->bEof);
116538 }
116539 break;
116540 }
116541
116542 case FTSQUERY_OR: {
116543 Fts3Expr *pLeft = pExpr->pLeft;
116544 Fts3Expr *pRight = pExpr->pRight;
116545 sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
116546
116547 assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
116548 assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
116549
116550 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
116551 fts3EvalNextRow(pCsr, pLeft, pRc);
116552 }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
116553 fts3EvalNextRow(pCsr, pRight, pRc);
116554 }else{
116555 fts3EvalNextRow(pCsr, pLeft, pRc);
116556 fts3EvalNextRow(pCsr, pRight, pRc);
116557 }
116558
116559 pExpr->bEof = (pLeft->bEof && pRight->bEof);
116560 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
116561 if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
116562 pExpr->iDocid = pLeft->iDocid;
116563 }else{
116564 pExpr->iDocid = pRight->iDocid;
116565 }
116566
116567 break;
116568 }
116569
116570 case FTSQUERY_NOT: {
116571 Fts3Expr *pLeft = pExpr->pLeft;
116572 Fts3Expr *pRight = pExpr->pRight;
116573
116574 if( pRight->bStart==0 ){
116575 fts3EvalNextRow(pCsr, pRight, pRc);
116576 assert( *pRc!=SQLITE_OK || pRight->bStart );
116577 }
116578
116579 fts3EvalNextRow(pCsr, pLeft, pRc);
116580 if( pLeft->bEof==0 ){
116581 while( !*pRc
116582 && !pRight->bEof
116583 && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
116584 ){
116585 fts3EvalNextRow(pCsr, pRight, pRc);
116586 }
116587 }
116588 pExpr->iDocid = pLeft->iDocid;
116589 pExpr->bEof = pLeft->bEof;
116590 break;
116591 }
116592
116593 default: {
116594 Fts3Phrase *pPhrase = pExpr->pPhrase;
116595 fts3EvalInvalidatePoslist(pPhrase);
116596 *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
116597 pExpr->iDocid = pPhrase->doclist.iDocid;
116598 break;
116599 }
116600 }
116601 }
116602 }
116603
116604 /*
116605 ** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
116606 ** cluster, then this function returns 1 immediately.
116607 **
116608 ** Otherwise, it checks if the current row really does match the NEAR
116609 ** expression, using the data currently stored in the position lists
116610 ** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
116611 **
116612 ** If the current row is a match, the position list associated with each
116613 ** phrase in the NEAR expression is edited in place to contain only those
116614 ** phrase instances sufficiently close to their peers to satisfy all NEAR
116615 ** constraints. In this case it returns 1. If the NEAR expression does not
116616 ** match the current row, 0 is returned. The position lists may or may not
116617 ** be edited if 0 is returned.
116618 */
116619 static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
116620 int res = 1;
116621
116622 /* The following block runs if pExpr is the root of a NEAR query.
116623 ** For example, the query:
@@ -115827,11 +116635,11 @@
116635 ** | |
116636 ** "w" "x"
116637 **
116638 ** The right-hand child of a NEAR node is always a phrase. The
116639 ** left-hand child may be either a phrase or a NEAR node. There are
116640 ** no exceptions to this - it's the way the parser in fts3_expr.c works.
116641 */
116642 if( *pRc==SQLITE_OK
116643 && pExpr->eType==FTSQUERY_NEAR
116644 && pExpr->bEof==0
116645 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
@@ -115854,21 +116662,21 @@
116662 int nToken = p->pPhrase->nToken;
116663
116664 for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
116665 Fts3Phrase *pPhrase = p->pRight->pPhrase;
116666 int nNear = p->nNear;
116667 res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
116668 }
116669
116670 aPoslist = pExpr->pRight->pPhrase->doclist.pList;
116671 nToken = pExpr->pRight->pPhrase->nToken;
116672 for(p=pExpr->pLeft; p && res; p=p->pLeft){
116673 int nNear = p->pParent->nNear;
116674 Fts3Phrase *pPhrase = (
116675 p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
116676 );
116677 res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
116678 }
116679 }
116680
116681 sqlite3_free(aTmp);
116682 }
@@ -115875,132 +116683,33 @@
116683
116684 return res;
116685 }
116686
116687 /*
116688 ** This function is a helper function for fts3EvalTestDeferredAndNear().
116689 ** Assuming no error occurs or has occurred, It returns non-zero if the
116690 ** expression passed as the second argument matches the row that pCsr
116691 ** currently points to, or zero if it does not.
116692 **
116693 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
116694 ** If an error occurs during execution of this function, *pRc is set to
116695 ** the appropriate SQLite error code. In this case the returned value is
116696 ** undefined.
116697 */
116698 static int fts3EvalTestExpr(
116699 Fts3Cursor *pCsr, /* FTS cursor handle */
116700 Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
116701 int *pRc /* IN/OUT: Error code */
116702 ){
116703 int bHit = 1; /* Return value */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116704 if( *pRc==SQLITE_OK ){
116705 switch( pExpr->eType ){
116706 case FTSQUERY_NEAR:
116707 case FTSQUERY_AND:
116708 bHit = (
116709 fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
116710 && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
116711 && fts3EvalNearTest(pExpr, pRc)
116712 );
116713
116714 /* If the NEAR expression does not match any rows, zero the doclist for
116715 ** all phrases involved in the NEAR. This is because the snippet(),
@@ -116022,31 +116731,31 @@
116731 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
116732 ){
116733 Fts3Expr *p;
116734 for(p=pExpr; p->pPhrase==0; p=p->pLeft){
116735 if( p->pRight->iDocid==pCsr->iPrevId ){
116736 fts3EvalInvalidatePoslist(p->pRight->pPhrase);
116737 }
116738 }
116739 if( p->iDocid==pCsr->iPrevId ){
116740 fts3EvalInvalidatePoslist(p->pPhrase);
116741 }
116742 }
116743
116744 break;
116745
116746 case FTSQUERY_OR: {
116747 int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
116748 int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
116749 bHit = bHit1 || bHit2;
116750 break;
116751 }
116752
116753 case FTSQUERY_NOT:
116754 bHit = (
116755 fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
116756 && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
116757 );
116758 break;
116759
116760 default: {
116761 if( pCsr->pDeferred
@@ -116053,11 +116762,11 @@
116762 && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
116763 ){
116764 Fts3Phrase *pPhrase = pExpr->pPhrase;
116765 assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
116766 if( pExpr->bDeferred ){
116767 fts3EvalInvalidatePoslist(pPhrase);
116768 }
116769 *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
116770 bHit = (pPhrase->doclist.pList!=0);
116771 pExpr->iDocid = pCsr->iPrevId;
116772 }else{
@@ -116069,31 +116778,53 @@
116778 }
116779 return bHit;
116780 }
116781
116782 /*
116783 ** This function is called as the second part of each xNext operation when
116784 ** iterating through the results of a full-text query. At this point the
116785 ** cursor points to a row that matches the query expression, with the
116786 ** following caveats:
116787 **
116788 ** * Up until this point, "NEAR" operators in the expression have been
116789 ** treated as "AND".
116790 **
116791 ** * Deferred tokens have not yet been considered.
116792 **
116793 ** If *pRc is not SQLITE_OK when this function is called, it immediately
116794 ** returns 0. Otherwise, it tests whether or not after considering NEAR
116795 ** operators and deferred tokens the current row is still a match for the
116796 ** expression. It returns 1 if both of the following are true:
116797 **
116798 ** 1. *pRc is SQLITE_OK when this function returns, and
116799 **
116800 ** 2. After scanning the current FTS table row for the deferred tokens,
116801 ** it is determined that the row does *not* match the query.
116802 **
116803 ** Or, if no error occurs and it seems the current row does match the FTS
116804 ** query, return 0.
116805 */
116806 static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
116807 int rc = *pRc;
116808 int bMiss = 0;
116809 if( rc==SQLITE_OK ){
116810
116811 /* If there are one or more deferred tokens, load the current row into
116812 ** memory and scan it to determine the position list for each deferred
116813 ** token. Then, see if this row is really a match, considering deferred
116814 ** tokens and NEAR operators (neither of which were taken into account
116815 ** earlier, by fts3EvalNextRow()).
116816 */
116817 if( pCsr->pDeferred ){
116818 rc = fts3CursorSeek(0, pCsr);
116819 if( rc==SQLITE_OK ){
116820 rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
116821 }
116822 }
116823 bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
116824
116825 /* Free the position-lists accumulated for each deferred token above. */
116826 sqlite3Fts3FreeDeferredDoclists(pCsr);
116827 *pRc = rc;
116828 }
116829 return (rc==SQLITE_OK && bMiss);
116830 }
@@ -116100,11 +116831,11 @@
116831
116832 /*
116833 ** Advance to the next document that matches the FTS expression in
116834 ** Fts3Cursor.pExpr.
116835 */
116836 static int fts3EvalNext(Fts3Cursor *pCsr){
116837 int rc = SQLITE_OK; /* Return Code */
116838 Fts3Expr *pExpr = pCsr->pExpr;
116839 assert( pCsr->isEof==0 );
116840 if( pExpr==0 ){
116841 pCsr->isEof = 1;
@@ -116112,23 +116843,23 @@
116843 do {
116844 if( pCsr->isRequireSeek==0 ){
116845 sqlite3_reset(pCsr->pStmt);
116846 }
116847 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116848 fts3EvalNextRow(pCsr, pExpr, &rc);
116849 pCsr->isEof = pExpr->bEof;
116850 pCsr->isRequireSeek = 1;
116851 pCsr->isMatchinfoNeeded = 1;
116852 pCsr->iPrevId = pExpr->iDocid;
116853 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
116854 }
116855 return rc;
116856 }
116857
116858 /*
116859 ** Restart interation for expression pExpr so that the next call to
116860 ** fts3EvalNext() visits the first row. Do not allow incremental
116861 ** loading or merging of phrase doclists for this iteration.
116862 **
116863 ** If *pRc is other than SQLITE_OK when this function is called, it is
116864 ** a no-op. If an error occurs within this function, *pRc is set to an
116865 ** SQLite error code before returning.
@@ -116140,11 +116871,11 @@
116871 ){
116872 if( pExpr && *pRc==SQLITE_OK ){
116873 Fts3Phrase *pPhrase = pExpr->pPhrase;
116874
116875 if( pPhrase ){
116876 fts3EvalInvalidatePoslist(pPhrase);
116877 if( pPhrase->bIncr ){
116878 assert( pPhrase->nToken==1 );
116879 assert( pPhrase->aToken[0].pSegcsr );
116880 sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
116881 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
@@ -116256,18 +116987,18 @@
116987 /* Ensure the %_content statement is reset. */
116988 if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
116989 assert( sqlite3_data_count(pCsr->pStmt)==0 );
116990
116991 /* Advance to the next document */
116992 fts3EvalNextRow(pCsr, pRoot, &rc);
116993 pCsr->isEof = pRoot->bEof;
116994 pCsr->isRequireSeek = 1;
116995 pCsr->isMatchinfoNeeded = 1;
116996 pCsr->iPrevId = pRoot->iDocid;
116997 }while( pCsr->isEof==0
116998 && pRoot->eType==FTSQUERY_NEAR
116999 && fts3EvalTestDeferredAndNear(pCsr, &rc)
117000 );
117001
117002 if( rc==SQLITE_OK && pCsr->isEof==0 ){
117003 fts3EvalUpdateCounts(pRoot);
117004 }
@@ -116285,14 +117016,14 @@
117016 **
117017 ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
117018 */
117019 fts3EvalRestart(pCsr, pRoot, &rc);
117020 do {
117021 fts3EvalNextRow(pCsr, pRoot, &rc);
117022 assert( pRoot->bEof==0 );
117023 }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
117024 fts3EvalTestDeferredAndNear(pCsr, &rc);
117025 }
117026 }
117027 return rc;
117028 }
117029
@@ -116419,18 +117150,32 @@
117150 */
117151 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
117152 if( pPhrase ){
117153 int i;
117154 sqlite3_free(pPhrase->doclist.aAll);
117155 fts3EvalInvalidatePoslist(pPhrase);
117156 memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
117157 for(i=0; i<pPhrase->nToken; i++){
117158 fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
117159 pPhrase->aToken[i].pSegcsr = 0;
117160 }
117161 }
117162 }
117163
117164 #if !SQLITE_CORE
117165 /*
117166 ** Initialize API pointer table, if required.
117167 */
117168 SQLITE_API int sqlite3_extension_init(
117169 sqlite3 *db,
117170 char **pzErrMsg,
117171 const sqlite3_api_routines *pApi
117172 ){
117173 SQLITE_EXTENSION_INIT2(pApi)
117174 return sqlite3Fts3Init(db);
117175 }
117176 #endif
117177
117178 #endif
117179
117180 /************** End of fts3.c ************************************************/
117181 /************** Begin file fts3_aux.c ****************************************/
@@ -118917,14 +119662,10 @@
119662 ** (in which case SQLITE_CORE is not defined), or
119663 **
119664 ** * The FTS3 module is being built into the core of
119665 ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
119666 */
 
 
 
 
119667 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
119668
119669
119670 /*
119671 ** Implementation of the SQL scalar function for accessing the underlying
119672
+21 -4
--- 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-24 11:29:51 9b191bb4c7c1e1b12b188c0b3eee1f8f587887c8"
110
+#define SQLITE_VERSION "3.7.8"
111
+#define SQLITE_VERSION_NUMBER 3007008
112
+#define SQLITE_SOURCE_ID "2011-07-19 18:29:00 ed5f0aad6b21066bacd01521e82c22e96991f400"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -739,20 +739,37 @@
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
+**
744761
*/
745762
#define SQLITE_FCNTL_LOCKSTATE 1
746763
#define SQLITE_GET_LOCKPROXYFILE 2
747764
#define SQLITE_SET_LOCKPROXYFILE 3
748765
#define SQLITE_LAST_ERRNO 4
749766
#define SQLITE_FCNTL_SIZE_HINT 5
750767
#define SQLITE_FCNTL_CHUNK_SIZE 6
751768
#define SQLITE_FCNTL_FILE_POINTER 7
752769
#define SQLITE_FCNTL_SYNC_OMITTED 8
753
-
770
+#define SQLITE_FCNTL_WIN32_AV_RETRY 9
754771
755772
/*
756773
** CAPI3REF: Mutex Handle
757774
**
758775
** The mutex module within SQLite defines [sqlite3_mutex] to be an
759776
--- 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-24 11:29:51 9b191bb4c7c1e1b12b188c0b3eee1f8f587887c8"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -739,20 +739,37 @@
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
759
--- 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-07-19 18:29:00 ed5f0aad6b21066bacd01521e82c22e96991f400"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -739,20 +739,37 @@
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 */
762 #define SQLITE_FCNTL_LOCKSTATE 1
763 #define SQLITE_GET_LOCKPROXYFILE 2
764 #define SQLITE_SET_LOCKPROXYFILE 3
765 #define SQLITE_LAST_ERRNO 4
766 #define SQLITE_FCNTL_SIZE_HINT 5
767 #define SQLITE_FCNTL_CHUNK_SIZE 6
768 #define SQLITE_FCNTL_FILE_POINTER 7
769 #define SQLITE_FCNTL_SYNC_OMITTED 8
770 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
771
772 /*
773 ** CAPI3REF: Mutex Handle
774 **
775 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
776
+278 -29
--- src/tar.c
+++ src/tar.c
@@ -27,31 +27,253 @@
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
+ int n;
207
+ blob_reset(&tball.pax);
208
+ blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
209
+ zName = blob_buffer(&tball.pax);
210
+ nName = blob_size(&tball.pax);
211
+ }
212
+
213
+ /* find the split position */
214
+ split = find_split_pos(zName, nName);
215
+
216
+ /* extract a name, truncate if needed */
217
+ padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
218
+
219
+ /* extract a prefix field, truncate when needed */
220
+ padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split-1 : 0));
221
+}
222
+
223
+
224
+/*
225
+** add a Pax Interchange header to the scratch buffer
226
+**
227
+** format: <length> <key>=<value>\n
228
+** the tricky part is that each header contains its own
229
+** size in decimal, counting that length.
230
+*/
231
+static void add_pax_header(
232
+ const char *zField,
233
+ const char *zValue,
234
+ int nValue
235
+){
236
+ /* calculate length without length field */
237
+ int blen = strlen(zField) + nValue + 3;
238
+ /* calculate the length of the length field */
239
+ int next10 = 1;
240
+ int n;
241
+ for(n = blen; n > 0; ){
242
+ blen++; next10 *= 10;
243
+ n /= 10;
244
+ }
245
+ /* adding the length extended the length field? */
246
+ if(blen > next10){
247
+ blen++;
248
+ }
249
+ /* build the string */
250
+ blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
251
+ /* this _must_ be right */
252
+ if(blob_size(&tball.pax) != blen){
253
+ fossil_fatal("internal error: PAX tar header has bad length");
254
+ }
255
+}
256
+
257
+
258
+/*
259
+** set the header type, calculate the checksum and output
260
+** the header
261
+*/
262
+static void cksum_and_write_header(
263
+ char cType
264
+){
265
+ unsigned int cksum = 0;
266
+ int i;
267
+ memset(&tball.aHdr[148], ' ', 8);
268
+ tball.aHdr[156] = cType;
269
+ for(i=0; i<512; i++) cksum += tball.aHdr[i];
270
+ sqlite3_snprintf(8, (char*)&tball.aHdr[148], "%07o", cksum);
271
+ tball.aHdr[155] = 0;
272
+ gzip_step((char*)tball.aHdr, 512);
273
+}
274
+
53275
54276
/*
55277
** Build a header for a file or directory and write that header
56278
** into the growing tarball.
57279
*/
@@ -59,33 +281,49 @@
59281
const char *zName, /* Name of the object */
60282
int nName, /* Number of characters in zName */
61283
int iMode, /* Mode. 0644 or 0755 */
62284
unsigned int mTime, /* File modification time */
63285
int iSize, /* Size of the object in bytes */
64
- int iType /* Type of object. 0==file. 5==directory */
286
+ char cType /* Type of object. '0'==file. '5'==directory */
65287
){
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
- }
288
+ /* set mode and modification time */
77289
sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode);
78
- sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
79290
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);
291
+
292
+ /* see if we need to output a Pax Interchange Header */
293
+ if( !is_iso646_name(zName, nName) ||
294
+ !tar_split_path(zName, nName, tball.aHdr, &tball.aHdr[345]) ){
295
+ int lastPage;
296
+ /* add a file name for interoperability with older programs */
297
+ approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 1);
298
+
299
+ /* generate the Pax Interchange path header */
300
+ blob_reset(&tball.pax);
301
+ add_pax_header("path", zName, nName);
302
+
303
+ /* set the header length, and write the header */
304
+ sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
305
+ blob_size(&tball.pax));
306
+ cksum_and_write_header('x');
307
+
308
+ /* write the Pax Interchange data */
309
+ gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
310
+ lastPage = blob_size(&tball.pax) % 512;
311
+ if( lastPage!=0 ){
312
+ gzip_step(tball.zSpaces, 512 - lastPage);
313
+ }
314
+
315
+ /* generate an approximate path for the regular header */
316
+ approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 0);
317
+ }
318
+ /* set the size */
319
+ sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
320
+
321
+ /* write the regular header */
322
+ cksum_and_write_header(cType);
86323
}
324
+
87325
88326
/*
89327
** Recursively add an directory entry for the given file if those
90328
** directories have not previously been seen.
91329
*/
@@ -95,18 +333,27 @@
95333
unsigned int mTime /* Modification time */
96334
){
97335
int i;
98336
for(i=nName-1; i>0 && zName[i]!='/'; i--){}
99337
if( i<=0 ) return;
100
- if( tball.zPrevDir[i]==0 && memcmp(tball.zPrevDir, zName, i)==0 ) return;
338
+ if( i < tball.nPrevDirAlloc && tball.zPrevDir[i]==0 &&
339
+ memcmp(tball.zPrevDir, zName, i)==0 ) return;
101340
db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%#q')", i, zName);
102341
if( sqlite3_changes(g.db)==0 ) return;
103342
tar_add_directory_of(zName, i-1, mTime);
104
- tar_add_header(zName, i, 0755, mTime, 0, 5);
343
+ tar_add_header(zName, i, 0755, mTime, 0, '5');
344
+ if( i >= tball.nPrevDirAlloc ){
345
+ int nsize = tball.nPrevDirAlloc * 2;
346
+ if(i+1 > nsize)
347
+ nsize = i+1;
348
+ tball.zPrevDir = fossil_realloc(tball.zPrevDir, nsize);
349
+ tball.nPrevDirAlloc = nsize;
350
+ }
105351
memcpy(tball.zPrevDir, zName, i);
106352
tball.zPrevDir[i] = 0;
107353
}
354
+
108355
109356
/*
110357
** Add a single file to the growing tarball.
111358
*/
112359
static void tar_add_file(
@@ -117,15 +364,13 @@
117364
){
118365
int nName = strlen(zName);
119366
int n = blob_size(pContent);
120367
int lastPage;
121368
122
- if( nName>=250 ){
123
- fossil_fatal("name too long for ustar format: \"%s\"", zName);
124
- }
369
+ /* length check moved to tar_split_path */
125370
tar_add_directory_of(zName, nName, mTime);
126
- tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, 0);
371
+ tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, '0');
127372
if( n ){
128373
gzip_step(blob_buffer(pContent), n);
129374
lastPage = n % 512;
130375
if( lastPage!=0 ){
131376
gzip_step(tball.zSpaces, 512 - lastPage);
@@ -142,10 +387,14 @@
142387
gzip_step(tball.zSpaces, 512);
143388
gzip_step(tball.zSpaces, 512);
144389
gzip_finish(pOut);
145390
fossil_free(tball.aHdr);
146391
tball.aHdr = 0;
392
+ fossil_free(tball.zPrevDir);
393
+ tball.zPrevDir = NULL;
394
+ tball.nPrevDirAlloc = 0;
395
+ blob_reset(&tball.pax);
147396
}
148397
149398
150399
/*
151400
** COMMAND: test-tarball
152401
--- src/tar.c
+++ src/tar.c
@@ -27,31 +27,253 @@
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 +281,49 @@
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 +333,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 +364,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 +387,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,253 @@
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 int n;
207 blob_reset(&tball.pax);
208 blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
209 zName = blob_buffer(&tball.pax);
210 nName = blob_size(&tball.pax);
211 }
212
213 /* find the split position */
214 split = find_split_pos(zName, nName);
215
216 /* extract a name, truncate if needed */
217 padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
218
219 /* extract a prefix field, truncate when needed */
220 padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split-1 : 0));
221 }
222
223
224 /*
225 ** add a Pax Interchange header to the scratch buffer
226 **
227 ** format: <length> <key>=<value>\n
228 ** the tricky part is that each header contains its own
229 ** size in decimal, counting that length.
230 */
231 static void add_pax_header(
232 const char *zField,
233 const char *zValue,
234 int nValue
235 ){
236 /* calculate length without length field */
237 int blen = strlen(zField) + nValue + 3;
238 /* calculate the length of the length field */
239 int next10 = 1;
240 int n;
241 for(n = blen; n > 0; ){
242 blen++; next10 *= 10;
243 n /= 10;
244 }
245 /* adding the length extended the length field? */
246 if(blen > next10){
247 blen++;
248 }
249 /* build the string */
250 blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
251 /* this _must_ be right */
252 if(blob_size(&tball.pax) != blen){
253 fossil_fatal("internal error: PAX tar header has bad length");
254 }
255 }
256
257
258 /*
259 ** set the header type, calculate the checksum and output
260 ** the header
261 */
262 static void cksum_and_write_header(
263 char cType
264 ){
265 unsigned int cksum = 0;
266 int i;
267 memset(&tball.aHdr[148], ' ', 8);
268 tball.aHdr[156] = cType;
269 for(i=0; i<512; i++) cksum += tball.aHdr[i];
270 sqlite3_snprintf(8, (char*)&tball.aHdr[148], "%07o", cksum);
271 tball.aHdr[155] = 0;
272 gzip_step((char*)tball.aHdr, 512);
273 }
274
275
276 /*
277 ** Build a header for a file or directory and write that header
278 ** into the growing tarball.
279 */
@@ -59,33 +281,49 @@
281 const char *zName, /* Name of the object */
282 int nName, /* Number of characters in zName */
283 int iMode, /* Mode. 0644 or 0755 */
284 unsigned int mTime, /* File modification time */
285 int iSize, /* Size of the object in bytes */
286 char cType /* Type of object. '0'==file. '5'==directory */
287 ){
288 /* set mode and modification time */
 
 
 
 
 
 
 
 
 
 
289 sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode);
 
290 sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime);
291
292 /* see if we need to output a Pax Interchange Header */
293 if( !is_iso646_name(zName, nName) ||
294 !tar_split_path(zName, nName, tball.aHdr, &tball.aHdr[345]) ){
295 int lastPage;
296 /* add a file name for interoperability with older programs */
297 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 1);
298
299 /* generate the Pax Interchange path header */
300 blob_reset(&tball.pax);
301 add_pax_header("path", zName, nName);
302
303 /* set the header length, and write the header */
304 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
305 blob_size(&tball.pax));
306 cksum_and_write_header('x');
307
308 /* write the Pax Interchange data */
309 gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
310 lastPage = blob_size(&tball.pax) % 512;
311 if( lastPage!=0 ){
312 gzip_step(tball.zSpaces, 512 - lastPage);
313 }
314
315 /* generate an approximate path for the regular header */
316 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 0);
317 }
318 /* set the size */
319 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
320
321 /* write the regular header */
322 cksum_and_write_header(cType);
323 }
324
325
326 /*
327 ** Recursively add an directory entry for the given file if those
328 ** directories have not previously been seen.
329 */
@@ -95,18 +333,27 @@
333 unsigned int mTime /* Modification time */
334 ){
335 int i;
336 for(i=nName-1; i>0 && zName[i]!='/'; i--){}
337 if( i<=0 ) return;
338 if( i < tball.nPrevDirAlloc && tball.zPrevDir[i]==0 &&
339 memcmp(tball.zPrevDir, zName, i)==0 ) return;
340 db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%#q')", i, zName);
341 if( sqlite3_changes(g.db)==0 ) return;
342 tar_add_directory_of(zName, i-1, mTime);
343 tar_add_header(zName, i, 0755, mTime, 0, '5');
344 if( i >= tball.nPrevDirAlloc ){
345 int nsize = tball.nPrevDirAlloc * 2;
346 if(i+1 > nsize)
347 nsize = i+1;
348 tball.zPrevDir = fossil_realloc(tball.zPrevDir, nsize);
349 tball.nPrevDirAlloc = nsize;
350 }
351 memcpy(tball.zPrevDir, zName, i);
352 tball.zPrevDir[i] = 0;
353 }
354
355
356 /*
357 ** Add a single file to the growing tarball.
358 */
359 static void tar_add_file(
@@ -117,15 +364,13 @@
364 ){
365 int nName = strlen(zName);
366 int n = blob_size(pContent);
367 int lastPage;
368
369 /* length check moved to tar_split_path */
 
 
370 tar_add_directory_of(zName, nName, mTime);
371 tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, '0');
372 if( n ){
373 gzip_step(blob_buffer(pContent), n);
374 lastPage = n % 512;
375 if( lastPage!=0 ){
376 gzip_step(tball.zSpaces, 512 - lastPage);
@@ -142,10 +387,14 @@
387 gzip_step(tball.zSpaces, 512);
388 gzip_step(tball.zSpaces, 512);
389 gzip_finish(pOut);
390 fossil_free(tball.aHdr);
391 tball.aHdr = 0;
392 fossil_free(tball.zPrevDir);
393 tball.zPrevDir = NULL;
394 tball.nPrevDirAlloc = 0;
395 blob_reset(&tball.pax);
396 }
397
398
399 /*
400 ** COMMAND: test-tarball
401
+278 -29
--- src/tar.c
+++ src/tar.c
@@ -27,31 +27,253 @@
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
+ int n;
207
+ blob_reset(&tball.pax);
208
+ blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
209
+ zName = blob_buffer(&tball.pax);
210
+ nName = blob_size(&tball.pax);
211
+ }
212
+
213
+ /* find the split position */
214
+ split = find_split_pos(zName, nName);
215
+
216
+ /* extract a name, truncate if needed */
217
+ padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
218
+
219
+ /* extract a prefix field, truncate when needed */
220
+ padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split-1 : 0));
221
+}
222
+
223
+
224
+/*
225
+** add a Pax Interchange header to the scratch buffer
226
+**
227
+** format: <length> <key>=<value>\n
228
+** the tricky part is that each header contains its own
229
+** size in decimal, counting that length.
230
+*/
231
+static void add_pax_header(
232
+ const char *zField,
233
+ const char *zValue,
234
+ int nValue
235
+){
236
+ /* calculate length without length field */
237
+ int blen = strlen(zField) + nValue + 3;
238
+ /* calculate the length of the length field */
239
+ int next10 = 1;
240
+ int n;
241
+ for(n = blen; n > 0; ){
242
+ blen++; next10 *= 10;
243
+ n /= 10;
244
+ }
245
+ /* adding the length extended the length field? */
246
+ if(blen > next10){
247
+ blen++;
248
+ }
249
+ /* build the string */
250
+ blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
251
+ /* this _must_ be right */
252
+ if(blob_size(&tball.pax) != blen){
253
+ fossil_fatal("internal error: PAX tar header has bad length");
254
+ }
255
+}
256
+
257
+
258
+/*
259
+** set the header type, calculate the checksum and output
260
+** the header
261
+*/
262
+static void cksum_and_write_header(
263
+ char cType
264
+){
265
+ unsigned int cksum = 0;
266
+ int i;
267
+ memset(&tball.aHdr[148], ' ', 8);
268
+ tball.aHdr[156] = cType;
269
+ for(i=0; i<512; i++) cksum += tball.aHdr[i];
270
+ sqlite3_snprintf(8, (char*)&tball.aHdr[148], "%07o", cksum);
271
+ tball.aHdr[155] = 0;
272
+ gzip_step((char*)tball.aHdr, 512);
273
+}
274
+
53275
54276
/*
55277
** Build a header for a file or directory and write that header
56278
** into the growing tarball.
57279
*/
@@ -59,33 +281,49 @@
59281
const char *zName, /* Name of the object */
60282
int nName, /* Number of characters in zName */
61283
int iMode, /* Mode. 0644 or 0755 */
62284
unsigned int mTime, /* File modification time */
63285
int iSize, /* Size of the object in bytes */
64
- int iType /* Type of object. 0==file. 5==directory */
286
+ char cType /* Type of object. '0'==file. '5'==directory */
65287
){
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
- }
288
+ /* set mode and modification time */
77289
sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode);
78
- sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
79290
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);
291
+
292
+ /* see if we need to output a Pax Interchange Header */
293
+ if( !is_iso646_name(zName, nName) ||
294
+ !tar_split_path(zName, nName, tball.aHdr, &tball.aHdr[345]) ){
295
+ int lastPage;
296
+ /* add a file name for interoperability with older programs */
297
+ approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 1);
298
+
299
+ /* generate the Pax Interchange path header */
300
+ blob_reset(&tball.pax);
301
+ add_pax_header("path", zName, nName);
302
+
303
+ /* set the header length, and write the header */
304
+ sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
305
+ blob_size(&tball.pax));
306
+ cksum_and_write_header('x');
307
+
308
+ /* write the Pax Interchange data */
309
+ gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
310
+ lastPage = blob_size(&tball.pax) % 512;
311
+ if( lastPage!=0 ){
312
+ gzip_step(tball.zSpaces, 512 - lastPage);
313
+ }
314
+
315
+ /* generate an approximate path for the regular header */
316
+ approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 0);
317
+ }
318
+ /* set the size */
319
+ sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
320
+
321
+ /* write the regular header */
322
+ cksum_and_write_header(cType);
86323
}
324
+
87325
88326
/*
89327
** Recursively add an directory entry for the given file if those
90328
** directories have not previously been seen.
91329
*/
@@ -95,18 +333,27 @@
95333
unsigned int mTime /* Modification time */
96334
){
97335
int i;
98336
for(i=nName-1; i>0 && zName[i]!='/'; i--){}
99337
if( i<=0 ) return;
100
- if( tball.zPrevDir[i]==0 && memcmp(tball.zPrevDir, zName, i)==0 ) return;
338
+ if( i < tball.nPrevDirAlloc && tball.zPrevDir[i]==0 &&
339
+ memcmp(tball.zPrevDir, zName, i)==0 ) return;
101340
db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%#q')", i, zName);
102341
if( sqlite3_changes(g.db)==0 ) return;
103342
tar_add_directory_of(zName, i-1, mTime);
104
- tar_add_header(zName, i, 0755, mTime, 0, 5);
343
+ tar_add_header(zName, i, 0755, mTime, 0, '5');
344
+ if( i >= tball.nPrevDirAlloc ){
345
+ int nsize = tball.nPrevDirAlloc * 2;
346
+ if(i+1 > nsize)
347
+ nsize = i+1;
348
+ tball.zPrevDir = fossil_realloc(tball.zPrevDir, nsize);
349
+ tball.nPrevDirAlloc = nsize;
350
+ }
105351
memcpy(tball.zPrevDir, zName, i);
106352
tball.zPrevDir[i] = 0;
107353
}
354
+
108355
109356
/*
110357
** Add a single file to the growing tarball.
111358
*/
112359
static void tar_add_file(
@@ -117,15 +364,13 @@
117364
){
118365
int nName = strlen(zName);
119366
int n = blob_size(pContent);
120367
int lastPage;
121368
122
- if( nName>=250 ){
123
- fossil_fatal("name too long for ustar format: \"%s\"", zName);
124
- }
369
+ /* length check moved to tar_split_path */
125370
tar_add_directory_of(zName, nName, mTime);
126
- tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, 0);
371
+ tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, '0');
127372
if( n ){
128373
gzip_step(blob_buffer(pContent), n);
129374
lastPage = n % 512;
130375
if( lastPage!=0 ){
131376
gzip_step(tball.zSpaces, 512 - lastPage);
@@ -142,10 +387,14 @@
142387
gzip_step(tball.zSpaces, 512);
143388
gzip_step(tball.zSpaces, 512);
144389
gzip_finish(pOut);
145390
fossil_free(tball.aHdr);
146391
tball.aHdr = 0;
392
+ fossil_free(tball.zPrevDir);
393
+ tball.zPrevDir = NULL;
394
+ tball.nPrevDirAlloc = 0;
395
+ blob_reset(&tball.pax);
147396
}
148397
149398
150399
/*
151400
** COMMAND: test-tarball
152401
--- src/tar.c
+++ src/tar.c
@@ -27,31 +27,253 @@
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 +281,49 @@
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 +333,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 +364,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 +387,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,253 @@
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 int n;
207 blob_reset(&tball.pax);
208 blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
209 zName = blob_buffer(&tball.pax);
210 nName = blob_size(&tball.pax);
211 }
212
213 /* find the split position */
214 split = find_split_pos(zName, nName);
215
216 /* extract a name, truncate if needed */
217 padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
218
219 /* extract a prefix field, truncate when needed */
220 padded_copy(pPrefix, USTAR_PREFIX_LEN, zName, (split > 0 ? split-1 : 0));
221 }
222
223
224 /*
225 ** add a Pax Interchange header to the scratch buffer
226 **
227 ** format: <length> <key>=<value>\n
228 ** the tricky part is that each header contains its own
229 ** size in decimal, counting that length.
230 */
231 static void add_pax_header(
232 const char *zField,
233 const char *zValue,
234 int nValue
235 ){
236 /* calculate length without length field */
237 int blen = strlen(zField) + nValue + 3;
238 /* calculate the length of the length field */
239 int next10 = 1;
240 int n;
241 for(n = blen; n > 0; ){
242 blen++; next10 *= 10;
243 n /= 10;
244 }
245 /* adding the length extended the length field? */
246 if(blen > next10){
247 blen++;
248 }
249 /* build the string */
250 blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
251 /* this _must_ be right */
252 if(blob_size(&tball.pax) != blen){
253 fossil_fatal("internal error: PAX tar header has bad length");
254 }
255 }
256
257
258 /*
259 ** set the header type, calculate the checksum and output
260 ** the header
261 */
262 static void cksum_and_write_header(
263 char cType
264 ){
265 unsigned int cksum = 0;
266 int i;
267 memset(&tball.aHdr[148], ' ', 8);
268 tball.aHdr[156] = cType;
269 for(i=0; i<512; i++) cksum += tball.aHdr[i];
270 sqlite3_snprintf(8, (char*)&tball.aHdr[148], "%07o", cksum);
271 tball.aHdr[155] = 0;
272 gzip_step((char*)tball.aHdr, 512);
273 }
274
275
276 /*
277 ** Build a header for a file or directory and write that header
278 ** into the growing tarball.
279 */
@@ -59,33 +281,49 @@
281 const char *zName, /* Name of the object */
282 int nName, /* Number of characters in zName */
283 int iMode, /* Mode. 0644 or 0755 */
284 unsigned int mTime, /* File modification time */
285 int iSize, /* Size of the object in bytes */
286 char cType /* Type of object. '0'==file. '5'==directory */
287 ){
288 /* set mode and modification time */
 
 
 
 
 
 
 
 
 
 
289 sqlite3_snprintf(8, (char*)&tball.aHdr[100], "%07o", iMode);
 
290 sqlite3_snprintf(12, (char*)&tball.aHdr[136], "%011o", mTime);
291
292 /* see if we need to output a Pax Interchange Header */
293 if( !is_iso646_name(zName, nName) ||
294 !tar_split_path(zName, nName, tball.aHdr, &tball.aHdr[345]) ){
295 int lastPage;
296 /* add a file name for interoperability with older programs */
297 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 1);
298
299 /* generate the Pax Interchange path header */
300 blob_reset(&tball.pax);
301 add_pax_header("path", zName, nName);
302
303 /* set the header length, and write the header */
304 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
305 blob_size(&tball.pax));
306 cksum_and_write_header('x');
307
308 /* write the Pax Interchange data */
309 gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
310 lastPage = blob_size(&tball.pax) % 512;
311 if( lastPage!=0 ){
312 gzip_step(tball.zSpaces, 512 - lastPage);
313 }
314
315 /* generate an approximate path for the regular header */
316 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 0);
317 }
318 /* set the size */
319 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", iSize);
320
321 /* write the regular header */
322 cksum_and_write_header(cType);
323 }
324
325
326 /*
327 ** Recursively add an directory entry for the given file if those
328 ** directories have not previously been seen.
329 */
@@ -95,18 +333,27 @@
333 unsigned int mTime /* Modification time */
334 ){
335 int i;
336 for(i=nName-1; i>0 && zName[i]!='/'; i--){}
337 if( i<=0 ) return;
338 if( i < tball.nPrevDirAlloc && tball.zPrevDir[i]==0 &&
339 memcmp(tball.zPrevDir, zName, i)==0 ) return;
340 db_multi_exec("INSERT OR IGNORE INTO dir VALUES('%#q')", i, zName);
341 if( sqlite3_changes(g.db)==0 ) return;
342 tar_add_directory_of(zName, i-1, mTime);
343 tar_add_header(zName, i, 0755, mTime, 0, '5');
344 if( i >= tball.nPrevDirAlloc ){
345 int nsize = tball.nPrevDirAlloc * 2;
346 if(i+1 > nsize)
347 nsize = i+1;
348 tball.zPrevDir = fossil_realloc(tball.zPrevDir, nsize);
349 tball.nPrevDirAlloc = nsize;
350 }
351 memcpy(tball.zPrevDir, zName, i);
352 tball.zPrevDir[i] = 0;
353 }
354
355
356 /*
357 ** Add a single file to the growing tarball.
358 */
359 static void tar_add_file(
@@ -117,15 +364,13 @@
364 ){
365 int nName = strlen(zName);
366 int n = blob_size(pContent);
367 int lastPage;
368
369 /* length check moved to tar_split_path */
 
 
370 tar_add_directory_of(zName, nName, mTime);
371 tar_add_header(zName, nName, isExe ? 0755 : 0644, mTime, n, '0');
372 if( n ){
373 gzip_step(blob_buffer(pContent), n);
374 lastPage = n % 512;
375 if( lastPage!=0 ){
376 gzip_step(tball.zSpaces, 512 - lastPage);
@@ -142,10 +387,14 @@
387 gzip_step(tball.zSpaces, 512);
388 gzip_step(tball.zSpaces, 512);
389 gzip_finish(pOut);
390 fossil_free(tball.aHdr);
391 tball.aHdr = 0;
392 fossil_free(tball.zPrevDir);
393 tball.zPrevDir = NULL;
394 tball.nPrevDirAlloc = 0;
395 blob_reset(&tball.pax);
396 }
397
398
399 /*
400 ** COMMAND: test-tarball
401
+74 -13
--- src/timeline.c
+++ src/timeline.c
@@ -107,11 +107,55 @@
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
+}
113157
114158
/*
115159
** Output a timeline in the web format given a query. The query
116160
** should return these columns:
117161
**
@@ -142,10 +186,11 @@
142186
char zPrevDate[20];
143187
GraphContext *pGraph = 0;
144188
int prevWasDivider = 0; /* True if previous output row was <hr> */
145189
int fchngQueryInit = 0; /* True if fchngQuery is initialized */
146190
Stmt fchngQuery; /* Query for file changes on check-ins */
191
+ static Stmt qbranch;
147192
148193
zPrevDate[0] = 0;
149194
mxWikiLen = db_get_int("timeline-max-comment", 0);
150195
if( db_get_boolean("timeline-block-markup", 0) ){
151196
wikiFlags = WIKI_INLINE;
@@ -157,10 +202,14 @@
157202
/* style is not moved to css, because this is
158203
** a technical div for the timeline graph
159204
*/
160205
@ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
161206
}
207
+ db_static_prepare(&qbranch,
208
+ "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
209
+ TAG_BRANCH
210
+ );
162211
163212
@ <table id="timelineTable" class="timelineTable">
164213
blob_zero(&comment);
165214
while( db_step(pQuery)==SQLITE_ROW ){
166215
int rid = db_column_int(pQuery, 0);
@@ -170,10 +219,11 @@
170219
const char *zDate = db_column_text(pQuery, 2);
171220
const char *zType = db_column_text(pQuery, 7);
172221
const char *zUser = db_column_text(pQuery, 4);
173222
const char *zTagList = db_column_text(pQuery, 8);
174223
int tagid = db_column_int(pQuery, 9);
224
+ const char *zBr = 0; /* Branch */
175225
int commentColumn = 3; /* Column containing comment text */
176226
char zTime[8];
177227
if( tagid ){
178228
if( tagid==prevTagid ){
179229
if( tmFlags & TIMELINE_BRIEF ){
@@ -208,37 +258,44 @@
208258
memcpy(zTime, &zDate[11], 5);
209259
zTime[5] = 0;
210260
@ <tr>
211261
@ <td class="timelineTime">%s(zTime)</td>
212262
@ <td class="timelineGraph">
213
- if( pGraph && zType[0]=='c' ){
263
+ if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0;
264
+ if( zType[0]=='c'
265
+ && (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0)
266
+ ){
267
+ db_reset(&qbranch);
268
+ db_bind_int(&qbranch, ":rid", rid);
269
+ if( db_step(&qbranch)==SQLITE_ROW ){
270
+ zBr = db_column_text(&qbranch, 0);
271
+ }else{
272
+ zBr = "trunk";
273
+ }
274
+ if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
275
+ if( zBr==0 || strcmp(zBr,"trunk")==0 ){
276
+ zBgClr = 0;
277
+ }else{
278
+ zBgClr = hash_color(zBr);
279
+ }
280
+ }
281
+ }
282
+ if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
214283
int nParent = 0;
215284
int aParent[32];
216
- const char *zBr;
217285
int gidx;
218286
static Stmt qparent;
219
- static Stmt qbranch;
220287
db_static_prepare(&qparent,
221288
"SELECT pid FROM plink"
222289
" WHERE cid=:rid AND pid NOT IN phantom"
223290
" ORDER BY isprim DESC /*sort*/"
224291
);
225
- db_static_prepare(&qbranch,
226
- "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
227
- TAG_BRANCH
228
- );
229292
db_bind_int(&qparent, ":rid", rid);
230293
while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){
231294
aParent[nParent++] = db_column_int(&qparent, 0);
232295
}
233296
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
- }
240297
gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf);
241298
db_reset(&qbranch);
242299
@ <div id="m%d(gidx)"></div>
243300
}
244301
@</td>
@@ -768,10 +825,12 @@
768825
** fc Show details of files changed
769826
** f=RID Show family (immediate parents and children) of RID
770827
** from=RID Path from...
771828
** to=RID ... to this
772829
** nomerge ... avoid merge links on the path
830
+** brbg Background color from branch name
831
+** ubg Background color from user
773832
**
774833
** p= and d= can appear individually or together. If either p= or d=
775834
** appear, then u=, y=, a=, and b= are ignored.
776835
**
777836
** If a= and b= appear, only a= is used. If neither appear, the most
@@ -826,10 +885,12 @@
826885
tmFlags = TIMELINE_GRAPH;
827886
}
828887
if( P("ng")!=0 || zSearch!=0 ){
829888
tmFlags &= ~TIMELINE_GRAPH;
830889
}
890
+ if( P("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
891
+ if( P("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
831892
832893
style_header("Timeline");
833894
login_anonymous_available();
834895
timeline_temp_table();
835896
blob_zero(&sql);
836897
--- src/timeline.c
+++ src/timeline.c
@@ -107,11 +107,55 @@
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 +186,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 +202,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 +219,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 +258,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>
@@ -768,10 +825,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 +885,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);
836
--- src/timeline.c
+++ src/timeline.c
@@ -107,11 +107,55 @@
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 ** Output a timeline in the web format given a query. The query
160 ** should return these columns:
161 **
@@ -142,10 +186,11 @@
186 char zPrevDate[20];
187 GraphContext *pGraph = 0;
188 int prevWasDivider = 0; /* True if previous output row was <hr> */
189 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
190 Stmt fchngQuery; /* Query for file changes on check-ins */
191 static Stmt qbranch;
192
193 zPrevDate[0] = 0;
194 mxWikiLen = db_get_int("timeline-max-comment", 0);
195 if( db_get_boolean("timeline-block-markup", 0) ){
196 wikiFlags = WIKI_INLINE;
@@ -157,10 +202,14 @@
202 /* style is not moved to css, because this is
203 ** a technical div for the timeline graph
204 */
205 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
206 }
207 db_static_prepare(&qbranch,
208 "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid",
209 TAG_BRANCH
210 );
211
212 @ <table id="timelineTable" class="timelineTable">
213 blob_zero(&comment);
214 while( db_step(pQuery)==SQLITE_ROW ){
215 int rid = db_column_int(pQuery, 0);
@@ -170,10 +219,11 @@
219 const char *zDate = db_column_text(pQuery, 2);
220 const char *zType = db_column_text(pQuery, 7);
221 const char *zUser = db_column_text(pQuery, 4);
222 const char *zTagList = db_column_text(pQuery, 8);
223 int tagid = db_column_int(pQuery, 9);
224 const char *zBr = 0; /* Branch */
225 int commentColumn = 3; /* Column containing comment text */
226 char zTime[8];
227 if( tagid ){
228 if( tagid==prevTagid ){
229 if( tmFlags & TIMELINE_BRIEF ){
@@ -208,37 +258,44 @@
258 memcpy(zTime, &zDate[11], 5);
259 zTime[5] = 0;
260 @ <tr>
261 @ <td class="timelineTime">%s(zTime)</td>
262 @ <td class="timelineGraph">
263 if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0;
264 if( zType[0]=='c'
265 && (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0)
266 ){
267 db_reset(&qbranch);
268 db_bind_int(&qbranch, ":rid", rid);
269 if( db_step(&qbranch)==SQLITE_ROW ){
270 zBr = db_column_text(&qbranch, 0);
271 }else{
272 zBr = "trunk";
273 }
274 if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
275 if( zBr==0 || strcmp(zBr,"trunk")==0 ){
276 zBgClr = 0;
277 }else{
278 zBgClr = hash_color(zBr);
279 }
280 }
281 }
282 if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
283 int nParent = 0;
284 int aParent[32];
 
285 int gidx;
286 static Stmt qparent;
 
287 db_static_prepare(&qparent,
288 "SELECT pid FROM plink"
289 " WHERE cid=:rid AND pid NOT IN phantom"
290 " ORDER BY isprim DESC /*sort*/"
291 );
 
 
 
 
292 db_bind_int(&qparent, ":rid", rid);
293 while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){
294 aParent[nParent++] = db_column_int(&qparent, 0);
295 }
296 db_reset(&qparent);
 
 
 
 
 
 
297 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf);
298 db_reset(&qbranch);
299 @ <div id="m%d(gidx)"></div>
300 }
301 @</td>
@@ -768,10 +825,12 @@
825 ** fc Show details of files changed
826 ** f=RID Show family (immediate parents and children) of RID
827 ** from=RID Path from...
828 ** to=RID ... to this
829 ** nomerge ... avoid merge links on the path
830 ** brbg Background color from branch name
831 ** ubg Background color from user
832 **
833 ** p= and d= can appear individually or together. If either p= or d=
834 ** appear, then u=, y=, a=, and b= are ignored.
835 **
836 ** If a= and b= appear, only a= is used. If neither appear, the most
@@ -826,10 +885,12 @@
885 tmFlags = TIMELINE_GRAPH;
886 }
887 if( P("ng")!=0 || zSearch!=0 ){
888 tmFlags &= ~TIMELINE_GRAPH;
889 }
890 if( P("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
891 if( P("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
892
893 style_header("Timeline");
894 login_anonymous_available();
895 timeline_temp_table();
896 blob_zero(&sql);
897
+7 -7
--- src/winhttp.c
+++ src/winhttp.c
@@ -444,11 +444,11 @@
444444
** is logged in.
445445
**
446446
** In the following description of the methods, "Fossil-DSCM" will be
447447
** used as the default SERVICE-NAME:
448448
**
449
-** fossil service create ?SERVICE-NAME? ?OPTIONS?
449
+** fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
450450
**
451451
** Creates a service. Available options include:
452452
**
453453
** -D|--display DISPLAY-NAME
454454
**
@@ -458,11 +458,11 @@
458458
**
459459
** -S|--start TYPE
460460
**
461461
** Sets the start type of the service. TYPE can be "manual",
462462
** which means you need to start the service yourself with the
463
-** 'fossil service start' command or with the "net start" command
463
+** 'fossil winsrv start' command or with the "net start" command
464464
** from the operating system. If TYPE is set to "auto", the service
465465
** will be started automatically by the system during startup.
466466
**
467467
** -U|--username USERNAME
468468
**
@@ -509,27 +509,27 @@
509509
** Enables automatic login if the --localauth option is present
510510
** and the "localauth" setting is off and the connection is from
511511
** localhost.
512512
**
513513
**
514
-** fossil service delete ?SERVICE-NAME?
514
+** fossil winsrv delete ?SERVICE-NAME?
515515
**
516516
** Deletes a service. If the service is currently running, it will be
517517
** stopped first and then deleted.
518518
**
519519
**
520
-** fossil service show ?SERVICE-NAME?
520
+** fossil winsrv show ?SERVICE-NAME?
521521
**
522522
** Shows how the service is configured and its current state.
523523
**
524524
**
525
-** fossil service start ?SERVICE-NAME?
525
+** fossil winsrv start ?SERVICE-NAME?
526526
**
527527
** Start the service.
528528
**
529529
**
530
-** fossil service stop ?SERVICE-NAME?
530
+** fossil winsrv stop ?SERVICE-NAME?
531531
**
532532
** Stop the service.
533533
**
534534
**
535535
** NOTE: This command is available on Windows operating systems only and
@@ -852,11 +852,11 @@
852852
853853
#else /* _WIN32 -- This code is for win32 only */
854854
#include "winhttp.h"
855855
856856
void cmd_win32_service(void){
857
- fossil_fatal("The service command is platform specific "
857
+ fossil_fatal("The winsrv command is platform specific "
858858
"and not available on this platform.");
859859
return;
860860
}
861861
862862
#endif /* _WIN32 -- This code is for win32 only */
863863
--- src/winhttp.c
+++ src/winhttp.c
@@ -444,11 +444,11 @@
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 service create ?SERVICE-NAME? ?OPTIONS?
450 **
451 ** Creates a service. Available options include:
452 **
453 ** -D|--display DISPLAY-NAME
454 **
@@ -458,11 +458,11 @@
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 service 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 **
@@ -509,27 +509,27 @@
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 service 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 service show ?SERVICE-NAME?
521 **
522 ** Shows how the service is configured and its current state.
523 **
524 **
525 ** fossil service start ?SERVICE-NAME?
526 **
527 ** Start the service.
528 **
529 **
530 ** fossil service stop ?SERVICE-NAME?
531 **
532 ** Stop the service.
533 **
534 **
535 ** NOTE: This command is available on Windows operating systems only and
@@ -852,11 +852,11 @@
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 service 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
--- src/winhttp.c
+++ src/winhttp.c
@@ -444,11 +444,11 @@
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 **
@@ -458,11 +458,11 @@
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 **
@@ -509,27 +509,27 @@
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
@@ -852,11 +852,11 @@
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
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -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
@@ -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
@@ -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.msc
+++ win/Makefile.msc
@@ -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
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -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
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -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

Keyboard Shortcuts

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