Fossil SCM

Merge latest trunk changes.

mistachkin 2011-09-27 03:55 UTC tcl-integration merge
Commit 2d2b45bb178f30983dde6a1626e7f27abffd5d17
--- 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 +
+7
--- auto.def
+++ auto.def
@@ -134,10 +134,17 @@
134134
define FOSSIL_ENABLE_SSL
135135
define-append EXTRA_CFLAGS $cflags
136136
define-append EXTRA_LDFLAGS $ldflags
137137
define-append LIBS -lssl -lcrypto
138138
msg-result "HTTP support enabled"
139
+
140
+ # Silence OpenSSL deprecation warnings on Mac OS X 10.7.
141
+ if {[string match *-darwin* [get-define host]]} {
142
+ if {[cctest -cflags {-Wdeprecated-declarations}]} {
143
+ define-append EXTRA_CFLAGS -Wdeprecated-declarations
144
+ }
145
+ }
139146
} else {
140147
user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
141148
}
142149
}
143150
144151
--- auto.def
+++ auto.def
@@ -134,10 +134,17 @@
134 define FOSSIL_ENABLE_SSL
135 define-append EXTRA_CFLAGS $cflags
136 define-append EXTRA_LDFLAGS $ldflags
137 define-append LIBS -lssl -lcrypto
138 msg-result "HTTP support enabled"
 
 
 
 
 
 
 
139 } else {
140 user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
141 }
142 }
143
144
--- auto.def
+++ auto.def
@@ -134,10 +134,17 @@
134 define FOSSIL_ENABLE_SSL
135 define-append EXTRA_CFLAGS $cflags
136 define-append EXTRA_LDFLAGS $ldflags
137 define-append LIBS -lssl -lcrypto
138 msg-result "HTTP support enabled"
139
140 # Silence OpenSSL deprecation warnings on Mac OS X 10.7.
141 if {[string match *-darwin* [get-define host]]} {
142 if {[cctest -cflags {-Wdeprecated-declarations}]} {
143 define-append EXTRA_CFLAGS -Wdeprecated-declarations
144 }
145 }
146 } else {
147 user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
148 }
149 }
150
151
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -331,17 +331,11 @@
331331
# simply replaces the existing value.
332332
#
333333
# Returns the previous settings
334334
proc cc-update-settings {args} {
335335
set prev [cc-get-settings]
336
- array set new $prev
337
-
338
- foreach {name value} $args {
339
- set new($name) $value
340
- }
341
- cc-store-settings $new
342
-
336
+ cc-store-settings [dict merge $prev $args]
343337
return $prev
344338
}
345339
346340
# @cc-with settings ?{ script }?
347341
#
348342
349343
DELETED ci_cvs.txt
350344
DELETED ci_fossil.txt
351345
DELETED cvs2fossil.txt
352346
DELETED kktodo.wiki
353347
DELETED rse-notes.txt
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -331,17 +331,11 @@
331 # simply replaces the existing value.
332 #
333 # Returns the previous settings
334 proc cc-update-settings {args} {
335 set prev [cc-get-settings]
336 array set new $prev
337
338 foreach {name value} $args {
339 set new($name) $value
340 }
341 cc-store-settings $new
342
343 return $prev
344 }
345
346 # @cc-with settings ?{ script }?
347 #
348
349 ELETED ci_cvs.txt
350 ELETED ci_fossil.txt
351 ELETED cvs2fossil.txt
352 ELETED kktodo.wiki
353 ELETED rse-notes.txt
--- autosetup/cc.tcl
+++ autosetup/cc.tcl
@@ -331,17 +331,11 @@
331 # simply replaces the existing value.
332 #
333 # Returns the previous settings
334 proc cc-update-settings {args} {
335 set prev [cc-get-settings]
336 cc-store-settings [dict merge $prev $args]
 
 
 
 
 
 
337 return $prev
338 }
339
340 # @cc-with settings ?{ script }?
341 #
342
343 ELETED ci_cvs.txt
344 ELETED ci_fossil.txt
345 ELETED cvs2fossil.txt
346 ELETED kktodo.wiki
347 ELETED rse-notes.txt
D ci_cvs.txt
-190
--- a/ci_cvs.txt
+++ b/ci_cvs.txt
@@ -1,192 +0,0 @@
1
-===============================================================================
2
-
3
-First experimental codes ...
4
-
5
-tools/import-cvs.tcl
6
-tools/lib/rcsparser.tcl
7
-
8
-No actual import, right now only working on getting csets right. The
9
-code uses CVSROOT/history as foundation, and augments that with data
10
-from the individual RCS files (commit messages).
11
-
12
-Statistics of a run ...
13
- 3516 csets.
14
-
15
- 1545 breaks on user change
16
- 558 breaks on file duplicate
17
- 13 breaks on branch/trunk change
18
- 1402 breaks on commit message change
19
-
20
-Time statistics ...
21
- 3297 were processed in <= 1 seconds (93.77%)
22
- 217 were processed in between 2 seconds and 14 minutes.
23
- 1 was processed in ~41 minutes
24
- 1 was processed in ~22 hours
25
-
26
-Time fuzz - Differences between csets range from 0 seconds to 66
27
-days. Needs stats analysis to see if there is an obvious break. Even
28
-so the times within csets and between csets overlap a great deal,
29
-making time a bad criterium for cset separation, IMHO.
30
-
31
-Leaving that topic, back to the current cset separator ...
32
-
33
-It has a problem:
34
- The history file is not starting at the root!
35
-
36
-Examples:
37
- The first three changesets are
38
-
39
- =============================/user
40
- M {Wed Nov 22 09:28:49 AM PST 2000} ericm 1.4 tcllib/modules/ftpd/ChangeLog
41
- M {Wed Nov 22 09:28:49 AM PST 2000} ericm 1.7 tcllib/modules/ftpd/ftpd.tcl
42
- files: 2
43
- delta: 0
44
- range: 0 seconds
45
- =============================/cmsg
46
- M {Wed Nov 29 02:14:33 PM PST 2000} ericm 1.3 tcllib/aclocal.m4
47
- files: 1
48
- delta:
49
- range: 0 seconds
50
- =============================/cmsg
51
- M {Sun Feb 04 12:28:35 AM PST 2001} ericm 1.9 tcllib/modules/mime/ChangeLog
52
- M {Sun Feb 04 12:28:35 AM PST 2001} ericm 1.12 tcllib/modules/mime/mime.tcl
53
- files: 2
54
- delta: 0
55
- range: 0 seconds
56
-
57
-All csets modify files which already have several revisions. We have
58
-no csets from before that in the history, but these csets are in the
59
-RCS files.
60
-
61
-I wonder, is SF maybe removing old entries from the history when it
62
-grows too large ?
63
-
64
-This also affects incremental import ... I cannot assume that the
65
-history always grows. It may shrink ... I cannot keep an offset, will
66
-have to record the time of the last entry, or even the full entry
67
-processed last, to allow me to skip ahead to anything not known yet.
68
-
69
-I might have to try to implement the algorithm outlined below,
70
-matching the revision trees of the individual RCS files to each other
71
-to form the global tree of revisions. Maybe we can use the history to
72
-help in the matchup, for the parts where we do have it.
73
-
74
-Wait. This might be easier ... Take the delta information from the RCS
75
-files and generate a fake history ... Actually, this might even allow
76
-us to create a total history ... No, not quite, the merge entries the
77
-actual history may contain will be missing. These we can mix in from
78
-the actual history, as much as we have.
79
-
80
-Still, lets try that, a fake history, and then run this script on it
81
-to see if/where are differences.
82
-
83
-===============================================================================
84
-
85
-
86
-Notes about CVS import, regarding CVS.
87
-
88
-- Problem: CVS does not really track changesets, but only individual
89
- revisions of files. To recover changesets it is necessary to look at
90
- author, branch, timestamp information, and the commit messages. Even
91
- so this is only heuristic, not foolproof.
92
-
93
- Existing tool: cvsps.
94
-
95
- Processes the output of 'cvs log' to recover changesets. Problem:
96
- Sees only a linear list of revisions, does not see branchpoints,
97
- etc. Cannot use the tree structure to help in making the decisions.
98
-
99
-- Problem: CVS does not track merge-points at all. Recovery through
100
- heuristics is brittle at best, looking for keywords in commit
101
- messages which might indicate that a branch was merged with some
102
- other.
103
-
104
-
105
-Ideas regarding an algorithm to recover changesets.
106
-
107
-Key feature: Uses the per-file revision trees to help in uncovering
108
-the underlying changesets and global revision tree G.
109
-
110
-The per-file revision tree for a file X is in essence the global
111
-revision tree with all nodes not pertaining to X removed from it. In
112
-the reverse this allows us to built up the global revision tree from
113
-the per-file trees by matching nodes to each other and extending.
114
-
115
-Start with the per file revision tree of a single file as initial
116
-approximation of the global tree. All nodes of this tree refer to the
117
-revision of the file belonging to it, and through that the file
118
-itself. At each step the global tree contains the nodes for a finite
119
-set of files, and all nodes in the tree refer to revisions of all
120
-files in the set, making the mapping total.
121
-
122
-To add a file X to the tree take the per-file revision tree R and
123
-performs the following actions:
124
-
125
-- For each node N in R use the tuple <author, branch, commit message>
126
- to identify a set of nodes in G which may match N. Use the timestamp
127
- to locate the node nearest in time.
128
-
129
-- This process will leave nodes in N unmapped. If there are unmapped
130
- nodes which have no neighbouring mapped nodes we have to
131
- abort.
132
-
133
- Otherwise take the nodes which have mapped neighbours. Trace the
134
- edges and see which of these nodes are connected in the local
135
- tree. Then look at the identified neighbours and trace their
136
- connections.
137
-
138
- If two global nodes have a direct connection, but a multi-edge
139
- connection in the local tree insert global nodes mapping to the
140
- local nodes and map them together. This expands the global tree to
141
- hold the revisions added by the new file.
142
-
143
- Otherwise, both sides have multi-edge connections then abort. This
144
- looks like a merge of two different branches, but there are no such
145
- in CVS ... Wait ... sort the nodes over time and fit the new nodes
146
- in between the other nodes, per the timestamps. We have overlapping
147
- / alternating changes to one file and others.
148
-
149
- A last possibility is that a node is only connected to a mapped
150
- parent. This may be a new branch, or again an alternating change on
151
- the given line. Symbols on the revisions will help to map this.
152
-
153
-- We now have an extended global tree which incorporates the revisions
154
- of the new file. However new nodes will refer only to the new file,
155
- and old nodes may not refer to the new file. This has to be fixed,
156
- as all nodes have to refer to all files.
157
-
158
- Run over the tree and look at each parent/child pair. If a file is
159
- not referenced in the child, but the parent, then copy a reference
160
- to the file revision on the parent forward to the child. This
161
- signals that the file did not change in the given revision.
162
-
163
-- After all files have been integrated in this manner we have global
164
- revision tree capturing all changesets, including the unchanged
165
- files per changeset.
166
-
167
-
168
-This algorithm has to be refined to also take Attic/ files into
169
-account.
170
-
--------------------------------------------------------------------------
171
-
172
-Two archive files mapping to the same user file. How are they
173
-interleaved ?
174
-
175
-(a) sqlite/src/os_unix.h,v
176
-(b) sqlite/src/Attic/os_unix.h,v
177
-
178
-Problem: Max version of (a) is 1.9
179
- Max version of (b) is 1.11
180
- cvs co 1.10 -> no longer in the repository.
181
-
182
-This seems to indicate that the non-Attic file is relevant.
183
-
---------------------------------------------------------------------------
184
-
185
-tcllib - more problems - tklib/pie.tcl,v -
186
-
187
-invalid change text in
188
-/home/aku/Projects/Tcl/Fossil/Devel/Examples/cvs-tcllib/tklib/modules/tkpiechart/pie.tcl,v
189
-
190
-Possibly braces ?
--- a/ci_cvs.txt
+++ b/ci_cvs.txt
@@ -1,192 +0,0 @@
1 ===============================================================================
2
3 First experimental codes ...
4
5 tools/import-cvs.tcl
6 tools/lib/rcsparser.tcl
7
8 No actual import, right now only working on getting csets right. The
9 code uses CVSROOT/history as foundation, and augments that with data
10 from the individual RCS files (commit messages).
11
12 Statistics of a run ...
13 3516 csets.
14
15 1545 breaks on user change
16 558 breaks on file duplicate
17 13 breaks on branch/trunk change
18 1402 breaks on commit message change
19
20 Time statistics ...
21 3297 were processed in <= 1 seconds (93.77%)
22 217 were processed in between 2 seconds and 14 minutes.
23 1 was processed in ~41 minutes
24 1 was processed in ~22 hours
25
26 Time fuzz - Differences between csets range from 0 seconds to 66
27 days. Needs stats analysis to see if there is an obvious break. Even
28 so the times within csets and between csets overlap a great deal,
29 making time a bad criterium for cset separation, IMHO.
30
31 Leaving that topic, back to the current cset separator ...
32
33 It has a problem:
34 The history file is not starting at the root!
35
36 Examples:
37 The first three changesets are
38
39 =============================/user
40 M {Wed Nov 22 09:28:49 AM PST 2000} ericm 1.4 tcllib/modules/ftpd/ChangeLog
41 M {Wed Nov 22 09:28:49 AM PST 2000} ericm 1.7 tcllib/modules/ftpd/ftpd.tcl
42 files: 2
43 delta: 0
44 range: 0 seconds
45 =============================/cmsg
46 M {Wed Nov 29 02:14:33 PM PST 2000} ericm 1.3 tcllib/aclocal.m4
47 files: 1
48 delta:
49 range: 0 seconds
50 =============================/cmsg
51 M {Sun Feb 04 12:28:35 AM PST 2001} ericm 1.9 tcllib/modules/mime/ChangeLog
52 M {Sun Feb 04 12:28:35 AM PST 2001} ericm 1.12 tcllib/modules/mime/mime.tcl
53 files: 2
54 delta: 0
55 range: 0 seconds
56
57 All csets modify files which already have several revisions. We have
58 no csets from before that in the history, but these csets are in the
59 RCS files.
60
61 I wonder, is SF maybe removing old entries from the history when it
62 grows too large ?
63
64 This also affects incremental import ... I cannot assume that the
65 history always grows. It may shrink ... I cannot keep an offset, will
66 have to record the time of the last entry, or even the full entry
67 processed last, to allow me to skip ahead to anything not known yet.
68
69 I might have to try to implement the algorithm outlined below,
70 matching the revision trees of the individual RCS files to each other
71 to form the global tree of revisions. Maybe we can use the history to
72 help in the matchup, for the parts where we do have it.
73
74 Wait. This might be easier ... Take the delta information from the RCS
75 files and generate a fake history ... Actually, this might even allow
76 us to create a total history ... No, not quite, the merge entries the
77 actual history may contain will be missing. These we can mix in from
78 the actual history, as much as we have.
79
80 Still, lets try that, a fake history, and then run this script on it
81 to see if/where are differences.
82
83 ===============================================================================
84
85
86 Notes about CVS import, regarding CVS.
87
88 - Problem: CVS does not really track changesets, but only individual
89 revisions of files. To recover changesets it is necessary to look at
90 author, branch, timestamp information, and the commit messages. Even
91 so this is only heuristic, not foolproof.
92
93 Existing tool: cvsps.
94
95 Processes the output of 'cvs log' to recover changesets. Problem:
96 Sees only a linear list of revisions, does not see branchpoints,
97 etc. Cannot use the tree structure to help in making the decisions.
98
99 - Problem: CVS does not track merge-points at all. Recovery through
100 heuristics is brittle at best, looking for keywords in commit
101 messages which might indicate that a branch was merged with some
102 other.
103
104
105 Ideas regarding an algorithm to recover changesets.
106
107 Key feature: Uses the per-file revision trees to help in uncovering
108 the underlying changesets and global revision tree G.
109
110 The per-file revision tree for a file X is in essence the global
111 revision tree with all nodes not pertaining to X removed from it. In
112 the reverse this allows us to built up the global revision tree from
113 the per-file trees by matching nodes to each other and extending.
114
115 Start with the per file revision tree of a single file as initial
116 approximation of the global tree. All nodes of this tree refer to the
117 revision of the file belonging to it, and through that the file
118 itself. At each step the global tree contains the nodes for a finite
119 set of files, and all nodes in the tree refer to revisions of all
120 files in the set, making the mapping total.
121
122 To add a file X to the tree take the per-file revision tree R and
123 performs the following actions:
124
125 - For each node N in R use the tuple <author, branch, commit message>
126 to identify a set of nodes in G which may match N. Use the timestamp
127 to locate the node nearest in time.
128
129 - This process will leave nodes in N unmapped. If there are unmapped
130 nodes which have no neighbouring mapped nodes we have to
131 abort.
132
133 Otherwise take the nodes which have mapped neighbours. Trace the
134 edges and see which of these nodes are connected in the local
135 tree. Then look at the identified neighbours and trace their
136 connections.
137
138 If two global nodes have a direct connection, but a multi-edge
139 connection in the local tree insert global nodes mapping to the
140 local nodes and map them together. This expands the global tree to
141 hold the revisions added by the new file.
142
143 Otherwise, both sides have multi-edge connections then abort. This
144 looks like a merge of two different branches, but there are no such
145 in CVS ... Wait ... sort the nodes over time and fit the new nodes
146 in between the other nodes, per the timestamps. We have overlapping
147 / alternating changes to one file and others.
148
149 A last possibility is that a node is only connected to a mapped
150 parent. This may be a new branch, or again an alternating change on
151 the given line. Symbols on the revisions will help to map this.
152
153 - We now have an extended global tree which incorporates the revisions
154 of the new file. However new nodes will refer only to the new file,
155 and old nodes may not refer to the new file. This has to be fixed,
156 as all nodes have to refer to all files.
157
158 Run over the tree and look at each parent/child pair. If a file is
159 not referenced in the child, but the parent, then copy a reference
160 to the file revision on the parent forward to the child. This
161 signals that the file did not change in the given revision.
162
163 - After all files have been integrated in this manner we have global
164 revision tree capturing all changesets, including the unchanged
165 files per changeset.
166
167
168 This algorithm has to be refined to also take Attic/ files into
169 account.
170
--------------------------------------------------------------------------
171
172 Two archive files mapping to the same user file. How are they
173 interleaved ?
174
175 (a) sqlite/src/os_unix.h,v
176 (b) sqlite/src/Attic/os_unix.h,v
177
178 Problem: Max version of (a) is 1.9
179 Max version of (b) is 1.11
180 cvs co 1.10 -> no longer in the repository.
181
182 This seems to indicate that the non-Attic file is relevant.
183
---------------------------------------------------------------------------
184
185 tcllib - more problems - tklib/pie.tcl,v -
186
187 invalid change text in
188 /home/aku/Projects/Tcl/Fossil/Devel/Examples/cvs-tcllib/tklib/modules/tkpiechart/pie.tcl,v
189
190 Possibly braces ?
--- a/ci_cvs.txt
+++ b/ci_cvs.txt
@@ -1,192 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
---------------------------------------------------------------------------
 
 
 
 
 
 
 
D ci_fossil.txt
-126
--- a/ci_fossil.txt
+++ b/ci_fossil.txt
@@ -1,127 +0,0 @@
1
-
2
-To perform CVS imports for fossil we need at least the ability to
3
-parse CVS files, i.e. RCS files, with slight differences.
4
-
5
-For the general architecture of the import facility we have two major
6
-paths to choose between.
7
-
8
-One is to use an external tool which processes a cvs repository and
9
-drives fossil through its CLI to insert the found changesets.
10
-
11
-The other is to integrate the whole facility into the fossil binary
12
-itself.
13
-
14
-I dislike the second choice. It may be faster, as the implementation
15
-can use all internal functionality of fossil to perform the import,
16
-however it will also bloat the binary with functionality not needed
17
-most of the time. Which becomes especially obvious if more importers
18
-are to be written, like for monotone, bazaar, mercurial, bitkeeper,
19
-git, SVN, Arc, etc. Keeping all this out of the core fossil binary is
20
-IMHO more beneficial in the long term, also from a maintenance point
21
-of view. The tools can evolve separately. Especially important for CVS
22
-as it will have to deal with lots of broken repositories, all
23
-different.
24
-
25
-However, nothing speaks against looking for common parts in all
26
-possible import tools, and having these in the fossil core, as a
27
-general backend all importer may use. Something like that has already
28
-been proposed: The deconstruct|reconstruct methods. For us, actually
29
-only reconstruct is important. Taking an unordered collection of files
30
-(data, and manifests) it generates a proper fossil repository. With
31
-that method implemented all import tools only have to generate the
32
-necessary collection and then leave the main work of filling the
33
-database to fossil itself.
34
-
35
-The disadvantage of this method is however that it will gobble up a
36
-lot of temporary space in the filesystem to hold all unique revisions
37
-of all files in their expanded form.
38
-
39
-It might be worthwhile to consider an extension of 'reconstruct' which
40
-is able to incrementally add a set of files to an existing fossil
41
-repository already containing revisions. In that case the import tool
42
-can be changed to incrementally generate the collection for a
43
-particular revision, import it, and iterate over all revisions in the
44
-origin repository. This is of course also dependent on the origin
45
-repository itself, how well it supports such incremental export.
46
-
47
-This also leads to a possible method for performing the import using
48
-only existing functionality ('reconstruct' has not been implemented
49
-yet). Instead generating an unordered collection for each revision
50
-generate a properly setup workspace, simply commit it. This will
51
-require use of rm, add and update methods as well, to remove old and
52
-enter new files, and point the fossil repository to the correct parent
53
-revision from the new revision is derived.
54
-
55
-The relative efficiency (in time) of these incremental methods versus
56
-importing a complete collection of files encoding the entire origin
57
-repository however is not clear.
58
-
-----------------------------------
59
-
60
-reconstruct
61
-
62
-The core logic for handling content is in the file "content.c", in
63
-particular the functions 'content_put' and 'content_deltify'. One of
64
-the main users of these functions is in the file "checkin.c", see the
65
-function 'commit_cmd'.
66
-
67
-The logic is clear. The new modified files are simply stored without
68
-delta-compression, using 'content_put'. And should fosssil have an id
69
-for the _previous_ revision of the committed file it uses
70
-'content_deltify' to convert the already stored data for that revision
71
-into a delta with the just stored new revision as origin.
72
-
73
-In other words, fossil produces reverse deltas, with leaf revisions
74
-stored just zip-compressed (plain) and older revisions using both zip-
75
-and delta-compression.
76
-
77
-Of note is that the underlying logic in 'content_deltify' gives up on
78
-delta compression if the involved files are either not large enough,
79
-or if the achieved compression factor was not high enough. In that
80
-case the old revision of the file is left plain.
81
-
82
-The scheme can thus be called a 'truncated reverse delta'.
83
-
84
-The manifest is created and committed after the modified files. It
85
-uses the same logic as for the regular files. The new leaf is stored
86
-plain, and storage of the parent manifest is modified to be a delta
87
-with the current as origin.
88
-
89
-Further note that for a checkin of a merge result oonly the primary
90
-parent is modified in that way. The secondary parent, the one merged
91
-into the current revision is not touched. I.e. from the storage layer
92
-point of view this revision is still a leaf and the data is kept
93
-stored plain, not delta-compressed.
94
-
95
-
96
-
97
-Now the "reconstruct" can be done like so:
98
-
99
-- Scan the files in the indicated directory, and look for a manifest.
100
-
101
-- When the manifest has been found parse its contents and follow the
102
- chain of parent links to locate the root manifest (no parent).
103
-
104
-- Import the files referenced by the root manifest, then the manifest
105
- itself. This can be done using a modified form of the 'commit_cmd'
106
- which does not have to construct a manifest on its own from vfile,
107
- vmerge, etc.
108
-
109
-- After that recursively apply the import of the previous step to the
110
- children of the root, and so on.
111
-
112
-For an incremental "reconstruct" the collection of files would not be
113
-a single tree with a root, but a forest, and the roots to look for are
114
-not manifests without parent, but with a parent which is already
115
-present in the repository. After one such root has been found and
116
-processed the unprocessed files have to be searched further for more
117
-roots, and only if no such are found anymore will the remaining files
118
-be considered as superfluous.
119
-
120
-We can use the functions in "manifest.c" for the parsing and following
121
-the parental chain.
122
-
123
-Hm. But we have no direct child information. So the above algorithm
124
-has to be modified, we have to scan all manifests before we start
125
-importing, and we have to create a reverse index, from manifest to
126
-children so that we can perform the import from root to leaves.
--- a/ci_fossil.txt
+++ b/ci_fossil.txt
@@ -1,127 +0,0 @@
1
2 To perform CVS imports for fossil we need at least the ability to
3 parse CVS files, i.e. RCS files, with slight differences.
4
5 For the general architecture of the import facility we have two major
6 paths to choose between.
7
8 One is to use an external tool which processes a cvs repository and
9 drives fossil through its CLI to insert the found changesets.
10
11 The other is to integrate the whole facility into the fossil binary
12 itself.
13
14 I dislike the second choice. It may be faster, as the implementation
15 can use all internal functionality of fossil to perform the import,
16 however it will also bloat the binary with functionality not needed
17 most of the time. Which becomes especially obvious if more importers
18 are to be written, like for monotone, bazaar, mercurial, bitkeeper,
19 git, SVN, Arc, etc. Keeping all this out of the core fossil binary is
20 IMHO more beneficial in the long term, also from a maintenance point
21 of view. The tools can evolve separately. Especially important for CVS
22 as it will have to deal with lots of broken repositories, all
23 different.
24
25 However, nothing speaks against looking for common parts in all
26 possible import tools, and having these in the fossil core, as a
27 general backend all importer may use. Something like that has already
28 been proposed: The deconstruct|reconstruct methods. For us, actually
29 only reconstruct is important. Taking an unordered collection of files
30 (data, and manifests) it generates a proper fossil repository. With
31 that method implemented all import tools only have to generate the
32 necessary collection and then leave the main work of filling the
33 database to fossil itself.
34
35 The disadvantage of this method is however that it will gobble up a
36 lot of temporary space in the filesystem to hold all unique revisions
37 of all files in their expanded form.
38
39 It might be worthwhile to consider an extension of 'reconstruct' which
40 is able to incrementally add a set of files to an existing fossil
41 repository already containing revisions. In that case the import tool
42 can be changed to incrementally generate the collection for a
43 particular revision, import it, and iterate over all revisions in the
44 origin repository. This is of course also dependent on the origin
45 repository itself, how well it supports such incremental export.
46
47 This also leads to a possible method for performing the import using
48 only existing functionality ('reconstruct' has not been implemented
49 yet). Instead generating an unordered collection for each revision
50 generate a properly setup workspace, simply commit it. This will
51 require use of rm, add and update methods as well, to remove old and
52 enter new files, and point the fossil repository to the correct parent
53 revision from the new revision is derived.
54
55 The relative efficiency (in time) of these incremental methods versus
56 importing a complete collection of files encoding the entire origin
57 repository however is not clear.
58
-----------------------------------
59
60 reconstruct
61
62 The core logic for handling content is in the file "content.c", in
63 particular the functions 'content_put' and 'content_deltify'. One of
64 the main users of these functions is in the file "checkin.c", see the
65 function 'commit_cmd'.
66
67 The logic is clear. The new modified files are simply stored without
68 delta-compression, using 'content_put'. And should fosssil have an id
69 for the _previous_ revision of the committed file it uses
70 'content_deltify' to convert the already stored data for that revision
71 into a delta with the just stored new revision as origin.
72
73 In other words, fossil produces reverse deltas, with leaf revisions
74 stored just zip-compressed (plain) and older revisions using both zip-
75 and delta-compression.
76
77 Of note is that the underlying logic in 'content_deltify' gives up on
78 delta compression if the involved files are either not large enough,
79 or if the achieved compression factor was not high enough. In that
80 case the old revision of the file is left plain.
81
82 The scheme can thus be called a 'truncated reverse delta'.
83
84 The manifest is created and committed after the modified files. It
85 uses the same logic as for the regular files. The new leaf is stored
86 plain, and storage of the parent manifest is modified to be a delta
87 with the current as origin.
88
89 Further note that for a checkin of a merge result oonly the primary
90 parent is modified in that way. The secondary parent, the one merged
91 into the current revision is not touched. I.e. from the storage layer
92 point of view this revision is still a leaf and the data is kept
93 stored plain, not delta-compressed.
94
95
96
97 Now the "reconstruct" can be done like so:
98
99 - Scan the files in the indicated directory, and look for a manifest.
100
101 - When the manifest has been found parse its contents and follow the
102 chain of parent links to locate the root manifest (no parent).
103
104 - Import the files referenced by the root manifest, then the manifest
105 itself. This can be done using a modified form of the 'commit_cmd'
106 which does not have to construct a manifest on its own from vfile,
107 vmerge, etc.
108
109 - After that recursively apply the import of the previous step to the
110 children of the root, and so on.
111
112 For an incremental "reconstruct" the collection of files would not be
113 a single tree with a root, but a forest, and the roots to look for are
114 not manifests without parent, but with a parent which is already
115 present in the repository. After one such root has been found and
116 processed the unprocessed files have to be searched further for more
117 roots, and only if no such are found anymore will the remaining files
118 be considered as superfluous.
119
120 We can use the functions in "manifest.c" for the parsing and following
121 the parental chain.
122
123 Hm. But we have no direct child information. So the above algorithm
124 has to be modified, we have to scan all manifests before we start
125 importing, and we have to create a reverse index, from manifest to
126 children so that we can perform the import from root to leaves.
--- a/ci_fossil.txt
+++ b/ci_fossil.txt
@@ -1,127 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-----------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D cvs2fossil.txt
-66
--- a/cvs2fossil.txt
+++ b/cvs2fossil.txt
@@ -1,66 +0,0 @@
1
-
2
-Known problems and areas to work on
3
-===================================
4
-
5
-* Not yet able to handle the specification of multiple projects
6
- for one CVS repository. I.e. I can, for example, import all of
7
- tcllib, or a single subproject of tcllib, like tklib, but not
8
- multiple sub-projects in one go.
9
-
10
-* Consider to rework the breaker- and sort-passes so that they
11
- do not need all changesets as objects in memory.
12
-
13
- Current memory consumption after all changesets are loaded:
14
-
15
- bwidget 6971627 6.6
16
- cvs-memchan 4634049 4.4
17
- cvs-sqlite 45674501 43.6
18
- cvs-trf 8781289 8.4
19
- faqs 2835116 2.7
20
- libtommath 4405066 4.2
21
- mclistbox 3350190 3.2
22
- newclock 5020460 4.8
23
- oocore 4064574 3.9
24
- sampleextension 4729932 4.5
25
- tclapps 8482135 8.1
26
- tclbench 4116887 3.9
27
- tcl_bignum 2545192 2.4
28
- tclconfig 4105042 3.9
29
- tcllib 31707688 30.2
30
- tcltutorial 3512048 3.3
31
- tcl 109926382 104.8
32
- thread 8953139 8.5
33
- tklib 13935220 13.3
34
- tk 66149870 63.1
35
- widget 2625609 2.5
36
-
37
-* Look at the dependencies on external packages and consider
38
- which of them can be moved into the importer, either as a
39
- simple utility command, or wholesale.
40
-
41
- struct::list
42
- assign, map, reverse, filter
43
-
44
- Very few and self-contained commands.
45
-
46
- struct::set
47
- size, empty, contains, add, include, exclude,
48
- intersect, subsetof
49
-
50
- Most of the core commands.
51
-
52
- fileutil
53
- cat, appendToFile, writeFile,
54
- tempfile, stripPath, test
55
-
56
- fileutil::traverse
57
- In toto
58
-
59
- struct::graph
60
- In toto
61
-
62
- snit
63
- In toto
64
-
65
- sqlite3
66
- In toto
--- a/cvs2fossil.txt
+++ b/cvs2fossil.txt
@@ -1,66 +0,0 @@
1
2 Known problems and areas to work on
3 ===================================
4
5 * Not yet able to handle the specification of multiple projects
6 for one CVS repository. I.e. I can, for example, import all of
7 tcllib, or a single subproject of tcllib, like tklib, but not
8 multiple sub-projects in one go.
9
10 * Consider to rework the breaker- and sort-passes so that they
11 do not need all changesets as objects in memory.
12
13 Current memory consumption after all changesets are loaded:
14
15 bwidget 6971627 6.6
16 cvs-memchan 4634049 4.4
17 cvs-sqlite 45674501 43.6
18 cvs-trf 8781289 8.4
19 faqs 2835116 2.7
20 libtommath 4405066 4.2
21 mclistbox 3350190 3.2
22 newclock 5020460 4.8
23 oocore 4064574 3.9
24 sampleextension 4729932 4.5
25 tclapps 8482135 8.1
26 tclbench 4116887 3.9
27 tcl_bignum 2545192 2.4
28 tclconfig 4105042 3.9
29 tcllib 31707688 30.2
30 tcltutorial 3512048 3.3
31 tcl 109926382 104.8
32 thread 8953139 8.5
33 tklib 13935220 13.3
34 tk 66149870 63.1
35 widget 2625609 2.5
36
37 * Look at the dependencies on external packages and consider
38 which of them can be moved into the importer, either as a
39 simple utility command, or wholesale.
40
41 struct::list
42 assign, map, reverse, filter
43
44 Very few and self-contained commands.
45
46 struct::set
47 size, empty, contains, add, include, exclude,
48 intersect, subsetof
49
50 Most of the core commands.
51
52 fileutil
53 cat, appendToFile, writeFile,
54 tempfile, stripPath, test
55
56 fileutil::traverse
57 In toto
58
59 struct::graph
60 In toto
61
62 snit
63 In toto
64
65 sqlite3
66 In toto
--- a/cvs2fossil.txt
+++ b/cvs2fossil.txt
@@ -1,66 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D kktodo.wiki
-69
--- a/kktodo.wiki
+++ b/kktodo.wiki
@@ -1,69 +0,0 @@
1
-<h3>kkinnell</h3>
2
-
3
-.plan -- <i>Fossil, the DG</i> Bwahahahaha! The cover art could be an <i>homo erectus</i> skull lying on some COBOL code...
4
-
5
- 1. Command line interface reference docs
6
- <ul>
7
- <li> <font color="#bb4466">Finish initial pages.</font></li>
8
- <li> Start on tech-spec (serious, not "chatty") reference pages.</li>
9
- <li> Edit, edit, edit.</li>
10
- </ul>
11
-
12
- 2. Support docs
13
- <ul>
14
- <li>Basic explanation of Distributed SCM.</i>
15
- <li>Tutorial
16
- <ul>
17
- <li>Silly source. Start with existing dir struct.</li>
18
- <li>Repository. Creatiing and populating.</li>
19
- <li>Where? Local, Intranet, Internet.</li>
20
- <li>Who? Project size defined by size of code base versus
21
- number of developers. Size matters.</li>
22
- <li>How?
23
- <ul>
24
- <li>Open, close, commit, checkout, update, merge.</li>
25
- </ul>
26
- </li>
27
- <li>Hmmm. Experimenting.</li>
28
- <ul>
29
- <li>The road less travelled, or where'd that
30
- fork come from?</li>
31
- </ul>
32
- <li>Oops! Going back in time.</li>
33
- <ul>
34
- <li>Versions</li>
35
- <ul>
36
- <li>What <i>is</i> a version?</li>
37
- <li>Is it a "version" or a "tag"?</li>
38
- <li>DSCM redux: Revisionist versioning.</li>
39
- </ul>
40
- </ul>
41
- </ul>
42
- </li>
43
- <li>Basic explanation of <i>merge</i>.
44
- <ol>
45
- <li>Leaves, branches and baselines: We want a shrubbery!</li>
46
- <li><i>update</i> merges vs. <i>merge</i> merges.
47
- All merges are equal, but some are more equal than others.</li>
48
- </ol>
49
- </li>
50
- </ul>
51
-
52
- 3. Configuration
53
-
54
- 42. General
55
- <ul>
56
- <li>Co-ordinate style and tone with drh, other devs. (documentation
57
- standard? yuck.)</li>
58
- </ul>
59
-
60
- * Tips & tricks.
61
-
62
- * <b>Fossil</b> and <b>Sqlite</b>
63
- <ul>
64
- <li>Get a word in for Mrinal Kant's
65
- <a href="http://code.google.com/p/sqlite-manager/">SQLite Manager</a>
66
- XUL app. Great tool.</li>
67
- </ul>
68
-
69
- * Th (code groveling &#91;and code groveling {and code groveling ... } ... &#93; ... )
--- a/kktodo.wiki
+++ b/kktodo.wiki
@@ -1,69 +0,0 @@
1 <h3>kkinnell</h3>
2
3 .plan -- <i>Fossil, the DG</i> Bwahahahaha! The cover art could be an <i>homo erectus</i> skull lying on some COBOL code...
4
5 1. Command line interface reference docs
6 <ul>
7 <li> <font color="#bb4466">Finish initial pages.</font></li>
8 <li> Start on tech-spec (serious, not "chatty") reference pages.</li>
9 <li> Edit, edit, edit.</li>
10 </ul>
11
12 2. Support docs
13 <ul>
14 <li>Basic explanation of Distributed SCM.</i>
15 <li>Tutorial
16 <ul>
17 <li>Silly source. Start with existing dir struct.</li>
18 <li>Repository. Creatiing and populating.</li>
19 <li>Where? Local, Intranet, Internet.</li>
20 <li>Who? Project size defined by size of code base versus
21 number of developers. Size matters.</li>
22 <li>How?
23 <ul>
24 <li>Open, close, commit, checkout, update, merge.</li>
25 </ul>
26 </li>
27 <li>Hmmm. Experimenting.</li>
28 <ul>
29 <li>The road less travelled, or where'd that
30 fork come from?</li>
31 </ul>
32 <li>Oops! Going back in time.</li>
33 <ul>
34 <li>Versions</li>
35 <ul>
36 <li>What <i>is</i> a version?</li>
37 <li>Is it a "version" or a "tag"?</li>
38 <li>DSCM redux: Revisionist versioning.</li>
39 </ul>
40 </ul>
41 </ul>
42 </li>
43 <li>Basic explanation of <i>merge</i>.
44 <ol>
45 <li>Leaves, branches and baselines: We want a shrubbery!</li>
46 <li><i>update</i> merges vs. <i>merge</i> merges.
47 All merges are equal, but some are more equal than others.</li>
48 </ol>
49 </li>
50 </ul>
51
52 3. Configuration
53
54 42. General
55 <ul>
56 <li>Co-ordinate style and tone with drh, other devs. (documentation
57 standard? yuck.)</li>
58 </ul>
59
60 * Tips & tricks.
61
62 * <b>Fossil</b> and <b>Sqlite</b>
63 <ul>
64 <li>Get a word in for Mrinal Kant's
65 <a href="http://code.google.com/p/sqlite-manager/">SQLite Manager</a>
66 XUL app. Great tool.</li>
67 </ul>
68
69 * Th (code groveling &#91;and code groveling {and code groveling ... } ... &#93; ... )
--- a/kktodo.wiki
+++ b/kktodo.wiki
@@ -1,69 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
D rse-notes.txt
-198
--- a/rse-notes.txt
+++ b/rse-notes.txt
@@ -1,198 +0,0 @@
1
-From: "Ralf S. Engelschall"
2
-Date: October 18, 2008 1:40:53 PM EDT
3
-To: [email protected]
4
-Subject: Some Fossil Feedback
5
-
6
-I've today looked at your Fossil project (latest version from your
7
-repository). That's a _really_ interesting and very promising DVCS.
8
-While I looked around and tested it, I stumbled over some issues I want
9
-to share with you:
10
-
11
-o No tarball
12
-
13
- You currently still do not provide any tarballs of the Fossil sources.
14
- Sure, you are still hacking wild on the code and one can on-the-fly
15
- fetch a ZIP archive, but that's a manual process. For packagers (like
16
- me in the OpenPKG project) this is very nasty and just means that
17
- Fossil will usually still not be packaged. As a result it will be not
18
- spreaded as much as possible and this way you still do not get as much
19
- as possible feedback. Hence, I recommend that you let daily snapshot
20
- tarballs (or ZIP files) be rolled. This would be great.
21
-
22
-o UUID
23
-
24
- Under http://www.fossil-scm.org/index.html/doc/tip/www/concepts.wiki
25
- you describe the concepts and you clearly name the artifact ID a
26
- "UUID" and even say that this is a "Universally Unique Identifier".
27
- Unfortunately, a UUID is a 128-bit entity standardized by the ISO
28
- (under ISO/IEC 11578:1996) and IETF (under RFC-4122) and hence it is
29
- *VERY MUCH* confusing and unclean that your 160-bit SHA1-based ID is
30
- called "UUID" in Fossil.
31
-
32
- I *STRONGLY* recommend you to either use real UUIDs (128-bit
33
- entities, where a UUID of version 5 even is SHA1-based!) or you name
34
- your 160-bit SHA1 entities differently (perhaps AID for "Artifact
35
- Identifier"?).
36
-
37
-o "fossil cgi <script>"
38
-
39
- Currently we have only "fossil cgi <script>" where <script> contains
40
- "repository: <file>". This is a neat idea and should be kept. But
41
- this way one cannot easily host multiple repositories over this
42
- CGI interface without creating such a script for every individual
43
- repository.
44
-
45
- Perhaps a "fossil cgi --repository <file>" would help here, as this
46
- way one can use a generic CGI script which first figures out the
47
- name <name> of the individual project and then runs "fossil cgi
48
- --repository /path/to/repositories/<name>.db". But perhaps I'm just
49
- overlooking something and this is already possible...
50
-
51
-o "fossil db <operation>"
52
-
53
- In Monotone DVCS we have a "mtn db" command for the low-level SQLite
54
- database manipulations. For instance a "mtn --db=<monotone-repository>
55
- db dump" is more or less equal to a "sqlite3 <monotone-repository>
56
- .dump". A "mtn --db=<monotone-repository> db exec '<SQL>'" is equal
57
- "echo '<SQL>' | sqlite3 <monotone-repository>", etc. The point is
58
- that the DVCS user usually has no SQLite CLI at hand but as the DVCS
59
- already contains more or less the complete SQLite it is very useful to
60
- also include the SQLite CLI functionality and wire it into the DVCS
61
- CLI via a "db" command.
62
-
63
-o "fossil version"
64
-
65
- Mostly all VCS I know if either support a command "version" or a
66
- command-line option "--version" or most of the time even both. Please
67
- output the "This is fossil version [9e80dc66cf] 2008-10-18 13:03:36"
68
- there (at least additionally) instead of at the end of "fossil help".
69
-
70
-o "--port" vs. "-port"
71
-
72
- In the "fossil help server" there is "--port" while under
73
- http://www.fossil-scm.org/index.html/doc/tip/www/quickstart.wiki there
74
- is "-port". I personally like GNU-long-style options "--xxxx" more
75
- than the CC-style options "-xxx". But anyway, independent which one is
76
- correct (well, perhaps both even work) only one should be documented
77
- to avoid confusion.
78
-
79
-o User creation on the CLI
80
-
81
- There is "fossil user new ?USERNAME?" which interactively prompts
82
- for the capabilities and the password -- even from the TTY and not
83
- from STDIN. One needs "fossil user new ?USERNAME? ?CAPABILITIES?
84
- ?PASSWORD?" to be able to create a repository in batch without having
85
- to hack the user into the "user" table via the SQLite CLI. Similar:
86
- the "fossil user password USERNAME" should be actually "fossil user
87
- password USERNAME ?PASSWORD?", please.
88
-
89
-o "-R <repository"
90
-
91
- There is the "-R" option for specifiying the repository. But it is
92
- a sub-command option and not a global option. And on "fossil ui" or
93
- "fossil server" it even is an argument and not an option. This is
94
- confusing. Every time one has to figure out how to set the repository
95
- on the CLI. Monotone simply uses a *global* option "--db" and that's
96
- it. So, I recommend that Fossil also uses a single global option
97
- "--repository"/"-R" instead of a command-specific option. Sure, not
98
- all commands might require a repository, but IMHO it is better to
99
- ignore the global option there than having to figure out every time
100
- how the repository has to be specified.
101
-
102
-o Setup pages
103
-
104
- When hitting "Apply changes" on any setup page, one keeps staying on
105
- this page. Sure, that's what an "apply" button usually is about. But
106
- I at least would have liked to see a button (either instead of the
107
- "apply changes" or at least in addition) which applies the changes and
108
- goes back to the setup main page (from where one usually come).
109
-
110
-o _FOSSIL_
111
-
112
- Very nice idea to use another SQLite database for the _FOSSIL_
113
- control file. BUT: Why "_FOSSIL_"? CVS's "CVS" directory was ugly for
114
- decades. Today we have ".svn", ".git", ".hg" and "_MTN"/".mtn" to get
115
- rid of those ugly control files or directories of the DVCS! Sure,
116
- dot-files are disliked by Windows people. But that's no problem, one
117
- can accept "_XXX" in addition to ".XXX" easily, of course.
118
-
119
- So, I really would like to see the file "_FOSSIL_" to be renamed
120
- to ".fossil" under Unix and "_fossil" under Windows or (if the
121
- upper-case is important to you) ".FOSSIL" and "_FOSSIL". But to see
122
- an ugly "_FOSSIL_" at the top of every source tree is really rather
123
- boring for Unix people!
124
-
125
-o "fossil open", "fossil checkout", "fossil update".
126
-
127
- I'm personally confused that "fossil open" is what "checkout" does in
128
- other DVCS and that "checkout" is just a variant of "update". Hmmm...
129
- for me it looks at least one should be eleminated to reduce confusion.
130
- The difference between checkout and update could become an option of
131
- a single option. And the remaining to perhaps better should be either
132
- "open" + "update" or "checkout" + "update". Well, perhaps I'm still
133
- not understanding Fossil enough. But I can only tell that I got rather
134
- confused.
135
-
136
-o "fossil commit"
137
-
138
- There is "fossil commit" but no short-hand "fossil ci". But there
139
- is "fossil status" and even just "fossil st" which clearly shows
140
- that Fossil allows abbreviations or at least prefix-matching on the
141
- commands. Sure, "ci" is not a prefix of "commit" but mostly all VCS
142
- support the good old RCS/CVS "ci" and similar aliases. So I recommend
143
- that Fossil does not only alias matching, but also provides aliases:
144
- "ci" for "commit", "co" for "checkout", "log" for "timeline", etc.
145
- Sorry, having to type the long "fossil commit" every time is too long
146
- for us Unix hackers ;-)
147
-
148
- Additionally, Fossil seems to use GnuPG when installed and --nosign is
149
- not specified. Hmm... two questions arise here for me: 1. should the
150
- use of a cryptographically strong signature really be just _optional_
151
- (Monotone for instance RSA signs every commit) and 2. is GnuPG here
152
- really the right tool (Monotone does a plain RSA signing and is even
153
- able to leverage a running SSH agent for the operation -- something
154
- which is very cool both under Unix with "ssh-agent" and under Windows
155
- with "pagent"). OTOH, GnuPG 2.x supports a gpg-agent, so this might be
156
- no longer a big issue. But Fossil should document this a little bit
157
- futher: how to create the necessary GnuPG key, how to setup gpg-agent,
158
- etc.
159
-
160
-o "fossil diff"
161
-
162
- There is "Usage: fossil diff|gdiff ?-i? ?-r REVISION? FILE...". Two
163
- questions arise: Why do I have to specify a "FILE"? I would expect
164
- that a simple "fossil diff" recursively shows a "diff" of all changed
165
- files in the source tree. Additionally, how does one do a diff between
166
- two particular revisions (one seems to be not able to specifiy "-r"
167
- twice).
168
-
169
-o "manifest" / "manifest.uuid"
170
-
171
- Above I was already bothered by the _FOSSIL_ file, but now that I
172
- played with Fossil I see that "manifest" and "manifest.uuid" files
173
- showed up in my source tree. Why is this not implicitly in the
174
- database and instead externally represented in the source tree.
175
- Hmmm... then I recommend that you use a .fossil *DIRECTORY*, place
176
- the control file into .fossil/control (or whatever) and the manifest
177
- stuff into .fossil/manifest and .fossil/manifest.uuid. But please do
178
- not clutter the top-level of the source three with control data of the
179
- DVCS.
180
-
181
-o "fossil mv"
182
-
183
- There is "fossil add" and "fossil rm", but no "fossil mv". Hopefully
184
- this doesn't mean a file move is an "add" and a "remove" bundle, as
185
- this way Fossil would have trouble to know that the file was renamed
186
- and hence the full history tracking of a file seems to be broken.
187
-
188
-o "fossil changes" vs. "fossil status"
189
-
190
- Finally, I got confused by the "fossil changes" and "fossil status"
191
- commands. "fossil status" seems to be a super-set of "fossil changes".
192
- Looks a little bit less orthogonal than necessary. I would remove
193
- "fossil changes" or at least do not show the file details on "fossil
194
- status".
195
-
196
-Yours,
197
- Ralf S. Engelschall
198
-
--- a/rse-notes.txt
+++ b/rse-notes.txt
@@ -1,198 +0,0 @@
1 From: "Ralf S. Engelschall"
2 Date: October 18, 2008 1:40:53 PM EDT
3 To: [email protected]
4 Subject: Some Fossil Feedback
5
6 I've today looked at your Fossil project (latest version from your
7 repository). That's a _really_ interesting and very promising DVCS.
8 While I looked around and tested it, I stumbled over some issues I want
9 to share with you:
10
11 o No tarball
12
13 You currently still do not provide any tarballs of the Fossil sources.
14 Sure, you are still hacking wild on the code and one can on-the-fly
15 fetch a ZIP archive, but that's a manual process. For packagers (like
16 me in the OpenPKG project) this is very nasty and just means that
17 Fossil will usually still not be packaged. As a result it will be not
18 spreaded as much as possible and this way you still do not get as much
19 as possible feedback. Hence, I recommend that you let daily snapshot
20 tarballs (or ZIP files) be rolled. This would be great.
21
22 o UUID
23
24 Under http://www.fossil-scm.org/index.html/doc/tip/www/concepts.wiki
25 you describe the concepts and you clearly name the artifact ID a
26 "UUID" and even say that this is a "Universally Unique Identifier".
27 Unfortunately, a UUID is a 128-bit entity standardized by the ISO
28 (under ISO/IEC 11578:1996) and IETF (under RFC-4122) and hence it is
29 *VERY MUCH* confusing and unclean that your 160-bit SHA1-based ID is
30 called "UUID" in Fossil.
31
32 I *STRONGLY* recommend you to either use real UUIDs (128-bit
33 entities, where a UUID of version 5 even is SHA1-based!) or you name
34 your 160-bit SHA1 entities differently (perhaps AID for "Artifact
35 Identifier"?).
36
37 o "fossil cgi <script>"
38
39 Currently we have only "fossil cgi <script>" where <script> contains
40 "repository: <file>". This is a neat idea and should be kept. But
41 this way one cannot easily host multiple repositories over this
42 CGI interface without creating such a script for every individual
43 repository.
44
45 Perhaps a "fossil cgi --repository <file>" would help here, as this
46 way one can use a generic CGI script which first figures out the
47 name <name> of the individual project and then runs "fossil cgi
48 --repository /path/to/repositories/<name>.db". But perhaps I'm just
49 overlooking something and this is already possible...
50
51 o "fossil db <operation>"
52
53 In Monotone DVCS we have a "mtn db" command for the low-level SQLite
54 database manipulations. For instance a "mtn --db=<monotone-repository>
55 db dump" is more or less equal to a "sqlite3 <monotone-repository>
56 .dump". A "mtn --db=<monotone-repository> db exec '<SQL>'" is equal
57 "echo '<SQL>' | sqlite3 <monotone-repository>", etc. The point is
58 that the DVCS user usually has no SQLite CLI at hand but as the DVCS
59 already contains more or less the complete SQLite it is very useful to
60 also include the SQLite CLI functionality and wire it into the DVCS
61 CLI via a "db" command.
62
63 o "fossil version"
64
65 Mostly all VCS I know if either support a command "version" or a
66 command-line option "--version" or most of the time even both. Please
67 output the "This is fossil version [9e80dc66cf] 2008-10-18 13:03:36"
68 there (at least additionally) instead of at the end of "fossil help".
69
70 o "--port" vs. "-port"
71
72 In the "fossil help server" there is "--port" while under
73 http://www.fossil-scm.org/index.html/doc/tip/www/quickstart.wiki there
74 is "-port". I personally like GNU-long-style options "--xxxx" more
75 than the CC-style options "-xxx". But anyway, independent which one is
76 correct (well, perhaps both even work) only one should be documented
77 to avoid confusion.
78
79 o User creation on the CLI
80
81 There is "fossil user new ?USERNAME?" which interactively prompts
82 for the capabilities and the password -- even from the TTY and not
83 from STDIN. One needs "fossil user new ?USERNAME? ?CAPABILITIES?
84 ?PASSWORD?" to be able to create a repository in batch without having
85 to hack the user into the "user" table via the SQLite CLI. Similar:
86 the "fossil user password USERNAME" should be actually "fossil user
87 password USERNAME ?PASSWORD?", please.
88
89 o "-R <repository"
90
91 There is the "-R" option for specifiying the repository. But it is
92 a sub-command option and not a global option. And on "fossil ui" or
93 "fossil server" it even is an argument and not an option. This is
94 confusing. Every time one has to figure out how to set the repository
95 on the CLI. Monotone simply uses a *global* option "--db" and that's
96 it. So, I recommend that Fossil also uses a single global option
97 "--repository"/"-R" instead of a command-specific option. Sure, not
98 all commands might require a repository, but IMHO it is better to
99 ignore the global option there than having to figure out every time
100 how the repository has to be specified.
101
102 o Setup pages
103
104 When hitting "Apply changes" on any setup page, one keeps staying on
105 this page. Sure, that's what an "apply" button usually is about. But
106 I at least would have liked to see a button (either instead of the
107 "apply changes" or at least in addition) which applies the changes and
108 goes back to the setup main page (from where one usually come).
109
110 o _FOSSIL_
111
112 Very nice idea to use another SQLite database for the _FOSSIL_
113 control file. BUT: Why "_FOSSIL_"? CVS's "CVS" directory was ugly for
114 decades. Today we have ".svn", ".git", ".hg" and "_MTN"/".mtn" to get
115 rid of those ugly control files or directories of the DVCS! Sure,
116 dot-files are disliked by Windows people. But that's no problem, one
117 can accept "_XXX" in addition to ".XXX" easily, of course.
118
119 So, I really would like to see the file "_FOSSIL_" to be renamed
120 to ".fossil" under Unix and "_fossil" under Windows or (if the
121 upper-case is important to you) ".FOSSIL" and "_FOSSIL". But to see
122 an ugly "_FOSSIL_" at the top of every source tree is really rather
123 boring for Unix people!
124
125 o "fossil open", "fossil checkout", "fossil update".
126
127 I'm personally confused that "fossil open" is what "checkout" does in
128 other DVCS and that "checkout" is just a variant of "update". Hmmm...
129 for me it looks at least one should be eleminated to reduce confusion.
130 The difference between checkout and update could become an option of
131 a single option. And the remaining to perhaps better should be either
132 "open" + "update" or "checkout" + "update". Well, perhaps I'm still
133 not understanding Fossil enough. But I can only tell that I got rather
134 confused.
135
136 o "fossil commit"
137
138 There is "fossil commit" but no short-hand "fossil ci". But there
139 is "fossil status" and even just "fossil st" which clearly shows
140 that Fossil allows abbreviations or at least prefix-matching on the
141 commands. Sure, "ci" is not a prefix of "commit" but mostly all VCS
142 support the good old RCS/CVS "ci" and similar aliases. So I recommend
143 that Fossil does not only alias matching, but also provides aliases:
144 "ci" for "commit", "co" for "checkout", "log" for "timeline", etc.
145 Sorry, having to type the long "fossil commit" every time is too long
146 for us Unix hackers ;-)
147
148 Additionally, Fossil seems to use GnuPG when installed and --nosign is
149 not specified. Hmm... two questions arise here for me: 1. should the
150 use of a cryptographically strong signature really be just _optional_
151 (Monotone for instance RSA signs every commit) and 2. is GnuPG here
152 really the right tool (Monotone does a plain RSA signing and is even
153 able to leverage a running SSH agent for the operation -- something
154 which is very cool both under Unix with "ssh-agent" and under Windows
155 with "pagent"). OTOH, GnuPG 2.x supports a gpg-agent, so this might be
156 no longer a big issue. But Fossil should document this a little bit
157 futher: how to create the necessary GnuPG key, how to setup gpg-agent,
158 etc.
159
160 o "fossil diff"
161
162 There is "Usage: fossil diff|gdiff ?-i? ?-r REVISION? FILE...". Two
163 questions arise: Why do I have to specify a "FILE"? I would expect
164 that a simple "fossil diff" recursively shows a "diff" of all changed
165 files in the source tree. Additionally, how does one do a diff between
166 two particular revisions (one seems to be not able to specifiy "-r"
167 twice).
168
169 o "manifest" / "manifest.uuid"
170
171 Above I was already bothered by the _FOSSIL_ file, but now that I
172 played with Fossil I see that "manifest" and "manifest.uuid" files
173 showed up in my source tree. Why is this not implicitly in the
174 database and instead externally represented in the source tree.
175 Hmmm... then I recommend that you use a .fossil *DIRECTORY*, place
176 the control file into .fossil/control (or whatever) and the manifest
177 stuff into .fossil/manifest and .fossil/manifest.uuid. But please do
178 not clutter the top-level of the source three with control data of the
179 DVCS.
180
181 o "fossil mv"
182
183 There is "fossil add" and "fossil rm", but no "fossil mv". Hopefully
184 this doesn't mean a file move is an "add" and a "remove" bundle, as
185 this way Fossil would have trouble to know that the file was renamed
186 and hence the full history tracking of a file seems to be broken.
187
188 o "fossil changes" vs. "fossil status"
189
190 Finally, I got confused by the "fossil changes" and "fossil status"
191 commands. "fossil status" seems to be a super-set of "fossil changes".
192 Looks a little bit less orthogonal than necessary. I would remove
193 "fossil changes" or at least do not show the file details on "fossil
194 status".
195
196 Yours,
197 Ralf S. Engelschall
198
--- a/rse-notes.txt
+++ b/rse-notes.txt
@@ -1,198 +0,0 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
+18 -9
--- src/add.c
+++ src/add.c
@@ -108,11 +108,11 @@
108108
}else{
109109
char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
110110
db_multi_exec(
111111
"INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)"
112112
"VALUES(%d,0,0,0,%Q,%d,%d)",
113
- vid, zPath, file_isexe(zFullname), file_islink(zFullname));
113
+ vid, zPath, file_wd_isexe(zFullname), file_wd_islink(zFullname));
114114
fossil_free(zFullname);
115115
}
116116
if( db_changes() ){
117117
fossil_print("ADDED %s\n", zPath);
118118
return 1;
@@ -181,12 +181,17 @@
181181
** The --ignore option is a comma-separate list of glob patterns for files
182182
** to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore option
183183
** does not appear on the command line then the "ignore-glob" setting is
184184
** used.
185185
**
186
-** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
187
-** Options: --dotfiles, --ignore
186
+** Options:
187
+**
188
+** --dotfiles include files beginning with a dot (".")
189
+** --ignore <CSG> ignore files matching patterns from the
190
+** comma separated list of glob patterns.
191
+**
192
+** See also: addremove, rm
188193
*/
189194
void add_cmd(void){
190195
int i; /* Loop counter */
191196
int vid; /* Currently checked out version */
192197
int nRoot; /* Full path characters in g.zLocalRoot */
@@ -259,12 +264,11 @@
259264
**
260265
** This command does NOT remove the files from disk. It just marks the
261266
** files as no longer being part of the project. In other words, future
262267
** changes to the named files will not be versioned.
263268
**
264
-** SUMMARY: fossil rm FILE1 ?FILE2 ...?
265
-** or: fossil delete FILE1 ?FILE2 ...?
269
+** See also: addremove, add
266270
*/
267271
void delete_cmd(void){
268272
int i;
269273
int vid;
270274
Stmt loop;
@@ -344,11 +348,11 @@
344348
}
345349
346350
/*
347351
** COMMAND: addremove
348352
**
349
-** Usage: %fossil addremove ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
353
+** Usage: %fossil addremove ?OPTIONS?
350354
**
351355
** Do all necessary "add" and "rm" commands to synchronize the repository
352356
** with the content of the working checkout:
353357
**
354358
** * All files in the checkout but not in the repository (that is,
@@ -369,13 +373,18 @@
369373
** documentation on the "settings" command for further information.
370374
**
371375
** The --test option shows what would happen without actually doing anything.
372376
**
373377
** This command can be used to track third party software.
378
+**
379
+** Options:
380
+** --dotfiles include files beginning with a dot (".")
381
+** --ignore <CSG> ignore files matching patterns from the
382
+** comma separated list of glob patterns.
383
+** --test If given, show what would be done without doing so.
374384
**
375
-** SUMMARY: fossil addremove
376
-** Options: ?--dotfiles? ?--ignore GLOB? ?--test? ?--case-sensitive BOOL?
385
+** See also: add, rm
377386
*/
378387
void addremove_cmd(void){
379388
Blob path;
380389
const char *zIgnoreFlag = find_option("ignore",0,1);
381390
int allFlag = find_option("dotfiles",0,0)!=0;
@@ -426,11 +435,11 @@
426435
const char * zFile;
427436
const char * zPath;
428437
429438
zFile = db_column_text(&q, 0);
430439
zPath = db_column_text(&q, 1);
431
- if( !file_isfile_or_link(zPath) ){
440
+ if( !file_wd_isfile_or_link(zPath) ){
432441
if( !isTest ){
433442
db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
434443
}
435444
fossil_print("DELETED %s\n", zFile);
436445
nDelete++;
437446
--- src/add.c
+++ src/add.c
@@ -108,11 +108,11 @@
108 }else{
109 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
110 db_multi_exec(
111 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)"
112 "VALUES(%d,0,0,0,%Q,%d,%d)",
113 vid, zPath, file_isexe(zFullname), file_islink(zFullname));
114 fossil_free(zFullname);
115 }
116 if( db_changes() ){
117 fossil_print("ADDED %s\n", zPath);
118 return 1;
@@ -181,12 +181,17 @@
181 ** The --ignore option is a comma-separate list of glob patterns for files
182 ** to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore option
183 ** does not appear on the command line then the "ignore-glob" setting is
184 ** used.
185 **
186 ** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
187 ** Options: --dotfiles, --ignore
 
 
 
 
 
188 */
189 void add_cmd(void){
190 int i; /* Loop counter */
191 int vid; /* Currently checked out version */
192 int nRoot; /* Full path characters in g.zLocalRoot */
@@ -259,12 +264,11 @@
259 **
260 ** This command does NOT remove the files from disk. It just marks the
261 ** files as no longer being part of the project. In other words, future
262 ** changes to the named files will not be versioned.
263 **
264 ** SUMMARY: fossil rm FILE1 ?FILE2 ...?
265 ** or: fossil delete FILE1 ?FILE2 ...?
266 */
267 void delete_cmd(void){
268 int i;
269 int vid;
270 Stmt loop;
@@ -344,11 +348,11 @@
344 }
345
346 /*
347 ** COMMAND: addremove
348 **
349 ** Usage: %fossil addremove ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
350 **
351 ** Do all necessary "add" and "rm" commands to synchronize the repository
352 ** with the content of the working checkout:
353 **
354 ** * All files in the checkout but not in the repository (that is,
@@ -369,13 +373,18 @@
369 ** documentation on the "settings" command for further information.
370 **
371 ** The --test option shows what would happen without actually doing anything.
372 **
373 ** This command can be used to track third party software.
 
 
 
 
 
 
374 **
375 ** SUMMARY: fossil addremove
376 ** Options: ?--dotfiles? ?--ignore GLOB? ?--test? ?--case-sensitive BOOL?
377 */
378 void addremove_cmd(void){
379 Blob path;
380 const char *zIgnoreFlag = find_option("ignore",0,1);
381 int allFlag = find_option("dotfiles",0,0)!=0;
@@ -426,11 +435,11 @@
426 const char * zFile;
427 const char * zPath;
428
429 zFile = db_column_text(&q, 0);
430 zPath = db_column_text(&q, 1);
431 if( !file_isfile_or_link(zPath) ){
432 if( !isTest ){
433 db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
434 }
435 fossil_print("DELETED %s\n", zFile);
436 nDelete++;
437
--- src/add.c
+++ src/add.c
@@ -108,11 +108,11 @@
108 }else{
109 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
110 db_multi_exec(
111 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)"
112 "VALUES(%d,0,0,0,%Q,%d,%d)",
113 vid, zPath, file_wd_isexe(zFullname), file_wd_islink(zFullname));
114 fossil_free(zFullname);
115 }
116 if( db_changes() ){
117 fossil_print("ADDED %s\n", zPath);
118 return 1;
@@ -181,12 +181,17 @@
181 ** The --ignore option is a comma-separate list of glob patterns for files
182 ** to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore option
183 ** does not appear on the command line then the "ignore-glob" setting is
184 ** used.
185 **
186 ** Options:
187 **
188 ** --dotfiles include files beginning with a dot (".")
189 ** --ignore <CSG> ignore files matching patterns from the
190 ** comma separated list of glob patterns.
191 **
192 ** See also: addremove, rm
193 */
194 void add_cmd(void){
195 int i; /* Loop counter */
196 int vid; /* Currently checked out version */
197 int nRoot; /* Full path characters in g.zLocalRoot */
@@ -259,12 +264,11 @@
264 **
265 ** This command does NOT remove the files from disk. It just marks the
266 ** files as no longer being part of the project. In other words, future
267 ** changes to the named files will not be versioned.
268 **
269 ** See also: addremove, add
 
270 */
271 void delete_cmd(void){
272 int i;
273 int vid;
274 Stmt loop;
@@ -344,11 +348,11 @@
348 }
349
350 /*
351 ** COMMAND: addremove
352 **
353 ** Usage: %fossil addremove ?OPTIONS?
354 **
355 ** Do all necessary "add" and "rm" commands to synchronize the repository
356 ** with the content of the working checkout:
357 **
358 ** * All files in the checkout but not in the repository (that is,
@@ -369,13 +373,18 @@
373 ** documentation on the "settings" command for further information.
374 **
375 ** The --test option shows what would happen without actually doing anything.
376 **
377 ** This command can be used to track third party software.
378 **
379 ** Options:
380 ** --dotfiles include files beginning with a dot (".")
381 ** --ignore <CSG> ignore files matching patterns from the
382 ** comma separated list of glob patterns.
383 ** --test If given, show what would be done without doing so.
384 **
385 ** See also: add, rm
 
386 */
387 void addremove_cmd(void){
388 Blob path;
389 const char *zIgnoreFlag = find_option("ignore",0,1);
390 int allFlag = find_option("dotfiles",0,0)!=0;
@@ -426,11 +435,11 @@
435 const char * zFile;
436 const char * zPath;
437
438 zFile = db_column_text(&q, 0);
439 zPath = db_column_text(&q, 1);
440 if( !file_wd_isfile_or_link(zPath) ){
441 if( !isTest ){
442 db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
443 }
444 fossil_print("DELETED %s\n", zFile);
445 nDelete++;
446
+10 -10
--- src/attach.c
+++ src/attach.c
@@ -46,19 +46,19 @@
4646
"SELECT datetime(mtime,'localtime'), src, target, filename, comment, user"
4747
" FROM attachment",
4848
-1
4949
);
5050
if( zPage ){
51
- if( g.okRdWiki==0 ) login_needed();
51
+ if( g.perm.RdWiki==0 ) login_needed();
5252
style_header("Attachments To %h", zPage);
5353
blob_appendf(&sql, " WHERE target=%Q", zPage);
5454
}else if( zTkt ){
55
- if( g.okRdTkt==0 ) login_needed();
55
+ if( g.perm.RdTkt==0 ) login_needed();
5656
style_header("Attachments To Ticket %.10s", zTkt);
5757
blob_appendf(&sql, " WHERE target GLOB '%q*'", zTkt);
5858
}else{
59
- if( g.okRdTkt==0 && g.okRdWiki==0 ) login_needed();
59
+ if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ) login_needed();
6060
style_header("All Attachments");
6161
}
6262
blob_appendf(&sql, " ORDER BY mtime DESC");
6363
db_prepare(&q, "%s", blob_str(&sql));
6464
while( db_step(&q)==SQLITE_ROW ){
@@ -139,14 +139,14 @@
139139
140140
if( zPage && zTkt ) zTkt = 0;
141141
if( zFile==0 ) fossil_redirect_home();
142142
login_check_credentials();
143143
if( zPage ){
144
- if( g.okRdWiki==0 ) login_needed();
144
+ if( g.perm.RdWiki==0 ) login_needed();
145145
zTarget = zPage;
146146
}else if( zTkt ){
147
- if( g.okRdTkt==0 ) login_needed();
147
+ if( g.perm.RdTkt==0 ) login_needed();
148148
zTarget = zTkt;
149149
}else{
150150
fossil_redirect_home();
151151
}
152152
if( attachid>0 ){
@@ -172,11 +172,11 @@
172172
style_header("Missing");
173173
@ Attachment has been deleted
174174
style_footer();
175175
return;
176176
}
177
- g.okRead = 1;
177
+ g.perm.Read = 1;
178178
cgi_replace_parameter("name",zUUID);
179179
if( fossil_strcmp(g.zPath,"attachview")==0 ){
180180
artifact_page();
181181
}else{
182182
cgi_replace_parameter("m", mimetype_from_name(zFile));
@@ -207,19 +207,19 @@
207207
if( P("cancel") ) cgi_redirect(zFrom);
208208
if( zPage && zTkt ) fossil_redirect_home();
209209
if( zPage==0 && zTkt==0 ) fossil_redirect_home();
210210
login_check_credentials();
211211
if( zPage ){
212
- if( g.okApndWiki==0 || g.okAttach==0 ) login_needed();
212
+ if( g.perm.ApndWiki==0 || g.perm.Attach==0 ) login_needed();
213213
if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
214214
fossil_redirect_home();
215215
}
216216
zTarget = zPage;
217217
zTargetType = mprintf("Wiki Page <a href=\"%s/wiki?name=%h\">%h</a>",
218218
g.zTop, zPage, zPage);
219219
}else{
220
- if( g.okApndTkt==0 || g.okAttach==0 ) login_needed();
220
+ if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
221221
if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
222222
zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
223223
" WHERE tagname GLOB 'tkt-%q*'", zTkt);
224224
if( zTkt==0 ) fossil_redirect_home();
225225
}
@@ -313,14 +313,14 @@
313313
if( zPage && zTkt ) fossil_redirect_home();
314314
if( zPage==0 && zTkt==0 ) fossil_redirect_home();
315315
if( zFile==0 ) fossil_redirect_home();
316316
login_check_credentials();
317317
if( zPage ){
318
- if( g.okWrWiki==0 || g.okAttach==0 ) login_needed();
318
+ if( g.perm.WrWiki==0 || g.perm.Attach==0 ) login_needed();
319319
zTarget = zPage;
320320
}else{
321
- if( g.okWrTkt==0 || g.okAttach==0 ) login_needed();
321
+ if( g.perm.WrTkt==0 || g.perm.Attach==0 ) login_needed();
322322
zTarget = zTkt;
323323
}
324324
if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
325325
if( P("cancel") ){
326326
cgi_redirect(zFrom);
327327
--- src/attach.c
+++ src/attach.c
@@ -46,19 +46,19 @@
46 "SELECT datetime(mtime,'localtime'), src, target, filename, comment, user"
47 " FROM attachment",
48 -1
49 );
50 if( zPage ){
51 if( g.okRdWiki==0 ) login_needed();
52 style_header("Attachments To %h", zPage);
53 blob_appendf(&sql, " WHERE target=%Q", zPage);
54 }else if( zTkt ){
55 if( g.okRdTkt==0 ) login_needed();
56 style_header("Attachments To Ticket %.10s", zTkt);
57 blob_appendf(&sql, " WHERE target GLOB '%q*'", zTkt);
58 }else{
59 if( g.okRdTkt==0 && g.okRdWiki==0 ) login_needed();
60 style_header("All Attachments");
61 }
62 blob_appendf(&sql, " ORDER BY mtime DESC");
63 db_prepare(&q, "%s", blob_str(&sql));
64 while( db_step(&q)==SQLITE_ROW ){
@@ -139,14 +139,14 @@
139
140 if( zPage && zTkt ) zTkt = 0;
141 if( zFile==0 ) fossil_redirect_home();
142 login_check_credentials();
143 if( zPage ){
144 if( g.okRdWiki==0 ) login_needed();
145 zTarget = zPage;
146 }else if( zTkt ){
147 if( g.okRdTkt==0 ) login_needed();
148 zTarget = zTkt;
149 }else{
150 fossil_redirect_home();
151 }
152 if( attachid>0 ){
@@ -172,11 +172,11 @@
172 style_header("Missing");
173 @ Attachment has been deleted
174 style_footer();
175 return;
176 }
177 g.okRead = 1;
178 cgi_replace_parameter("name",zUUID);
179 if( fossil_strcmp(g.zPath,"attachview")==0 ){
180 artifact_page();
181 }else{
182 cgi_replace_parameter("m", mimetype_from_name(zFile));
@@ -207,19 +207,19 @@
207 if( P("cancel") ) cgi_redirect(zFrom);
208 if( zPage && zTkt ) fossil_redirect_home();
209 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
210 login_check_credentials();
211 if( zPage ){
212 if( g.okApndWiki==0 || g.okAttach==0 ) login_needed();
213 if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
214 fossil_redirect_home();
215 }
216 zTarget = zPage;
217 zTargetType = mprintf("Wiki Page <a href=\"%s/wiki?name=%h\">%h</a>",
218 g.zTop, zPage, zPage);
219 }else{
220 if( g.okApndTkt==0 || g.okAttach==0 ) login_needed();
221 if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
222 zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
223 " WHERE tagname GLOB 'tkt-%q*'", zTkt);
224 if( zTkt==0 ) fossil_redirect_home();
225 }
@@ -313,14 +313,14 @@
313 if( zPage && zTkt ) fossil_redirect_home();
314 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
315 if( zFile==0 ) fossil_redirect_home();
316 login_check_credentials();
317 if( zPage ){
318 if( g.okWrWiki==0 || g.okAttach==0 ) login_needed();
319 zTarget = zPage;
320 }else{
321 if( g.okWrTkt==0 || g.okAttach==0 ) login_needed();
322 zTarget = zTkt;
323 }
324 if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
325 if( P("cancel") ){
326 cgi_redirect(zFrom);
327
--- src/attach.c
+++ src/attach.c
@@ -46,19 +46,19 @@
46 "SELECT datetime(mtime,'localtime'), src, target, filename, comment, user"
47 " FROM attachment",
48 -1
49 );
50 if( zPage ){
51 if( g.perm.RdWiki==0 ) login_needed();
52 style_header("Attachments To %h", zPage);
53 blob_appendf(&sql, " WHERE target=%Q", zPage);
54 }else if( zTkt ){
55 if( g.perm.RdTkt==0 ) login_needed();
56 style_header("Attachments To Ticket %.10s", zTkt);
57 blob_appendf(&sql, " WHERE target GLOB '%q*'", zTkt);
58 }else{
59 if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ) login_needed();
60 style_header("All Attachments");
61 }
62 blob_appendf(&sql, " ORDER BY mtime DESC");
63 db_prepare(&q, "%s", blob_str(&sql));
64 while( db_step(&q)==SQLITE_ROW ){
@@ -139,14 +139,14 @@
139
140 if( zPage && zTkt ) zTkt = 0;
141 if( zFile==0 ) fossil_redirect_home();
142 login_check_credentials();
143 if( zPage ){
144 if( g.perm.RdWiki==0 ) login_needed();
145 zTarget = zPage;
146 }else if( zTkt ){
147 if( g.perm.RdTkt==0 ) login_needed();
148 zTarget = zTkt;
149 }else{
150 fossil_redirect_home();
151 }
152 if( attachid>0 ){
@@ -172,11 +172,11 @@
172 style_header("Missing");
173 @ Attachment has been deleted
174 style_footer();
175 return;
176 }
177 g.perm.Read = 1;
178 cgi_replace_parameter("name",zUUID);
179 if( fossil_strcmp(g.zPath,"attachview")==0 ){
180 artifact_page();
181 }else{
182 cgi_replace_parameter("m", mimetype_from_name(zFile));
@@ -207,19 +207,19 @@
207 if( P("cancel") ) cgi_redirect(zFrom);
208 if( zPage && zTkt ) fossil_redirect_home();
209 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
210 login_check_credentials();
211 if( zPage ){
212 if( g.perm.ApndWiki==0 || g.perm.Attach==0 ) login_needed();
213 if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
214 fossil_redirect_home();
215 }
216 zTarget = zPage;
217 zTargetType = mprintf("Wiki Page <a href=\"%s/wiki?name=%h\">%h</a>",
218 g.zTop, zPage, zPage);
219 }else{
220 if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
221 if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
222 zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
223 " WHERE tagname GLOB 'tkt-%q*'", zTkt);
224 if( zTkt==0 ) fossil_redirect_home();
225 }
@@ -313,14 +313,14 @@
313 if( zPage && zTkt ) fossil_redirect_home();
314 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
315 if( zFile==0 ) fossil_redirect_home();
316 login_check_credentials();
317 if( zPage ){
318 if( g.perm.WrWiki==0 || g.perm.Attach==0 ) login_needed();
319 zTarget = zPage;
320 }else{
321 if( g.perm.WrTkt==0 || g.perm.Attach==0 ) login_needed();
322 zTarget = zTkt;
323 }
324 if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
325 if( P("cancel") ){
326 cgi_redirect(zFrom);
327
+1 -1
--- src/bisect.c
+++ src/bisect.c
@@ -42,11 +42,11 @@
4242
}
4343
bisect.good = db_lget_int("bisect-good", 0);
4444
if( bisect.good==0 ){
4545
fossil_fatal("no \"good\" version has been identified");
4646
}
47
- p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"));
47
+ p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"), 0);
4848
if( p==0 ){
4949
char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
5050
char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
5151
fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
5252
zGood, zBad);
5353
--- src/bisect.c
+++ src/bisect.c
@@ -42,11 +42,11 @@
42 }
43 bisect.good = db_lget_int("bisect-good", 0);
44 if( bisect.good==0 ){
45 fossil_fatal("no \"good\" version has been identified");
46 }
47 p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"));
48 if( p==0 ){
49 char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
50 char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
51 fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
52 zGood, zBad);
53
--- src/bisect.c
+++ src/bisect.c
@@ -42,11 +42,11 @@
42 }
43 bisect.good = db_lget_int("bisect-good", 0);
44 if( bisect.good==0 ){
45 fossil_fatal("no \"good\" version has been identified");
46 }
47 p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"), 0);
48 if( p==0 ){
49 char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
50 char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
51 fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
52 zGood, zBad);
53
+1 -1
--- src/blob.c
+++ src/blob.c
@@ -681,11 +681,11 @@
681681
FILE *in;
682682
if( zFilename==0 || zFilename[0]==0
683683
|| (zFilename[0]=='-' && zFilename[1]==0) ){
684684
return blob_read_from_channel(pBlob, stdin, -1);
685685
}
686
- size = file_size(zFilename);
686
+ size = file_wd_size(zFilename);
687687
blob_zero(pBlob);
688688
if( size<0 ){
689689
fossil_fatal("no such file: %s", zFilename);
690690
}
691691
if( size==0 ){
692692
--- src/blob.c
+++ src/blob.c
@@ -681,11 +681,11 @@
681 FILE *in;
682 if( zFilename==0 || zFilename[0]==0
683 || (zFilename[0]=='-' && zFilename[1]==0) ){
684 return blob_read_from_channel(pBlob, stdin, -1);
685 }
686 size = file_size(zFilename);
687 blob_zero(pBlob);
688 if( size<0 ){
689 fossil_fatal("no such file: %s", zFilename);
690 }
691 if( size==0 ){
692
--- src/blob.c
+++ src/blob.c
@@ -681,11 +681,11 @@
681 FILE *in;
682 if( zFilename==0 || zFilename[0]==0
683 || (zFilename[0]=='-' && zFilename[1]==0) ){
684 return blob_read_from_channel(pBlob, stdin, -1);
685 }
686 size = file_wd_size(zFilename);
687 blob_zero(pBlob);
688 if( size<0 ){
689 fossil_fatal("no such file: %s", zFilename);
690 }
691 if( size==0 ){
692
+9 -7
--- src/branch.c
+++ src/branch.c
@@ -217,11 +217,11 @@
217217
218218
219219
/*
220220
** COMMAND: branch
221221
**
222
-** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
222
+** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
223223
**
224224
** Run various subcommands to manage branches of the open repository or
225225
** of the repository identified by the -R or --repository option.
226226
**
227227
** %fossil branch new BRANCH-NAME BASIS ?--bgcolor COLOR? ?--private?
@@ -228,16 +228,18 @@
228228
**
229229
** Create a new branch BRANCH-NAME off of check-in BASIS.
230230
** You can optionally give the branch a default color. The
231231
** --private option makes the branch private.
232232
**
233
-** %fossil branch list
234
-** %fossil branch ls
233
+** %fossil branch list ?-all | --closed?
234
+** %fossil branch ls ?-all | --closed?
235235
**
236236
** List all branches. Use --all or --closed to list all branches
237237
** or closed branches. The default is to show only open branches.
238238
**
239
+** Options:
240
+** -R|--repository FILE Run commands on repository FILE
239241
*/
240242
void branch_cmd(void){
241243
int n;
242244
const char *zCmd = "list";
243245
db_find_and_open_repository(0, 0);
@@ -284,11 +286,11 @@
284286
int showClosed = P("closed")!=0;
285287
int showAll = P("all")!=0;
286288
int colorTest = P("colortest")!=0;
287289
288290
login_check_credentials();
289
- if( !g.okRead ){ login_needed(); return; }
291
+ if( !g.perm.Read ){ login_needed(); return; }
290292
if( colorTest ){
291293
showClosed = 0;
292294
showAll = 1;
293295
}
294296
@@ -346,11 +348,11 @@
346348
}
347349
if( colorTest ){
348350
const char *zColor = hash_color(zBr);
349351
@ <li><span style="background-color: %s(zColor)">
350352
@ %h(zBr) &rarr; %s(zColor)</span></li>
351
- }else if( g.okHistory ){
353
+ }else if( g.perm.History ){
352354
@ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
353355
}else{
354356
@ <li><b>%h(zBr)</b></li>
355357
}
356358
}
@@ -372,11 +374,11 @@
372374
** the timeline of a "brlist" page. Add some additional hyperlinks
373375
** to the end of the line.
374376
*/
375377
static void brtimeline_extra(int rid){
376378
Stmt q;
377
- if( !g.okHistory ) return;
379
+ if( !g.perm.History ) return;
378380
db_prepare(&q,
379381
"SELECT substr(tagname,5) FROM tagxref, tag"
380382
" WHERE tagxref.rid=%d"
381383
" AND tagxref.tagid=tag.tagid"
382384
" AND tagxref.tagtype>0"
@@ -397,11 +399,11 @@
397399
*/
398400
void brtimeline_page(void){
399401
Stmt q;
400402
401403
login_check_credentials();
402
- if( !g.okRead ){ login_needed(); return; }
404
+ if( !g.perm.Read ){ login_needed(); return; }
403405
404406
style_header("Branches");
405407
style_submenu_element("List", "List", "brlist");
406408
login_anonymous_available();
407409
@ <h2>The initial check-in for each branch:</h2>
408410
--- src/branch.c
+++ src/branch.c
@@ -217,11 +217,11 @@
217
218
219 /*
220 ** COMMAND: branch
221 **
222 ** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
223 **
224 ** Run various subcommands to manage branches of the open repository or
225 ** of the repository identified by the -R or --repository option.
226 **
227 ** %fossil branch new BRANCH-NAME BASIS ?--bgcolor COLOR? ?--private?
@@ -228,16 +228,18 @@
228 **
229 ** Create a new branch BRANCH-NAME off of check-in BASIS.
230 ** You can optionally give the branch a default color. The
231 ** --private option makes the branch private.
232 **
233 ** %fossil branch list
234 ** %fossil branch ls
235 **
236 ** List all branches. Use --all or --closed to list all branches
237 ** or closed branches. The default is to show only open branches.
238 **
 
 
239 */
240 void branch_cmd(void){
241 int n;
242 const char *zCmd = "list";
243 db_find_and_open_repository(0, 0);
@@ -284,11 +286,11 @@
284 int showClosed = P("closed")!=0;
285 int showAll = P("all")!=0;
286 int colorTest = P("colortest")!=0;
287
288 login_check_credentials();
289 if( !g.okRead ){ login_needed(); return; }
290 if( colorTest ){
291 showClosed = 0;
292 showAll = 1;
293 }
294
@@ -346,11 +348,11 @@
346 }
347 if( colorTest ){
348 const char *zColor = hash_color(zBr);
349 @ <li><span style="background-color: %s(zColor)">
350 @ %h(zBr) &rarr; %s(zColor)</span></li>
351 }else if( g.okHistory ){
352 @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
353 }else{
354 @ <li><b>%h(zBr)</b></li>
355 }
356 }
@@ -372,11 +374,11 @@
372 ** the timeline of a "brlist" page. Add some additional hyperlinks
373 ** to the end of the line.
374 */
375 static void brtimeline_extra(int rid){
376 Stmt q;
377 if( !g.okHistory ) return;
378 db_prepare(&q,
379 "SELECT substr(tagname,5) FROM tagxref, tag"
380 " WHERE tagxref.rid=%d"
381 " AND tagxref.tagid=tag.tagid"
382 " AND tagxref.tagtype>0"
@@ -397,11 +399,11 @@
397 */
398 void brtimeline_page(void){
399 Stmt q;
400
401 login_check_credentials();
402 if( !g.okRead ){ login_needed(); return; }
403
404 style_header("Branches");
405 style_submenu_element("List", "List", "brlist");
406 login_anonymous_available();
407 @ <h2>The initial check-in for each branch:</h2>
408
--- src/branch.c
+++ src/branch.c
@@ -217,11 +217,11 @@
217
218
219 /*
220 ** COMMAND: branch
221 **
222 ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
223 **
224 ** Run various subcommands to manage branches of the open repository or
225 ** of the repository identified by the -R or --repository option.
226 **
227 ** %fossil branch new BRANCH-NAME BASIS ?--bgcolor COLOR? ?--private?
@@ -228,16 +228,18 @@
228 **
229 ** Create a new branch BRANCH-NAME off of check-in BASIS.
230 ** You can optionally give the branch a default color. The
231 ** --private option makes the branch private.
232 **
233 ** %fossil branch list ?-all | --closed?
234 ** %fossil branch ls ?-all | --closed?
235 **
236 ** List all branches. Use --all or --closed to list all branches
237 ** or closed branches. The default is to show only open branches.
238 **
239 ** Options:
240 ** -R|--repository FILE Run commands on repository FILE
241 */
242 void branch_cmd(void){
243 int n;
244 const char *zCmd = "list";
245 db_find_and_open_repository(0, 0);
@@ -284,11 +286,11 @@
286 int showClosed = P("closed")!=0;
287 int showAll = P("all")!=0;
288 int colorTest = P("colortest")!=0;
289
290 login_check_credentials();
291 if( !g.perm.Read ){ login_needed(); return; }
292 if( colorTest ){
293 showClosed = 0;
294 showAll = 1;
295 }
296
@@ -346,11 +348,11 @@
348 }
349 if( colorTest ){
350 const char *zColor = hash_color(zBr);
351 @ <li><span style="background-color: %s(zColor)">
352 @ %h(zBr) &rarr; %s(zColor)</span></li>
353 }else if( g.perm.History ){
354 @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
355 }else{
356 @ <li><b>%h(zBr)</b></li>
357 }
358 }
@@ -372,11 +374,11 @@
374 ** the timeline of a "brlist" page. Add some additional hyperlinks
375 ** to the end of the line.
376 */
377 static void brtimeline_extra(int rid){
378 Stmt q;
379 if( !g.perm.History ) return;
380 db_prepare(&q,
381 "SELECT substr(tagname,5) FROM tagxref, tag"
382 " WHERE tagxref.rid=%d"
383 " AND tagxref.tagid=tag.tagid"
384 " AND tagxref.tagtype>0"
@@ -397,11 +399,11 @@
399 */
400 void brtimeline_page(void){
401 Stmt q;
402
403 login_check_credentials();
404 if( !g.perm.Read ){ login_needed(); return; }
405
406 style_header("Branches");
407 style_submenu_element("List", "List", "brlist");
408 login_anonymous_available();
409 @ <h2>The initial check-in for each branch:</h2>
410
+2 -2
--- src/browse.c
+++ src/browse.c
@@ -77,11 +77,11 @@
7777
int i, j;
7878
char *zSep = "";
7979
8080
for(i=0; zPath[i]; i=j){
8181
for(j=i; zPath[j] && zPath[j]!='/'; j++){}
82
- if( zPath[j] && g.okHistory ){
82
+ if( zPath[j] && g.perm.History ){
8383
if( zCI ){
8484
blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&amp;name=%#T\">%#h</a>",
8585
zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]);
8686
}else{
8787
blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
@@ -118,11 +118,11 @@
118118
Blob dirname;
119119
Manifest *pM = 0;
120120
const char *zSubdirLink;
121121
122122
login_check_credentials();
123
- if( !g.okHistory ){ login_needed(); return; }
123
+ if( !g.perm.History ){ login_needed(); return; }
124124
while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
125125
style_header("File List");
126126
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
127127
pathelementFunc, 0, 0);
128128
129129
--- src/browse.c
+++ src/browse.c
@@ -77,11 +77,11 @@
77 int i, j;
78 char *zSep = "";
79
80 for(i=0; zPath[i]; i=j){
81 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
82 if( zPath[j] && g.okHistory ){
83 if( zCI ){
84 blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&amp;name=%#T\">%#h</a>",
85 zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]);
86 }else{
87 blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
@@ -118,11 +118,11 @@
118 Blob dirname;
119 Manifest *pM = 0;
120 const char *zSubdirLink;
121
122 login_check_credentials();
123 if( !g.okHistory ){ login_needed(); return; }
124 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
125 style_header("File List");
126 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
127 pathelementFunc, 0, 0);
128
129
--- src/browse.c
+++ src/browse.c
@@ -77,11 +77,11 @@
77 int i, j;
78 char *zSep = "";
79
80 for(i=0; zPath[i]; i=j){
81 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
82 if( zPath[j] && g.perm.History ){
83 if( zCI ){
84 blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&amp;name=%#T\">%#h</a>",
85 zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]);
86 }else{
87 blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
@@ -118,11 +118,11 @@
118 Blob dirname;
119 Manifest *pM = 0;
120 const char *zSubdirLink;
121
122 login_check_credentials();
123 if( !g.perm.History ){ login_needed(); return; }
124 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
125 style_header("File List");
126 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
127 pathelementFunc, 0, 0);
128
129
+58 -49
--- src/checkin.c
+++ src/checkin.c
@@ -64,11 +64,11 @@
6464
}
6565
}
6666
blob_append(report, zPrefix, nPrefix);
6767
if( isDeleted ){
6868
blob_appendf(report, "DELETED %s\n", zDisplayName);
69
- }else if( !file_isfile_or_link(zFullName) ){
69
+ }else if( !file_wd_isfile_or_link(zFullName) ){
7070
if( file_access(zFullName, 0)==0 ){
7171
blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName);
7272
if( missingIsFatal ){
7373
fossil_warning("not a file: %s", zDisplayName);
7474
nErr++;
@@ -126,27 +126,25 @@
126126
}
127127
128128
/*
129129
** COMMAND: changes
130130
**
131
-** Usage: %fossil changes
131
+** Usage: %fossil changes ?OPTIONS?
132132
**
133133
** Report on the edit status of all files in the current checkout.
134
-** See also the "status" and "extra" commands.
135134
**
136135
** Pathnames are displayed according to the "relative-paths" setting,
137136
** unless overridden by the --abs-paths or --rel-paths options.
138137
**
139138
** Options:
140
-**
139
+** --abs-paths Display absolute pathnames.
140
+** --rel-paths Display pathnames relative to the current working
141
+** directory.
141142
** --sha1sum Verify file status using SHA1 hashing rather
142143
** than relying on file mtimes.
143
-**
144
-** --abs-paths Display absolute pathnames.
145
-**
146
-** --rel-paths Display pathnames relative to the current working
147
-** directory.
144
+**
145
+** See also: extra, ls, status
148146
*/
149147
void changes_cmd(void){
150148
Blob report;
151149
int vid;
152150
int useSha1sum = find_option("sha1sum", 0, 0)!=0;
@@ -161,26 +159,26 @@
161159
}
162160
163161
/*
164162
** COMMAND: status
165163
**
166
-** Usage: %fossil status
164
+** Usage: %fossil status ?OPTIONS?
167165
**
168166
** Report on the status of the current checkout.
169167
**
170168
** Pathnames are displayed according to the "relative-paths" setting,
171169
** unless overridden by the --abs-paths or --rel-paths options.
172170
**
173171
** Options:
174172
**
173
+** --abs-paths Display absolute pathnames.
174
+** --rel-paths Display pathnames relative to the current working
175
+** directory.
175176
** --sha1sum Verify file status using SHA1 hashing rather
176177
** than relying on file mtimes.
177178
**
178
-** --abs-paths Display absolute pathnames.
179
-**
180
-** --rel-paths Display pathnames relative to the current working
181
-** directory.
179
+** See also: changes, extra, ls
182180
*/
183181
void status_cmd(void){
184182
int vid;
185183
db_must_be_within_tree();
186184
/* 012345678901234 */
@@ -195,14 +193,19 @@
195193
}
196194
197195
/*
198196
** COMMAND: ls
199197
**
200
-** Usage: %fossil ls [-l]
198
+** Usage: %fossil ls ?OPTIONS?
201199
**
202200
** Show the names of all files in the current checkout. The -l provides
203201
** extra information about each file.
202
+**
203
+** Options:
204
+** -l Provide extra information about each file.
205
+**
206
+** See also: changes, extra, status
204207
*/
205208
void ls_cmd(void){
206209
int vid;
207210
Stmt q;
208211
int isBrief;
@@ -227,11 +230,11 @@
227230
fossil_print("%s\n", zPathname);
228231
}else if( isNew ){
229232
fossil_print("ADDED %s\n", zPathname);
230233
}else if( isDeleted ){
231234
fossil_print("DELETED %s\n", zPathname);
232
- }else if( !file_isfile_or_link(zFullName) ){
235
+ }else if( !file_wd_isfile_or_link(zFullName) ){
233236
if( file_access(zFullName, 0)==0 ){
234237
fossil_print("NOT_A_FILE %s\n", zPathname);
235238
}else{
236239
fossil_print("MISSING %s\n", zPathname);
237240
}
@@ -247,11 +250,11 @@
247250
db_finalize(&q);
248251
}
249252
250253
/*
251254
** COMMAND: extras
252
-** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
255
+** Usage: %fossil extras ?OPTIONS?
253256
**
254257
** Print a list of all files in the source tree that are not part of
255258
** the current checkout. See also the "clean" command.
256259
**
257260
** Files and subdirectories whose names begin with "." are normally
@@ -263,20 +266,17 @@
263266
**
264267
** Pathnames are displayed according to the "relative-paths" setting,
265268
** unless overridden by the --abs-paths or --rel-paths options.
266269
**
267270
** Options:
268
-**
269
-** --dotfiles Include files with names beginning with "."
270
-**
271
-** --ignore GLOBPATTERN
272
-** Override the "ignore-glob" setting.
273
-**
274
-** --abs-paths Display absolute pathnames.
275
-**
276
-** --rel-paths Display pathnames relative to the current working
277
-** directory.
271
+** --abs-paths Display absolute pathnames.
272
+** --dotfiles include files beginning with a dot (".")
273
+** --ignore <CSG> ignore files matching patterns from the
274
+** --rel-paths Display pathnames relative to the current working
275
+** directory.
276
+**
277
+** See also: changes, clean, status
278278
*/
279279
void extra_cmd(void){
280280
Blob path;
281281
Blob repo;
282282
Stmt q;
@@ -328,15 +328,15 @@
328328
db_finalize(&q);
329329
}
330330
331331
/*
332332
** COMMAND: clean
333
-** Usage: %fossil clean ?--force? ?--dotfiles? ?--ignore GLOBPATTERN?
333
+** Usage: %fossil clean ?OPTIONS?
334334
**
335335
** Delete all "extra" files in the source tree. "Extra" files are
336
-** files that are not officially part of the checkout. See also
337
-** the "extra" command. This operation cannot be undone.
336
+** files that are not officially part of the checkout. This operation
337
+** cannot be undone.
338338
**
339339
** You will be prompted before removing each file. If you are
340340
** sure you wish to remove all "extra" files you can specify the
341341
** optional --force flag and no prompts will be issued.
342342
**
@@ -345,10 +345,18 @@
345345
** is used.
346346
**
347347
** The GLOBPATTERN is a comma-separated list of GLOB expressions for
348348
** files that are ignored. The GLOBPATTERN specified by the "ignore-glob"
349349
** is used if the --ignore option is omitted.
350
+**
351
+** Options:
352
+** --dotfiles include files beginning with a dot (".")
353
+** --force Remove files without prompting
354
+** --ignore <CSG> ignore files matching patterns from the
355
+** comma separated list of glob patterns.
356
+**
357
+** See also: addremove, extra, status
350358
*/
351359
void clean_cmd(void){
352360
int allFlag;
353361
int dotfilesFlag;
354362
const char *zIgnoreFlag;
@@ -415,11 +423,12 @@
415423
*/
416424
static void prepare_commit_comment(
417425
Blob *pComment,
418426
char *zInit,
419427
const char *zBranch,
420
- int parent_rid
428
+ int parent_rid,
429
+ const char *zUserOvrd
421430
){
422431
const char *zEditor;
423432
char *zCmd;
424433
char *zFile;
425434
Blob text, line;
@@ -430,11 +439,11 @@
430439
"\n"
431440
"# Enter comments on this check-in. Lines beginning with # are ignored.\n"
432441
"# The check-in comment follows wiki formatting rules.\n"
433442
"#\n", -1
434443
);
435
- blob_appendf(&text, "# user: %s\n", g.zLogin);
444
+ blob_appendf(&text, "# user: %s\n", zUserOvrd ? zUserOvrd : g.zLogin);
436445
if( zBranch && zBranch[0] ){
437446
blob_appendf(&text, "# tags: %s\n#\n", zBranch);
438447
}else{
439448
char *zTags = info_tags_of_checkin(parent_rid, 1);
440449
if( zTags ) blob_appendf(&text, "# tags: %z\n#\n", zTags);
@@ -661,16 +670,16 @@
661670
** the filesystem. On windows, the "executable" bit is retained
662671
** unchanged from the original.
663672
*/
664673
blob_resize(&filename, nBasename);
665674
blob_append(&filename, zName, -1);
666
- isexe = file_isexe(blob_str(&filename));
675
+ isexe = file_wd_isexe(blob_str(&filename));
667676
668677
/* For unix, check if the file on the filesystem is symlink.
669678
** On windows, the bit is retained unchanged from original.
670679
*/
671
- isLink = file_islink(blob_str(&filename));
680
+ isLink = file_wd_islink(blob_str(&filename));
672681
#endif
673682
if( isexe ){
674683
zPerm = " x";
675684
}else if( isLink ){
676685
zPerm = " l"; /* note: symlinks don't have executable bit on unix */
@@ -839,30 +848,30 @@
839848
** to be placed in the named branch. The --bgcolor option can be followed
840849
** by a color name (ex: '#ffc0c0') to specify the background color of
841850
** entries in the new branch when shown in the web timeline interface.
842851
**
843852
** A check-in is not permitted to fork unless the --force or -f
844
-** option appears. A check-in is not allowed against a closed check-in.
853
+** option appears. A check-in is not allowed against a closed leaf.
845854
**
846855
** The --private option creates a private check-in that is never synced.
847856
** Children of private check-ins are automatically private.
848857
**
849858
** the --tag option applies the symbolic tag name to the check-in.
850859
**
851860
** Options:
852
-**
853
-** --comment|-m COMMENT-TEXT
854
-** --message-file|-M COMMENT-FILE
855
-** --branch NEW-BRANCH-NAME
856
-** --bgcolor COLOR
857
-** --nosign
858
-** --force|-f
859
-** --private
860
-** --baseline
861
-** --delta
862
-** --tag TAG-NAME
863
-**
861
+** --baseline use a baseline manifest in the commit process
862
+** --bgcolor COLOR apply given COLOR to the branch
863
+** --branch NEW-BRANCH-NAME check in to this new branch
864
+** --comment|-m COMMENT-TEXT use COMMENT-TEXT as commit comment
865
+** --delta use a delta manifest in the commit process
866
+** --force|-f allow forking with this commit
867
+** --message-file|-M FILE read the commit comment from given file
868
+** --nosign do not attempt to sign this commit with gpg
869
+** --private do not sync changes and their descendants
870
+** --tag TAG-NAME assign given tag TAG-NAME to the checkin
871
+**
872
+** See also: branch, changes, checkout, extra, sync
864873
*/
865874
void commit_cmd(void){
866875
int hasChanges; /* True if unsaved changes exist */
867876
int vid; /* blob-id of parent version */
868877
int nrid; /* blob-id of a modified file */
@@ -1034,11 +1043,11 @@
10341043
}else if( zComFile ){
10351044
blob_zero(&comment);
10361045
blob_read_from_file(&comment, zComFile);
10371046
}else{
10381047
char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
1039
- prepare_commit_comment(&comment, zInit, zBranch, vid);
1048
+ prepare_commit_comment(&comment, zInit, zBranch, vid, zUserOvrd);
10401049
free(zInit);
10411050
}
10421051
if( blob_size(&comment)==0 ){
10431052
Blob ans;
10441053
blob_zero(&ans);
@@ -1071,11 +1080,11 @@
10711080
zFullname = db_column_text(&q, 1);
10721081
rid = db_column_int(&q, 2);
10731082
crnlOk = db_column_int(&q, 3);
10741083
10751084
blob_zero(&content);
1076
- if( file_islink(zFullname) ){
1085
+ if( file_wd_islink(zFullname) ){
10771086
/* Instead of file content, put link destination path */
10781087
blob_read_link(&content, zFullname);
10791088
}else{
10801089
blob_read_from_file(&content, zFullname);
10811090
}
10821091
--- src/checkin.c
+++ src/checkin.c
@@ -64,11 +64,11 @@
64 }
65 }
66 blob_append(report, zPrefix, nPrefix);
67 if( isDeleted ){
68 blob_appendf(report, "DELETED %s\n", zDisplayName);
69 }else if( !file_isfile_or_link(zFullName) ){
70 if( file_access(zFullName, 0)==0 ){
71 blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName);
72 if( missingIsFatal ){
73 fossil_warning("not a file: %s", zDisplayName);
74 nErr++;
@@ -126,27 +126,25 @@
126 }
127
128 /*
129 ** COMMAND: changes
130 **
131 ** Usage: %fossil changes
132 **
133 ** Report on the edit status of all files in the current checkout.
134 ** See also the "status" and "extra" commands.
135 **
136 ** Pathnames are displayed according to the "relative-paths" setting,
137 ** unless overridden by the --abs-paths or --rel-paths options.
138 **
139 ** Options:
140 **
 
 
141 ** --sha1sum Verify file status using SHA1 hashing rather
142 ** than relying on file mtimes.
143 **
144 ** --abs-paths Display absolute pathnames.
145 **
146 ** --rel-paths Display pathnames relative to the current working
147 ** directory.
148 */
149 void changes_cmd(void){
150 Blob report;
151 int vid;
152 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
@@ -161,26 +159,26 @@
161 }
162
163 /*
164 ** COMMAND: status
165 **
166 ** Usage: %fossil status
167 **
168 ** Report on the status of the current checkout.
169 **
170 ** Pathnames are displayed according to the "relative-paths" setting,
171 ** unless overridden by the --abs-paths or --rel-paths options.
172 **
173 ** Options:
174 **
 
 
 
175 ** --sha1sum Verify file status using SHA1 hashing rather
176 ** than relying on file mtimes.
177 **
178 ** --abs-paths Display absolute pathnames.
179 **
180 ** --rel-paths Display pathnames relative to the current working
181 ** directory.
182 */
183 void status_cmd(void){
184 int vid;
185 db_must_be_within_tree();
186 /* 012345678901234 */
@@ -195,14 +193,19 @@
195 }
196
197 /*
198 ** COMMAND: ls
199 **
200 ** Usage: %fossil ls [-l]
201 **
202 ** Show the names of all files in the current checkout. The -l provides
203 ** extra information about each file.
 
 
 
 
 
204 */
205 void ls_cmd(void){
206 int vid;
207 Stmt q;
208 int isBrief;
@@ -227,11 +230,11 @@
227 fossil_print("%s\n", zPathname);
228 }else if( isNew ){
229 fossil_print("ADDED %s\n", zPathname);
230 }else if( isDeleted ){
231 fossil_print("DELETED %s\n", zPathname);
232 }else if( !file_isfile_or_link(zFullName) ){
233 if( file_access(zFullName, 0)==0 ){
234 fossil_print("NOT_A_FILE %s\n", zPathname);
235 }else{
236 fossil_print("MISSING %s\n", zPathname);
237 }
@@ -247,11 +250,11 @@
247 db_finalize(&q);
248 }
249
250 /*
251 ** COMMAND: extras
252 ** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
253 **
254 ** Print a list of all files in the source tree that are not part of
255 ** the current checkout. See also the "clean" command.
256 **
257 ** Files and subdirectories whose names begin with "." are normally
@@ -263,20 +266,17 @@
263 **
264 ** Pathnames are displayed according to the "relative-paths" setting,
265 ** unless overridden by the --abs-paths or --rel-paths options.
266 **
267 ** Options:
268 **
269 ** --dotfiles Include files with names beginning with "."
270 **
271 ** --ignore GLOBPATTERN
272 ** Override the "ignore-glob" setting.
273 **
274 ** --abs-paths Display absolute pathnames.
275 **
276 ** --rel-paths Display pathnames relative to the current working
277 ** directory.
278 */
279 void extra_cmd(void){
280 Blob path;
281 Blob repo;
282 Stmt q;
@@ -328,15 +328,15 @@
328 db_finalize(&q);
329 }
330
331 /*
332 ** COMMAND: clean
333 ** Usage: %fossil clean ?--force? ?--dotfiles? ?--ignore GLOBPATTERN?
334 **
335 ** Delete all "extra" files in the source tree. "Extra" files are
336 ** files that are not officially part of the checkout. See also
337 ** the "extra" command. This operation cannot be undone.
338 **
339 ** You will be prompted before removing each file. If you are
340 ** sure you wish to remove all "extra" files you can specify the
341 ** optional --force flag and no prompts will be issued.
342 **
@@ -345,10 +345,18 @@
345 ** is used.
346 **
347 ** The GLOBPATTERN is a comma-separated list of GLOB expressions for
348 ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob"
349 ** is used if the --ignore option is omitted.
 
 
 
 
 
 
 
 
350 */
351 void clean_cmd(void){
352 int allFlag;
353 int dotfilesFlag;
354 const char *zIgnoreFlag;
@@ -415,11 +423,12 @@
415 */
416 static void prepare_commit_comment(
417 Blob *pComment,
418 char *zInit,
419 const char *zBranch,
420 int parent_rid
 
421 ){
422 const char *zEditor;
423 char *zCmd;
424 char *zFile;
425 Blob text, line;
@@ -430,11 +439,11 @@
430 "\n"
431 "# Enter comments on this check-in. Lines beginning with # are ignored.\n"
432 "# The check-in comment follows wiki formatting rules.\n"
433 "#\n", -1
434 );
435 blob_appendf(&text, "# user: %s\n", g.zLogin);
436 if( zBranch && zBranch[0] ){
437 blob_appendf(&text, "# tags: %s\n#\n", zBranch);
438 }else{
439 char *zTags = info_tags_of_checkin(parent_rid, 1);
440 if( zTags ) blob_appendf(&text, "# tags: %z\n#\n", zTags);
@@ -661,16 +670,16 @@
661 ** the filesystem. On windows, the "executable" bit is retained
662 ** unchanged from the original.
663 */
664 blob_resize(&filename, nBasename);
665 blob_append(&filename, zName, -1);
666 isexe = file_isexe(blob_str(&filename));
667
668 /* For unix, check if the file on the filesystem is symlink.
669 ** On windows, the bit is retained unchanged from original.
670 */
671 isLink = file_islink(blob_str(&filename));
672 #endif
673 if( isexe ){
674 zPerm = " x";
675 }else if( isLink ){
676 zPerm = " l"; /* note: symlinks don't have executable bit on unix */
@@ -839,30 +848,30 @@
839 ** to be placed in the named branch. The --bgcolor option can be followed
840 ** by a color name (ex: '#ffc0c0') to specify the background color of
841 ** entries in the new branch when shown in the web timeline interface.
842 **
843 ** A check-in is not permitted to fork unless the --force or -f
844 ** option appears. A check-in is not allowed against a closed check-in.
845 **
846 ** The --private option creates a private check-in that is never synced.
847 ** Children of private check-ins are automatically private.
848 **
849 ** the --tag option applies the symbolic tag name to the check-in.
850 **
851 ** Options:
852 **
853 ** --comment|-m COMMENT-TEXT
854 ** --message-file|-M COMMENT-FILE
855 ** --branch NEW-BRANCH-NAME
856 ** --bgcolor COLOR
857 ** --nosign
858 ** --force|-f
859 ** --private
860 ** --baseline
861 ** --delta
862 ** --tag TAG-NAME
863 **
864 */
865 void commit_cmd(void){
866 int hasChanges; /* True if unsaved changes exist */
867 int vid; /* blob-id of parent version */
868 int nrid; /* blob-id of a modified file */
@@ -1034,11 +1043,11 @@
1034 }else if( zComFile ){
1035 blob_zero(&comment);
1036 blob_read_from_file(&comment, zComFile);
1037 }else{
1038 char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
1039 prepare_commit_comment(&comment, zInit, zBranch, vid);
1040 free(zInit);
1041 }
1042 if( blob_size(&comment)==0 ){
1043 Blob ans;
1044 blob_zero(&ans);
@@ -1071,11 +1080,11 @@
1071 zFullname = db_column_text(&q, 1);
1072 rid = db_column_int(&q, 2);
1073 crnlOk = db_column_int(&q, 3);
1074
1075 blob_zero(&content);
1076 if( file_islink(zFullname) ){
1077 /* Instead of file content, put link destination path */
1078 blob_read_link(&content, zFullname);
1079 }else{
1080 blob_read_from_file(&content, zFullname);
1081 }
1082
--- src/checkin.c
+++ src/checkin.c
@@ -64,11 +64,11 @@
64 }
65 }
66 blob_append(report, zPrefix, nPrefix);
67 if( isDeleted ){
68 blob_appendf(report, "DELETED %s\n", zDisplayName);
69 }else if( !file_wd_isfile_or_link(zFullName) ){
70 if( file_access(zFullName, 0)==0 ){
71 blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName);
72 if( missingIsFatal ){
73 fossil_warning("not a file: %s", zDisplayName);
74 nErr++;
@@ -126,27 +126,25 @@
126 }
127
128 /*
129 ** COMMAND: changes
130 **
131 ** Usage: %fossil changes ?OPTIONS?
132 **
133 ** Report on the edit status of all files in the current checkout.
 
134 **
135 ** Pathnames are displayed according to the "relative-paths" setting,
136 ** unless overridden by the --abs-paths or --rel-paths options.
137 **
138 ** Options:
139 ** --abs-paths Display absolute pathnames.
140 ** --rel-paths Display pathnames relative to the current working
141 ** directory.
142 ** --sha1sum Verify file status using SHA1 hashing rather
143 ** than relying on file mtimes.
144 **
145 ** See also: extra, ls, status
 
 
 
146 */
147 void changes_cmd(void){
148 Blob report;
149 int vid;
150 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
@@ -161,26 +159,26 @@
159 }
160
161 /*
162 ** COMMAND: status
163 **
164 ** Usage: %fossil status ?OPTIONS?
165 **
166 ** Report on the status of the current checkout.
167 **
168 ** Pathnames are displayed according to the "relative-paths" setting,
169 ** unless overridden by the --abs-paths or --rel-paths options.
170 **
171 ** Options:
172 **
173 ** --abs-paths Display absolute pathnames.
174 ** --rel-paths Display pathnames relative to the current working
175 ** directory.
176 ** --sha1sum Verify file status using SHA1 hashing rather
177 ** than relying on file mtimes.
178 **
179 ** See also: changes, extra, ls
 
 
 
180 */
181 void status_cmd(void){
182 int vid;
183 db_must_be_within_tree();
184 /* 012345678901234 */
@@ -195,14 +193,19 @@
193 }
194
195 /*
196 ** COMMAND: ls
197 **
198 ** Usage: %fossil ls ?OPTIONS?
199 **
200 ** Show the names of all files in the current checkout. The -l provides
201 ** extra information about each file.
202 **
203 ** Options:
204 ** -l Provide extra information about each file.
205 **
206 ** See also: changes, extra, status
207 */
208 void ls_cmd(void){
209 int vid;
210 Stmt q;
211 int isBrief;
@@ -227,11 +230,11 @@
230 fossil_print("%s\n", zPathname);
231 }else if( isNew ){
232 fossil_print("ADDED %s\n", zPathname);
233 }else if( isDeleted ){
234 fossil_print("DELETED %s\n", zPathname);
235 }else if( !file_wd_isfile_or_link(zFullName) ){
236 if( file_access(zFullName, 0)==0 ){
237 fossil_print("NOT_A_FILE %s\n", zPathname);
238 }else{
239 fossil_print("MISSING %s\n", zPathname);
240 }
@@ -247,11 +250,11 @@
250 db_finalize(&q);
251 }
252
253 /*
254 ** COMMAND: extras
255 ** Usage: %fossil extras ?OPTIONS?
256 **
257 ** Print a list of all files in the source tree that are not part of
258 ** the current checkout. See also the "clean" command.
259 **
260 ** Files and subdirectories whose names begin with "." are normally
@@ -263,20 +266,17 @@
266 **
267 ** Pathnames are displayed according to the "relative-paths" setting,
268 ** unless overridden by the --abs-paths or --rel-paths options.
269 **
270 ** Options:
271 ** --abs-paths Display absolute pathnames.
272 ** --dotfiles include files beginning with a dot (".")
273 ** --ignore <CSG> ignore files matching patterns from the
274 ** --rel-paths Display pathnames relative to the current working
275 ** directory.
276 **
277 ** See also: changes, clean, status
 
 
 
278 */
279 void extra_cmd(void){
280 Blob path;
281 Blob repo;
282 Stmt q;
@@ -328,15 +328,15 @@
328 db_finalize(&q);
329 }
330
331 /*
332 ** COMMAND: clean
333 ** Usage: %fossil clean ?OPTIONS?
334 **
335 ** Delete all "extra" files in the source tree. "Extra" files are
336 ** files that are not officially part of the checkout. This operation
337 ** cannot be undone.
338 **
339 ** You will be prompted before removing each file. If you are
340 ** sure you wish to remove all "extra" files you can specify the
341 ** optional --force flag and no prompts will be issued.
342 **
@@ -345,10 +345,18 @@
345 ** is used.
346 **
347 ** The GLOBPATTERN is a comma-separated list of GLOB expressions for
348 ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob"
349 ** is used if the --ignore option is omitted.
350 **
351 ** Options:
352 ** --dotfiles include files beginning with a dot (".")
353 ** --force Remove files without prompting
354 ** --ignore <CSG> ignore files matching patterns from the
355 ** comma separated list of glob patterns.
356 **
357 ** See also: addremove, extra, status
358 */
359 void clean_cmd(void){
360 int allFlag;
361 int dotfilesFlag;
362 const char *zIgnoreFlag;
@@ -415,11 +423,12 @@
423 */
424 static void prepare_commit_comment(
425 Blob *pComment,
426 char *zInit,
427 const char *zBranch,
428 int parent_rid,
429 const char *zUserOvrd
430 ){
431 const char *zEditor;
432 char *zCmd;
433 char *zFile;
434 Blob text, line;
@@ -430,11 +439,11 @@
439 "\n"
440 "# Enter comments on this check-in. Lines beginning with # are ignored.\n"
441 "# The check-in comment follows wiki formatting rules.\n"
442 "#\n", -1
443 );
444 blob_appendf(&text, "# user: %s\n", zUserOvrd ? zUserOvrd : g.zLogin);
445 if( zBranch && zBranch[0] ){
446 blob_appendf(&text, "# tags: %s\n#\n", zBranch);
447 }else{
448 char *zTags = info_tags_of_checkin(parent_rid, 1);
449 if( zTags ) blob_appendf(&text, "# tags: %z\n#\n", zTags);
@@ -661,16 +670,16 @@
670 ** the filesystem. On windows, the "executable" bit is retained
671 ** unchanged from the original.
672 */
673 blob_resize(&filename, nBasename);
674 blob_append(&filename, zName, -1);
675 isexe = file_wd_isexe(blob_str(&filename));
676
677 /* For unix, check if the file on the filesystem is symlink.
678 ** On windows, the bit is retained unchanged from original.
679 */
680 isLink = file_wd_islink(blob_str(&filename));
681 #endif
682 if( isexe ){
683 zPerm = " x";
684 }else if( isLink ){
685 zPerm = " l"; /* note: symlinks don't have executable bit on unix */
@@ -839,30 +848,30 @@
848 ** to be placed in the named branch. The --bgcolor option can be followed
849 ** by a color name (ex: '#ffc0c0') to specify the background color of
850 ** entries in the new branch when shown in the web timeline interface.
851 **
852 ** A check-in is not permitted to fork unless the --force or -f
853 ** option appears. A check-in is not allowed against a closed leaf.
854 **
855 ** The --private option creates a private check-in that is never synced.
856 ** Children of private check-ins are automatically private.
857 **
858 ** the --tag option applies the symbolic tag name to the check-in.
859 **
860 ** Options:
861 ** --baseline use a baseline manifest in the commit process
862 ** --bgcolor COLOR apply given COLOR to the branch
863 ** --branch NEW-BRANCH-NAME check in to this new branch
864 ** --comment|-m COMMENT-TEXT use COMMENT-TEXT as commit comment
865 ** --delta use a delta manifest in the commit process
866 ** --force|-f allow forking with this commit
867 ** --message-file|-M FILE read the commit comment from given file
868 ** --nosign do not attempt to sign this commit with gpg
869 ** --private do not sync changes and their descendants
870 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
871 **
872 ** See also: branch, changes, checkout, extra, sync
873 */
874 void commit_cmd(void){
875 int hasChanges; /* True if unsaved changes exist */
876 int vid; /* blob-id of parent version */
877 int nrid; /* blob-id of a modified file */
@@ -1034,11 +1043,11 @@
1043 }else if( zComFile ){
1044 blob_zero(&comment);
1045 blob_read_from_file(&comment, zComFile);
1046 }else{
1047 char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
1048 prepare_commit_comment(&comment, zInit, zBranch, vid, zUserOvrd);
1049 free(zInit);
1050 }
1051 if( blob_size(&comment)==0 ){
1052 Blob ans;
1053 blob_zero(&ans);
@@ -1071,11 +1080,11 @@
1080 zFullname = db_column_text(&q, 1);
1081 rid = db_column_int(&q, 2);
1082 crnlOk = db_column_int(&q, 3);
1083
1084 blob_zero(&content);
1085 if( file_wd_islink(zFullname) ){
1086 /* Instead of file content, put link destination path */
1087 blob_read_link(&content, zFullname);
1088 }else{
1089 blob_read_from_file(&content, zFullname);
1090 }
1091
+14 -4
--- src/checkout.c
+++ src/checkout.c
@@ -113,11 +113,11 @@
113113
manifest_file_rewind(pManifest);
114114
while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
115115
int isExe;
116116
blob_append(&filename, pFile->zName, -1);
117117
isExe = pFile->zPerm && strstr(pFile->zPerm, "x");
118
- file_setexe(blob_str(&filename), isExe);
118
+ file_wd_setexe(blob_str(&filename), isExe);
119119
set_or_clear_isexe(pFile->zName, vid, isExe);
120120
blob_resize(&filename, baseLen);
121121
}
122122
blob_reset(&filename);
123123
manifest_destroy(pManifest);
@@ -164,22 +164,27 @@
164164
165165
/*
166166
** COMMAND: checkout
167167
** COMMAND: co
168168
**
169
-** Usage: %fossil checkout VERSION ?-f|--force? ?--keep?
169
+** Usage: %fossil checkout ?VERSION | --latest? ?OPTIONS?
170
+** or: %fossil co ?VERSION | --latest? ?OPTIONS?
170171
**
171172
** Check out a version specified on the command-line. This command
172173
** will abort if there are edited files in the current checkout unless
173174
** the --force option appears on the command-line. The --keep option
174175
** leaves files on disk unchanged, except the manifest and manifest.uuid
175176
** files.
176177
**
177178
** The --latest flag can be used in place of VERSION to checkout the
178179
** latest version in the repository.
180
+**
181
+** Options:
182
+** --force Ignore edited files in the current checkout
183
+** --keep Only update the manifest and manifest.uuid files
179184
**
180
-** See also the "update" command.
185
+** See also: update
181186
*/
182187
void checkout_cmd(void){
183188
int forceFlag; /* Force checkout even if edits exist */
184189
int keepFlag; /* Do not change any files on disk */
185190
int latestFlag; /* Checkout the latest version */
@@ -269,15 +274,20 @@
269274
}
270275
271276
/*
272277
** COMMAND: close
273278
**
274
-** Usage: %fossil close ?-f|--force?
279
+** Usage: %fossil close ?OPTIONS?
275280
**
276281
** The opposite of "open". Close the current database connection.
277282
** Require a -f or --force flag if there are unsaved changed in the
278283
** current check-out.
284
+**
285
+** Options:
286
+** --force|-f necessary to close a check out with uncommitted changes
287
+**
288
+** See also: open
279289
*/
280290
void close_cmd(void){
281291
int forceFlag = find_option("force","f",0)!=0;
282292
db_must_be_within_tree();
283293
if( !forceFlag && unsaved_changes()==1 ){
284294
--- src/checkout.c
+++ src/checkout.c
@@ -113,11 +113,11 @@
113 manifest_file_rewind(pManifest);
114 while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
115 int isExe;
116 blob_append(&filename, pFile->zName, -1);
117 isExe = pFile->zPerm && strstr(pFile->zPerm, "x");
118 file_setexe(blob_str(&filename), isExe);
119 set_or_clear_isexe(pFile->zName, vid, isExe);
120 blob_resize(&filename, baseLen);
121 }
122 blob_reset(&filename);
123 manifest_destroy(pManifest);
@@ -164,22 +164,27 @@
164
165 /*
166 ** COMMAND: checkout
167 ** COMMAND: co
168 **
169 ** Usage: %fossil checkout VERSION ?-f|--force? ?--keep?
 
170 **
171 ** Check out a version specified on the command-line. This command
172 ** will abort if there are edited files in the current checkout unless
173 ** the --force option appears on the command-line. The --keep option
174 ** leaves files on disk unchanged, except the manifest and manifest.uuid
175 ** files.
176 **
177 ** The --latest flag can be used in place of VERSION to checkout the
178 ** latest version in the repository.
 
 
 
 
179 **
180 ** See also the "update" command.
181 */
182 void checkout_cmd(void){
183 int forceFlag; /* Force checkout even if edits exist */
184 int keepFlag; /* Do not change any files on disk */
185 int latestFlag; /* Checkout the latest version */
@@ -269,15 +274,20 @@
269 }
270
271 /*
272 ** COMMAND: close
273 **
274 ** Usage: %fossil close ?-f|--force?
275 **
276 ** The opposite of "open". Close the current database connection.
277 ** Require a -f or --force flag if there are unsaved changed in the
278 ** current check-out.
 
 
 
 
 
279 */
280 void close_cmd(void){
281 int forceFlag = find_option("force","f",0)!=0;
282 db_must_be_within_tree();
283 if( !forceFlag && unsaved_changes()==1 ){
284
--- src/checkout.c
+++ src/checkout.c
@@ -113,11 +113,11 @@
113 manifest_file_rewind(pManifest);
114 while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
115 int isExe;
116 blob_append(&filename, pFile->zName, -1);
117 isExe = pFile->zPerm && strstr(pFile->zPerm, "x");
118 file_wd_setexe(blob_str(&filename), isExe);
119 set_or_clear_isexe(pFile->zName, vid, isExe);
120 blob_resize(&filename, baseLen);
121 }
122 blob_reset(&filename);
123 manifest_destroy(pManifest);
@@ -164,22 +164,27 @@
164
165 /*
166 ** COMMAND: checkout
167 ** COMMAND: co
168 **
169 ** Usage: %fossil checkout ?VERSION | --latest? ?OPTIONS?
170 ** or: %fossil co ?VERSION | --latest? ?OPTIONS?
171 **
172 ** Check out a version specified on the command-line. This command
173 ** will abort if there are edited files in the current checkout unless
174 ** the --force option appears on the command-line. The --keep option
175 ** leaves files on disk unchanged, except the manifest and manifest.uuid
176 ** files.
177 **
178 ** The --latest flag can be used in place of VERSION to checkout the
179 ** latest version in the repository.
180 **
181 ** Options:
182 ** --force Ignore edited files in the current checkout
183 ** --keep Only update the manifest and manifest.uuid files
184 **
185 ** See also: update
186 */
187 void checkout_cmd(void){
188 int forceFlag; /* Force checkout even if edits exist */
189 int keepFlag; /* Do not change any files on disk */
190 int latestFlag; /* Checkout the latest version */
@@ -269,15 +274,20 @@
274 }
275
276 /*
277 ** COMMAND: close
278 **
279 ** Usage: %fossil close ?OPTIONS?
280 **
281 ** The opposite of "open". Close the current database connection.
282 ** Require a -f or --force flag if there are unsaved changed in the
283 ** current check-out.
284 **
285 ** Options:
286 ** --force|-f necessary to close a check out with uncommitted changes
287 **
288 ** See also: open
289 */
290 void close_cmd(void){
291 int forceFlag = find_option("force","f",0)!=0;
292 db_must_be_within_tree();
293 if( !forceFlag && unsaved_changes()==1 ){
294
+4 -4
--- src/clone.c
+++ src/clone.c
@@ -34,15 +34,15 @@
3434
** By default, your current login name is used to create the default
3535
** admin user. This can be overridden using the -A|--admin-user
3636
** parameter.
3737
**
3838
** Options:
39
-**
40
-** --admin-user|-A USERNAME Make USERNAME the administrator
41
-** --private Also clone private branches
42
-** --ssl-identity=filename Use the SSL identity if requested by the server
39
+** --admin-user|-A USERNAME Make USERNAME the administrator
40
+** --private Also clone private branches
41
+** --ssl-identity=filename Use the SSL identity if requested by the server
4342
**
43
+** See also: init
4444
*/
4545
void clone_cmd(void){
4646
char *zPassword;
4747
const char *zDefaultUser; /* Optional name of the default user */
4848
const char *zPw; /* The user clone password */
4949
--- src/clone.c
+++ src/clone.c
@@ -34,15 +34,15 @@
34 ** By default, your current login name is used to create the default
35 ** admin user. This can be overridden using the -A|--admin-user
36 ** parameter.
37 **
38 ** Options:
39 **
40 ** --admin-user|-A USERNAME Make USERNAME the administrator
41 ** --private Also clone private branches
42 ** --ssl-identity=filename Use the SSL identity if requested by the server
43 **
 
44 */
45 void clone_cmd(void){
46 char *zPassword;
47 const char *zDefaultUser; /* Optional name of the default user */
48 const char *zPw; /* The user clone password */
49
--- src/clone.c
+++ src/clone.c
@@ -34,15 +34,15 @@
34 ** By default, your current login name is used to create the default
35 ** admin user. This can be overridden using the -A|--admin-user
36 ** parameter.
37 **
38 ** Options:
39 ** --admin-user|-A USERNAME Make USERNAME the administrator
40 ** --private Also clone private branches
41 ** --ssl-identity=filename Use the SSL identity if requested by the server
 
42 **
43 ** See also: init
44 */
45 void clone_cmd(void){
46 char *zPassword;
47 const char *zDefaultUser; /* Optional name of the default user */
48 const char *zPw; /* The user clone password */
49
+9 -4
--- src/configure.c
+++ src/configure.c
@@ -153,14 +153,14 @@
153153
n -= 2;
154154
}
155155
for(i=0; i<count(aConfig); i++){
156156
if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
157157
int m = aConfig[i].groupMask;
158
- if( !g.okAdmin ){
158
+ if( !g.perm.Admin ){
159159
m &= ~CONFIGSET_USER;
160160
}
161
- if( !g.okRdAddr ){
161
+ if( !g.perm.RdAddr ){
162162
m &= ~CONFIGSET_ADDR;
163163
}
164164
return m;
165165
}
166166
}
@@ -553,11 +553,11 @@
553553
){
554554
const char *zName = blob_str(&aToken[1]);
555555
Blob content;
556556
blob_zero(&content);
557557
blob_extract(pIn, size, &content);
558
- g.okAdmin = g.okRdAddr = 1;
558
+ g.perm.Admin = g.perm.RdAddr = 1;
559559
configure_receive(zName, &content, groupMask);
560560
blob_reset(&content);
561561
blob_seek(pIn, 1, BLOB_SEEK_CUR);
562562
}
563563
}
@@ -726,11 +726,11 @@
726726
727727
728728
/*
729729
** COMMAND: configuration
730730
**
731
-** Usage: %fossil configuration METHOD ... ?-R|--repository REPOSITORY?
731
+** Usage: %fossil configuration METHOD ... ?OPTIONS?
732732
**
733733
** Where METHOD is one of: export import merge pull push reset. All methods
734734
** accept the -R or --repository option to specific a repository.
735735
**
736736
** %fossil configuration export AREA FILENAME
@@ -772,10 +772,15 @@
772772
**
773773
** %fossil configuration sync AREA ?URL?
774774
**
775775
** Synchronize configuration changes in the local repository with
776776
** the remote repository at URL.
777
+**
778
+** Options:
779
+** -R|--repository FILE Extract info from repository FILE
780
+**
781
+** See also: set
777782
*/
778783
void configuration_cmd(void){
779784
int n;
780785
const char *zMethod;
781786
if( g.argc<3 ){
782787
--- src/configure.c
+++ src/configure.c
@@ -153,14 +153,14 @@
153 n -= 2;
154 }
155 for(i=0; i<count(aConfig); i++){
156 if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
157 int m = aConfig[i].groupMask;
158 if( !g.okAdmin ){
159 m &= ~CONFIGSET_USER;
160 }
161 if( !g.okRdAddr ){
162 m &= ~CONFIGSET_ADDR;
163 }
164 return m;
165 }
166 }
@@ -553,11 +553,11 @@
553 ){
554 const char *zName = blob_str(&aToken[1]);
555 Blob content;
556 blob_zero(&content);
557 blob_extract(pIn, size, &content);
558 g.okAdmin = g.okRdAddr = 1;
559 configure_receive(zName, &content, groupMask);
560 blob_reset(&content);
561 blob_seek(pIn, 1, BLOB_SEEK_CUR);
562 }
563 }
@@ -726,11 +726,11 @@
726
727
728 /*
729 ** COMMAND: configuration
730 **
731 ** Usage: %fossil configuration METHOD ... ?-R|--repository REPOSITORY?
732 **
733 ** Where METHOD is one of: export import merge pull push reset. All methods
734 ** accept the -R or --repository option to specific a repository.
735 **
736 ** %fossil configuration export AREA FILENAME
@@ -772,10 +772,15 @@
772 **
773 ** %fossil configuration sync AREA ?URL?
774 **
775 ** Synchronize configuration changes in the local repository with
776 ** the remote repository at URL.
 
 
 
 
 
777 */
778 void configuration_cmd(void){
779 int n;
780 const char *zMethod;
781 if( g.argc<3 ){
782
--- src/configure.c
+++ src/configure.c
@@ -153,14 +153,14 @@
153 n -= 2;
154 }
155 for(i=0; i<count(aConfig); i++){
156 if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
157 int m = aConfig[i].groupMask;
158 if( !g.perm.Admin ){
159 m &= ~CONFIGSET_USER;
160 }
161 if( !g.perm.RdAddr ){
162 m &= ~CONFIGSET_ADDR;
163 }
164 return m;
165 }
166 }
@@ -553,11 +553,11 @@
553 ){
554 const char *zName = blob_str(&aToken[1]);
555 Blob content;
556 blob_zero(&content);
557 blob_extract(pIn, size, &content);
558 g.perm.Admin = g.perm.RdAddr = 1;
559 configure_receive(zName, &content, groupMask);
560 blob_reset(&content);
561 blob_seek(pIn, 1, BLOB_SEEK_CUR);
562 }
563 }
@@ -726,11 +726,11 @@
726
727
728 /*
729 ** COMMAND: configuration
730 **
731 ** Usage: %fossil configuration METHOD ... ?OPTIONS?
732 **
733 ** Where METHOD is one of: export import merge pull push reset. All methods
734 ** accept the -R or --repository option to specific a repository.
735 **
736 ** %fossil configuration export AREA FILENAME
@@ -772,10 +772,15 @@
772 **
773 ** %fossil configuration sync AREA ?URL?
774 **
775 ** Synchronize configuration changes in the local repository with
776 ** the remote repository at URL.
777 **
778 ** Options:
779 ** -R|--repository FILE Extract info from repository FILE
780 **
781 ** See also: set
782 */
783 void configuration_cmd(void){
784 int n;
785 const char *zMethod;
786 if( g.argc<3 ){
787
--- src/content.c
+++ src/content.c
@@ -312,11 +312,10 @@
312312
** Extract an artifact by its SHA1 hash and write the results on
313313
** standard output, or if the optional 4th argument is given, in
314314
** the named output file.
315315
**
316316
** Options:
317
-**
318317
** -R|--repository FILE Extract artifacts from repository FILE
319318
*/
320319
void artifact_cmd(void){
321320
int rid;
322321
Blob content;
323322
--- src/content.c
+++ src/content.c
@@ -312,11 +312,10 @@
312 ** Extract an artifact by its SHA1 hash and write the results on
313 ** standard output, or if the optional 4th argument is given, in
314 ** the named output file.
315 **
316 ** Options:
317 **
318 ** -R|--repository FILE Extract artifacts from repository FILE
319 */
320 void artifact_cmd(void){
321 int rid;
322 Blob content;
323
--- src/content.c
+++ src/content.c
@@ -312,11 +312,10 @@
312 ** Extract an artifact by its SHA1 hash and write the results on
313 ** standard output, or if the optional 4th argument is given, in
314 ** the named output file.
315 **
316 ** Options:
 
317 ** -R|--repository FILE Extract artifacts from repository FILE
318 */
319 void artifact_cmd(void){
320 int rid;
321 Blob content;
322
+10 -6
--- src/db.c
+++ src/db.c
@@ -1179,14 +1179,14 @@
11791179
** By default, your current login name is used to create the default
11801180
** admin user. This can be overridden using the -A|--admin-user
11811181
** parameter.
11821182
**
11831183
** Options:
1184
-**
1185
-** --admin-user|-A USERNAME
1186
-** --date-override DATETIME
1184
+** --admin-user|-A USERNAME select given USERNAME as admin user
1185
+** --date-override DATETIME use DATETIME as time of the initial checkin
11871186
**
1187
+** See also: clone
11881188
*/
11891189
void create_repository_cmd(void){
11901190
char *zPassword;
11911191
const char *zDate; /* Date of the initial check-in */
11921192
const char *zDefaultUser; /* Optional name of the default user */
@@ -1344,11 +1344,11 @@
13441344
** In either case, the string returned is stored in space obtained
13451345
** from malloc and should be freed by the calling function.
13461346
*/
13471347
char *db_reveal(const char *zKey){
13481348
char *zOut;
1349
- if( g.okRdAddr ){
1349
+ if( g.perm.RdAddr ){
13501350
zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
13511351
}else{
13521352
zOut = 0;
13531353
}
13541354
if( zOut==0 ){
@@ -1642,19 +1642,23 @@
16421642
}
16431643
16441644
/*
16451645
** COMMAND: open
16461646
**
1647
-** Usage: %fossil open FILENAME ?VERSION? ?--keep? ?--nested?
1647
+** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
16481648
**
16491649
** Open a connection to the local repository in FILENAME. A checkout
16501650
** for the repository is created with its root at the working directory.
16511651
** If VERSION is specified then that version is checked out. Otherwise
16521652
** the latest version is checked out. No files other than "manifest"
16531653
** and "manifest.uuid" are modified if the --keep option is present.
16541654
**
1655
-** See also the "close" command.
1655
+** Options:
1656
+** --keep Only modify the manifest and manifest.uuid files
1657
+** --nested Allow opening a repository inside an opened checkout
1658
+**
1659
+** See also: close
16561660
*/
16571661
void cmd_open(void){
16581662
Blob path;
16591663
int vid;
16601664
int keepFlag;
16611665
--- src/db.c
+++ src/db.c
@@ -1179,14 +1179,14 @@
1179 ** By default, your current login name is used to create the default
1180 ** admin user. This can be overridden using the -A|--admin-user
1181 ** parameter.
1182 **
1183 ** Options:
1184 **
1185 ** --admin-user|-A USERNAME
1186 ** --date-override DATETIME
1187 **
 
1188 */
1189 void create_repository_cmd(void){
1190 char *zPassword;
1191 const char *zDate; /* Date of the initial check-in */
1192 const char *zDefaultUser; /* Optional name of the default user */
@@ -1344,11 +1344,11 @@
1344 ** In either case, the string returned is stored in space obtained
1345 ** from malloc and should be freed by the calling function.
1346 */
1347 char *db_reveal(const char *zKey){
1348 char *zOut;
1349 if( g.okRdAddr ){
1350 zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
1351 }else{
1352 zOut = 0;
1353 }
1354 if( zOut==0 ){
@@ -1642,19 +1642,23 @@
1642 }
1643
1644 /*
1645 ** COMMAND: open
1646 **
1647 ** Usage: %fossil open FILENAME ?VERSION? ?--keep? ?--nested?
1648 **
1649 ** Open a connection to the local repository in FILENAME. A checkout
1650 ** for the repository is created with its root at the working directory.
1651 ** If VERSION is specified then that version is checked out. Otherwise
1652 ** the latest version is checked out. No files other than "manifest"
1653 ** and "manifest.uuid" are modified if the --keep option is present.
1654 **
1655 ** See also the "close" command.
 
 
 
 
1656 */
1657 void cmd_open(void){
1658 Blob path;
1659 int vid;
1660 int keepFlag;
1661
--- src/db.c
+++ src/db.c
@@ -1179,14 +1179,14 @@
1179 ** By default, your current login name is used to create the default
1180 ** admin user. This can be overridden using the -A|--admin-user
1181 ** parameter.
1182 **
1183 ** Options:
1184 ** --admin-user|-A USERNAME select given USERNAME as admin user
1185 ** --date-override DATETIME use DATETIME as time of the initial checkin
 
1186 **
1187 ** See also: clone
1188 */
1189 void create_repository_cmd(void){
1190 char *zPassword;
1191 const char *zDate; /* Date of the initial check-in */
1192 const char *zDefaultUser; /* Optional name of the default user */
@@ -1344,11 +1344,11 @@
1344 ** In either case, the string returned is stored in space obtained
1345 ** from malloc and should be freed by the calling function.
1346 */
1347 char *db_reveal(const char *zKey){
1348 char *zOut;
1349 if( g.perm.RdAddr ){
1350 zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
1351 }else{
1352 zOut = 0;
1353 }
1354 if( zOut==0 ){
@@ -1642,19 +1642,23 @@
1642 }
1643
1644 /*
1645 ** COMMAND: open
1646 **
1647 ** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
1648 **
1649 ** Open a connection to the local repository in FILENAME. A checkout
1650 ** for the repository is created with its root at the working directory.
1651 ** If VERSION is specified then that version is checked out. Otherwise
1652 ** the latest version is checked out. No files other than "manifest"
1653 ** and "manifest.uuid" are modified if the --keep option is present.
1654 **
1655 ** Options:
1656 ** --keep Only modify the manifest and manifest.uuid files
1657 ** --nested Allow opening a repository inside an opened checkout
1658 **
1659 ** See also: close
1660 */
1661 void cmd_open(void){
1662 Blob path;
1663 int vid;
1664 int keepFlag;
1665
+10 -6
--- src/db.c
+++ src/db.c
@@ -1179,14 +1179,14 @@
11791179
** By default, your current login name is used to create the default
11801180
** admin user. This can be overridden using the -A|--admin-user
11811181
** parameter.
11821182
**
11831183
** Options:
1184
-**
1185
-** --admin-user|-A USERNAME
1186
-** --date-override DATETIME
1184
+** --admin-user|-A USERNAME select given USERNAME as admin user
1185
+** --date-override DATETIME use DATETIME as time of the initial checkin
11871186
**
1187
+** See also: clone
11881188
*/
11891189
void create_repository_cmd(void){
11901190
char *zPassword;
11911191
const char *zDate; /* Date of the initial check-in */
11921192
const char *zDefaultUser; /* Optional name of the default user */
@@ -1344,11 +1344,11 @@
13441344
** In either case, the string returned is stored in space obtained
13451345
** from malloc and should be freed by the calling function.
13461346
*/
13471347
char *db_reveal(const char *zKey){
13481348
char *zOut;
1349
- if( g.okRdAddr ){
1349
+ if( g.perm.RdAddr ){
13501350
zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
13511351
}else{
13521352
zOut = 0;
13531353
}
13541354
if( zOut==0 ){
@@ -1642,19 +1642,23 @@
16421642
}
16431643
16441644
/*
16451645
** COMMAND: open
16461646
**
1647
-** Usage: %fossil open FILENAME ?VERSION? ?--keep? ?--nested?
1647
+** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
16481648
**
16491649
** Open a connection to the local repository in FILENAME. A checkout
16501650
** for the repository is created with its root at the working directory.
16511651
** If VERSION is specified then that version is checked out. Otherwise
16521652
** the latest version is checked out. No files other than "manifest"
16531653
** and "manifest.uuid" are modified if the --keep option is present.
16541654
**
1655
-** See also the "close" command.
1655
+** Options:
1656
+** --keep Only modify the manifest and manifest.uuid files
1657
+** --nested Allow opening a repository inside an opened checkout
1658
+**
1659
+** See also: close
16561660
*/
16571661
void cmd_open(void){
16581662
Blob path;
16591663
int vid;
16601664
int keepFlag;
16611665
--- src/db.c
+++ src/db.c
@@ -1179,14 +1179,14 @@
1179 ** By default, your current login name is used to create the default
1180 ** admin user. This can be overridden using the -A|--admin-user
1181 ** parameter.
1182 **
1183 ** Options:
1184 **
1185 ** --admin-user|-A USERNAME
1186 ** --date-override DATETIME
1187 **
 
1188 */
1189 void create_repository_cmd(void){
1190 char *zPassword;
1191 const char *zDate; /* Date of the initial check-in */
1192 const char *zDefaultUser; /* Optional name of the default user */
@@ -1344,11 +1344,11 @@
1344 ** In either case, the string returned is stored in space obtained
1345 ** from malloc and should be freed by the calling function.
1346 */
1347 char *db_reveal(const char *zKey){
1348 char *zOut;
1349 if( g.okRdAddr ){
1350 zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
1351 }else{
1352 zOut = 0;
1353 }
1354 if( zOut==0 ){
@@ -1642,19 +1642,23 @@
1642 }
1643
1644 /*
1645 ** COMMAND: open
1646 **
1647 ** Usage: %fossil open FILENAME ?VERSION? ?--keep? ?--nested?
1648 **
1649 ** Open a connection to the local repository in FILENAME. A checkout
1650 ** for the repository is created with its root at the working directory.
1651 ** If VERSION is specified then that version is checked out. Otherwise
1652 ** the latest version is checked out. No files other than "manifest"
1653 ** and "manifest.uuid" are modified if the --keep option is present.
1654 **
1655 ** See also the "close" command.
 
 
 
 
1656 */
1657 void cmd_open(void){
1658 Blob path;
1659 int vid;
1660 int keepFlag;
1661
--- src/db.c
+++ src/db.c
@@ -1179,14 +1179,14 @@
1179 ** By default, your current login name is used to create the default
1180 ** admin user. This can be overridden using the -A|--admin-user
1181 ** parameter.
1182 **
1183 ** Options:
1184 ** --admin-user|-A USERNAME select given USERNAME as admin user
1185 ** --date-override DATETIME use DATETIME as time of the initial checkin
 
1186 **
1187 ** See also: clone
1188 */
1189 void create_repository_cmd(void){
1190 char *zPassword;
1191 const char *zDate; /* Date of the initial check-in */
1192 const char *zDefaultUser; /* Optional name of the default user */
@@ -1344,11 +1344,11 @@
1344 ** In either case, the string returned is stored in space obtained
1345 ** from malloc and should be freed by the calling function.
1346 */
1347 char *db_reveal(const char *zKey){
1348 char *zOut;
1349 if( g.perm.RdAddr ){
1350 zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
1351 }else{
1352 zOut = 0;
1353 }
1354 if( zOut==0 ){
@@ -1642,19 +1642,23 @@
1642 }
1643
1644 /*
1645 ** COMMAND: open
1646 **
1647 ** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
1648 **
1649 ** Open a connection to the local repository in FILENAME. A checkout
1650 ** for the repository is created with its root at the working directory.
1651 ** If VERSION is specified then that version is checked out. Otherwise
1652 ** the latest version is checked out. No files other than "manifest"
1653 ** and "manifest.uuid" are modified if the --keep option is present.
1654 **
1655 ** Options:
1656 ** --keep Only modify the manifest and manifest.uuid files
1657 ** --nested Allow opening a repository inside an opened checkout
1658 **
1659 ** See also: close
1660 */
1661 void cmd_open(void){
1662 Blob path;
1663 int vid;
1664 int keepFlag;
1665
--- src/descendants.c
+++ src/descendants.c
@@ -264,20 +264,25 @@
264264
}
265265
266266
/*
267267
** COMMAND: descendants
268268
**
269
-** Usage: %fossil descendants ?BASELINE-ID?
269
+** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS?
270270
**
271271
** Find all leaf descendants of the baseline specified or if the argument
272272
** is omitted, of the baseline currently checked out.
273
+**
274
+** Options:
275
+** -R|--repository FILE Extract info from repository FILE
276
+**
277
+** See also: finfo, info, leaves
273278
*/
274279
void descendants_cmd(void){
275280
Stmt q;
276281
int base;
277282
278
- db_must_be_within_tree();
283
+ db_find_and_open_repository(0,0);
279284
if( g.argc==2 ){
280285
base = db_lget_int("checkout", 0);
281286
}else{
282287
base = name_to_typed_rid(g.argv[2], "ci");
283288
}
@@ -294,27 +299,34 @@
294299
}
295300
296301
/*
297302
** COMMAND: leaves
298303
**
299
-** Usage: %fossil leaves ?--all? ?--closed?
304
+** Usage: %fossil leaves ?OPTIONS?
300305
**
301306
** Find leaves of all branches. By default show only open leaves.
302307
** The --all flag causes all leaves (closed and open) to be shown.
303308
** The --closed flag shows only closed leaves.
304309
**
305310
** The --recompute flag causes the content of the "leaf" table in the
306311
** repository database to be recomputed.
312
+**
313
+** Options:
314
+** --all show ALL leaves
315
+** --closed show only closed leaves
316
+** --recompute recompute the "leaf" table in the repository DB
317
+**
318
+** See also: descendants, finfo, info, branch
307319
*/
308320
void leaves_cmd(void){
309321
Stmt q;
310322
Blob sql;
311323
int showAll = find_option("all", 0, 0)!=0;
312324
int showClosed = find_option("closed", 0, 0)!=0;
313325
int recomputeFlag = find_option("recompute",0,0)!=0;
314326
315
- db_must_be_within_tree();
327
+ db_find_and_open_repository(0,0);
316328
if( recomputeFlag ) leaf_rebuild();
317329
blob_zero(&sql);
318330
blob_append(&sql, timeline_query_for_tty(), -1);
319331
blob_appendf(&sql, " AND blob.rid IN leaf");
320332
if( showClosed ){
@@ -338,11 +350,11 @@
338350
Stmt q;
339351
int showAll = P("all")!=0;
340352
int showClosed = P("closed")!=0;
341353
342354
login_check_credentials();
343
- if( !g.okRead ){ login_needed(); return; }
355
+ if( !g.perm.Read ){ login_needed(); return; }
344356
345357
if( !showAll ){
346358
style_submenu_element("All", "All", "leaves?all");
347359
}
348360
if( !showClosed ){
349361
--- src/descendants.c
+++ src/descendants.c
@@ -264,20 +264,25 @@
264 }
265
266 /*
267 ** COMMAND: descendants
268 **
269 ** Usage: %fossil descendants ?BASELINE-ID?
270 **
271 ** Find all leaf descendants of the baseline specified or if the argument
272 ** is omitted, of the baseline currently checked out.
 
 
 
 
 
273 */
274 void descendants_cmd(void){
275 Stmt q;
276 int base;
277
278 db_must_be_within_tree();
279 if( g.argc==2 ){
280 base = db_lget_int("checkout", 0);
281 }else{
282 base = name_to_typed_rid(g.argv[2], "ci");
283 }
@@ -294,27 +299,34 @@
294 }
295
296 /*
297 ** COMMAND: leaves
298 **
299 ** Usage: %fossil leaves ?--all? ?--closed?
300 **
301 ** Find leaves of all branches. By default show only open leaves.
302 ** The --all flag causes all leaves (closed and open) to be shown.
303 ** The --closed flag shows only closed leaves.
304 **
305 ** The --recompute flag causes the content of the "leaf" table in the
306 ** repository database to be recomputed.
 
 
 
 
 
 
 
307 */
308 void leaves_cmd(void){
309 Stmt q;
310 Blob sql;
311 int showAll = find_option("all", 0, 0)!=0;
312 int showClosed = find_option("closed", 0, 0)!=0;
313 int recomputeFlag = find_option("recompute",0,0)!=0;
314
315 db_must_be_within_tree();
316 if( recomputeFlag ) leaf_rebuild();
317 blob_zero(&sql);
318 blob_append(&sql, timeline_query_for_tty(), -1);
319 blob_appendf(&sql, " AND blob.rid IN leaf");
320 if( showClosed ){
@@ -338,11 +350,11 @@
338 Stmt q;
339 int showAll = P("all")!=0;
340 int showClosed = P("closed")!=0;
341
342 login_check_credentials();
343 if( !g.okRead ){ login_needed(); return; }
344
345 if( !showAll ){
346 style_submenu_element("All", "All", "leaves?all");
347 }
348 if( !showClosed ){
349
--- src/descendants.c
+++ src/descendants.c
@@ -264,20 +264,25 @@
264 }
265
266 /*
267 ** COMMAND: descendants
268 **
269 ** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS?
270 **
271 ** Find all leaf descendants of the baseline specified or if the argument
272 ** is omitted, of the baseline currently checked out.
273 **
274 ** Options:
275 ** -R|--repository FILE Extract info from repository FILE
276 **
277 ** See also: finfo, info, leaves
278 */
279 void descendants_cmd(void){
280 Stmt q;
281 int base;
282
283 db_find_and_open_repository(0,0);
284 if( g.argc==2 ){
285 base = db_lget_int("checkout", 0);
286 }else{
287 base = name_to_typed_rid(g.argv[2], "ci");
288 }
@@ -294,27 +299,34 @@
299 }
300
301 /*
302 ** COMMAND: leaves
303 **
304 ** Usage: %fossil leaves ?OPTIONS?
305 **
306 ** Find leaves of all branches. By default show only open leaves.
307 ** The --all flag causes all leaves (closed and open) to be shown.
308 ** The --closed flag shows only closed leaves.
309 **
310 ** The --recompute flag causes the content of the "leaf" table in the
311 ** repository database to be recomputed.
312 **
313 ** Options:
314 ** --all show ALL leaves
315 ** --closed show only closed leaves
316 ** --recompute recompute the "leaf" table in the repository DB
317 **
318 ** See also: descendants, finfo, info, branch
319 */
320 void leaves_cmd(void){
321 Stmt q;
322 Blob sql;
323 int showAll = find_option("all", 0, 0)!=0;
324 int showClosed = find_option("closed", 0, 0)!=0;
325 int recomputeFlag = find_option("recompute",0,0)!=0;
326
327 db_find_and_open_repository(0,0);
328 if( recomputeFlag ) leaf_rebuild();
329 blob_zero(&sql);
330 blob_append(&sql, timeline_query_for_tty(), -1);
331 blob_appendf(&sql, " AND blob.rid IN leaf");
332 if( showClosed ){
@@ -338,11 +350,11 @@
350 Stmt q;
351 int showAll = P("all")!=0;
352 int showClosed = P("closed")!=0;
353
354 login_check_credentials();
355 if( !g.perm.Read ){ login_needed(); return; }
356
357 if( !showAll ){
358 style_submenu_element("All", "All", "leaves?all");
359 }
360 if( !showClosed ){
361
+3 -3
--- src/diff.c
+++ src/diff.c
@@ -837,21 +837,21 @@
837837
int iLimit;
838838
int annFlags = 0;
839839
Annotator ann;
840840
841841
login_check_credentials();
842
- if( !g.okRead ){ login_needed(); return; }
842
+ if( !g.perm.Read ){ login_needed(); return; }
843843
mid = name_to_typed_rid(PD("checkin","0"),"ci");
844844
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
845845
if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
846846
iLimit = atoi(PD("limit","-1"));
847847
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
848848
fossil_redirect_home();
849849
}
850850
style_header("File Annotation");
851851
if( P("filevers") ) annFlags |= ANN_FILE_VERS;
852
- annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags);
852
+ annotate_file(&ann, fnid, mid, g.perm.History, iLimit, annFlags);
853853
if( P("log") ){
854854
int i;
855855
@ <h2>Versions analyzed:</h2>
856856
@ <ol>
857857
for(i=0; i<ann.nVers; i++){
@@ -871,11 +871,11 @@
871871
}
872872
873873
/*
874874
** COMMAND: annotate
875875
**
876
-** %fossil annotate FILENAME
876
+** %fossil annotate ?OPTIONS? FILENAME
877877
**
878878
** Output the text of a file with markings to show when each line of
879879
** the file was last modified.
880880
**
881881
** Options:
882882
--- src/diff.c
+++ src/diff.c
@@ -837,21 +837,21 @@
837 int iLimit;
838 int annFlags = 0;
839 Annotator ann;
840
841 login_check_credentials();
842 if( !g.okRead ){ login_needed(); return; }
843 mid = name_to_typed_rid(PD("checkin","0"),"ci");
844 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
845 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
846 iLimit = atoi(PD("limit","-1"));
847 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
848 fossil_redirect_home();
849 }
850 style_header("File Annotation");
851 if( P("filevers") ) annFlags |= ANN_FILE_VERS;
852 annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags);
853 if( P("log") ){
854 int i;
855 @ <h2>Versions analyzed:</h2>
856 @ <ol>
857 for(i=0; i<ann.nVers; i++){
@@ -871,11 +871,11 @@
871 }
872
873 /*
874 ** COMMAND: annotate
875 **
876 ** %fossil annotate FILENAME
877 **
878 ** Output the text of a file with markings to show when each line of
879 ** the file was last modified.
880 **
881 ** Options:
882
--- src/diff.c
+++ src/diff.c
@@ -837,21 +837,21 @@
837 int iLimit;
838 int annFlags = 0;
839 Annotator ann;
840
841 login_check_credentials();
842 if( !g.perm.Read ){ login_needed(); return; }
843 mid = name_to_typed_rid(PD("checkin","0"),"ci");
844 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
845 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
846 iLimit = atoi(PD("limit","-1"));
847 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
848 fossil_redirect_home();
849 }
850 style_header("File Annotation");
851 if( P("filevers") ) annFlags |= ANN_FILE_VERS;
852 annotate_file(&ann, fnid, mid, g.perm.History, iLimit, annFlags);
853 if( P("log") ){
854 int i;
855 @ <h2>Versions analyzed:</h2>
856 @ <ol>
857 for(i=0; i<ann.nVers; i++){
@@ -871,11 +871,11 @@
871 }
872
873 /*
874 ** COMMAND: annotate
875 **
876 ** %fossil annotate ?OPTIONS? FILENAME
877 **
878 ** Output the text of a file with markings to show when each line of
879 ** the file was last modified.
880 **
881 ** Options:
882
+12 -6
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -71,14 +71,14 @@
7171
Blob file2; /* Content of zFile2 */
7272
const char *zName2; /* Name of zFile2 for display */
7373
7474
/* Read content of zFile2 into memory */
7575
blob_zero(&file2);
76
- if( file_size(zFile2)<0 ){
76
+ if( file_wd_size(zFile2)<0 ){
7777
zName2 = "/dev/null";
7878
}else{
79
- if( file_islink(zFile2) ){
79
+ if( file_wd_islink(zFile2) ){
8080
blob_read_link(&file2, zFile2);
8181
}else{
8282
blob_read_from_file(&file2, zFile2);
8383
}
8484
zName2 = zName;
@@ -193,11 +193,11 @@
193193
Blob fname;
194194
Blob content;
195195
int isLink;
196196
file_tree_name(zFileTreeName, &fname, 1);
197197
historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, 0);
198
- if( !isLink != !file_islink(zFrom) ){
198
+ if( !isLink != !file_wd_islink(zFrom) ){
199199
diff_printf("cannot compute difference between symlink and regular file\n");
200200
}else{
201201
diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, ignoreEolWs);
202202
}
203203
blob_reset(&content);
@@ -288,11 +288,11 @@
288288
srcid = 0;
289289
if( !asNewFile ){ showDiff = 0; }
290290
}
291291
if( showDiff ){
292292
Blob content;
293
- if( !isLink != !file_islink(zFullName) ){
293
+ if( !isLink != !file_wd_islink(zFullName) ){
294294
diff_print_index(zPathname);
295295
diff_printf("--- %s\n+++ %s\n", zPathname, zPathname);
296296
diff_printf("cannot compute difference between symlink and regular file\n");
297297
continue;
298298
}
@@ -431,11 +431,11 @@
431431
432432
/*
433433
** COMMAND: diff
434434
** COMMAND: gdiff
435435
**
436
-** Usage: %fossil diff|gdiff ?options? ?FILE1? ?FILE2 ...?
436
+** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
437437
**
438438
** Show the difference between the current version of each of the FILEs
439439
** specified (as they exist on disk) and that same file as it was checked
440440
** out. Or if the FILE arguments are omitted, show the unsaved changed
441441
** currently in the working check-out.
@@ -454,10 +454,16 @@
454454
** the "setting" command. If no external diff program is configured, then
455455
** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff".
456456
**
457457
** The "-N" or "--new-file" option causes the complete text of added or
458458
** deleted files to be displayed.
459
+**
460
+** Options:
461
+** --from|-r VERSION select VERSION as source for the diff
462
+** --new-file|-N output complete text of added or deleted files
463
+** -i use internal diff logic
464
+** --to VERSION select VERSION as target for the diff
459465
*/
460466
void diff_cmd(void){
461467
int isGDiff; /* True for gdiff. False for normal diff */
462468
int isInternDiff; /* True for internal diff */
463469
int hasNFlag; /* True if -N or --new-file flag is used */
@@ -512,11 +518,11 @@
512518
*/
513519
void vpatch_page(void){
514520
const char *zFrom = P("from");
515521
const char *zTo = P("to");
516522
login_check_credentials();
517
- if( !g.okRead ){ login_needed(); return; }
523
+ if( !g.perm.Read ){ login_needed(); return; }
518524
if( zFrom==0 || zTo==0 ) fossil_redirect_home();
519525
520526
cgi_set_content_type("text/plain");
521527
diff_all_two_versions(zFrom, zTo, 0, DIFF_NEWFILE);
522528
}
523529
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -71,14 +71,14 @@
71 Blob file2; /* Content of zFile2 */
72 const char *zName2; /* Name of zFile2 for display */
73
74 /* Read content of zFile2 into memory */
75 blob_zero(&file2);
76 if( file_size(zFile2)<0 ){
77 zName2 = "/dev/null";
78 }else{
79 if( file_islink(zFile2) ){
80 blob_read_link(&file2, zFile2);
81 }else{
82 blob_read_from_file(&file2, zFile2);
83 }
84 zName2 = zName;
@@ -193,11 +193,11 @@
193 Blob fname;
194 Blob content;
195 int isLink;
196 file_tree_name(zFileTreeName, &fname, 1);
197 historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, 0);
198 if( !isLink != !file_islink(zFrom) ){
199 diff_printf("cannot compute difference between symlink and regular file\n");
200 }else{
201 diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, ignoreEolWs);
202 }
203 blob_reset(&content);
@@ -288,11 +288,11 @@
288 srcid = 0;
289 if( !asNewFile ){ showDiff = 0; }
290 }
291 if( showDiff ){
292 Blob content;
293 if( !isLink != !file_islink(zFullName) ){
294 diff_print_index(zPathname);
295 diff_printf("--- %s\n+++ %s\n", zPathname, zPathname);
296 diff_printf("cannot compute difference between symlink and regular file\n");
297 continue;
298 }
@@ -431,11 +431,11 @@
431
432 /*
433 ** COMMAND: diff
434 ** COMMAND: gdiff
435 **
436 ** Usage: %fossil diff|gdiff ?options? ?FILE1? ?FILE2 ...?
437 **
438 ** Show the difference between the current version of each of the FILEs
439 ** specified (as they exist on disk) and that same file as it was checked
440 ** out. Or if the FILE arguments are omitted, show the unsaved changed
441 ** currently in the working check-out.
@@ -454,10 +454,16 @@
454 ** the "setting" command. If no external diff program is configured, then
455 ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff".
456 **
457 ** The "-N" or "--new-file" option causes the complete text of added or
458 ** deleted files to be displayed.
 
 
 
 
 
 
459 */
460 void diff_cmd(void){
461 int isGDiff; /* True for gdiff. False for normal diff */
462 int isInternDiff; /* True for internal diff */
463 int hasNFlag; /* True if -N or --new-file flag is used */
@@ -512,11 +518,11 @@
512 */
513 void vpatch_page(void){
514 const char *zFrom = P("from");
515 const char *zTo = P("to");
516 login_check_credentials();
517 if( !g.okRead ){ login_needed(); return; }
518 if( zFrom==0 || zTo==0 ) fossil_redirect_home();
519
520 cgi_set_content_type("text/plain");
521 diff_all_two_versions(zFrom, zTo, 0, DIFF_NEWFILE);
522 }
523
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -71,14 +71,14 @@
71 Blob file2; /* Content of zFile2 */
72 const char *zName2; /* Name of zFile2 for display */
73
74 /* Read content of zFile2 into memory */
75 blob_zero(&file2);
76 if( file_wd_size(zFile2)<0 ){
77 zName2 = "/dev/null";
78 }else{
79 if( file_wd_islink(zFile2) ){
80 blob_read_link(&file2, zFile2);
81 }else{
82 blob_read_from_file(&file2, zFile2);
83 }
84 zName2 = zName;
@@ -193,11 +193,11 @@
193 Blob fname;
194 Blob content;
195 int isLink;
196 file_tree_name(zFileTreeName, &fname, 1);
197 historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, 0);
198 if( !isLink != !file_wd_islink(zFrom) ){
199 diff_printf("cannot compute difference between symlink and regular file\n");
200 }else{
201 diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, ignoreEolWs);
202 }
203 blob_reset(&content);
@@ -288,11 +288,11 @@
288 srcid = 0;
289 if( !asNewFile ){ showDiff = 0; }
290 }
291 if( showDiff ){
292 Blob content;
293 if( !isLink != !file_wd_islink(zFullName) ){
294 diff_print_index(zPathname);
295 diff_printf("--- %s\n+++ %s\n", zPathname, zPathname);
296 diff_printf("cannot compute difference between symlink and regular file\n");
297 continue;
298 }
@@ -431,11 +431,11 @@
431
432 /*
433 ** COMMAND: diff
434 ** COMMAND: gdiff
435 **
436 ** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
437 **
438 ** Show the difference between the current version of each of the FILEs
439 ** specified (as they exist on disk) and that same file as it was checked
440 ** out. Or if the FILE arguments are omitted, show the unsaved changed
441 ** currently in the working check-out.
@@ -454,10 +454,16 @@
454 ** the "setting" command. If no external diff program is configured, then
455 ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff".
456 **
457 ** The "-N" or "--new-file" option causes the complete text of added or
458 ** deleted files to be displayed.
459 **
460 ** Options:
461 ** --from|-r VERSION select VERSION as source for the diff
462 ** --new-file|-N output complete text of added or deleted files
463 ** -i use internal diff logic
464 ** --to VERSION select VERSION as target for the diff
465 */
466 void diff_cmd(void){
467 int isGDiff; /* True for gdiff. False for normal diff */
468 int isInternDiff; /* True for internal diff */
469 int hasNFlag; /* True if -N or --new-file flag is used */
@@ -512,11 +518,11 @@
518 */
519 void vpatch_page(void){
520 const char *zFrom = P("from");
521 const char *zTo = P("to");
522 login_check_credentials();
523 if( !g.perm.Read ){ login_needed(); return; }
524 if( zFrom==0 || zTo==0 ) fossil_redirect_home();
525
526 cgi_set_content_type("text/plain");
527 diff_all_two_versions(zFrom, zTo, 0, DIFF_NEWFILE);
528 }
529
+2 -2
--- src/doc.c
+++ src/doc.c
@@ -345,11 +345,11 @@
345345
** WEBPAGE: doc
346346
** URL: /doc?name=BASELINE/PATH
347347
** URL: /doc/BASELINE/PATH
348348
**
349349
** BASELINE can be either a baseline uuid prefix or magic words "tip"
350
-** to me the most recently checked in baseline or "ckout" to mean the
350
+** to mean the most recently checked in baseline or "ckout" to mean the
351351
** content of the local checkout, if any. PATH is the relative pathname
352352
** of some file. This method returns the file content.
353353
**
354354
** If PATH matches the patterns *.wiki or *.txt then formatting content
355355
** is added before returning the file. For all other names, the content
@@ -363,11 +363,11 @@
363363
int i; /* Loop counter */
364364
Blob filebody; /* Content of the documentation file */
365365
char zBaseline[UUID_SIZE+1]; /* Baseline UUID */
366366
367367
login_check_credentials();
368
- if( !g.okRead ){ login_needed(); return; }
368
+ if( !g.perm.Read ){ login_needed(); return; }
369369
zName = PD("name", "tip/index.wiki");
370370
for(i=0; zName[i] && zName[i]!='/'; i++){}
371371
if( zName[i]==0 || i>UUID_SIZE ){
372372
goto doc_not_found;
373373
}
374374
--- src/doc.c
+++ src/doc.c
@@ -345,11 +345,11 @@
345 ** WEBPAGE: doc
346 ** URL: /doc?name=BASELINE/PATH
347 ** URL: /doc/BASELINE/PATH
348 **
349 ** BASELINE can be either a baseline uuid prefix or magic words "tip"
350 ** to me the most recently checked in baseline or "ckout" to mean the
351 ** content of the local checkout, if any. PATH is the relative pathname
352 ** of some file. This method returns the file content.
353 **
354 ** If PATH matches the patterns *.wiki or *.txt then formatting content
355 ** is added before returning the file. For all other names, the content
@@ -363,11 +363,11 @@
363 int i; /* Loop counter */
364 Blob filebody; /* Content of the documentation file */
365 char zBaseline[UUID_SIZE+1]; /* Baseline UUID */
366
367 login_check_credentials();
368 if( !g.okRead ){ login_needed(); return; }
369 zName = PD("name", "tip/index.wiki");
370 for(i=0; zName[i] && zName[i]!='/'; i++){}
371 if( zName[i]==0 || i>UUID_SIZE ){
372 goto doc_not_found;
373 }
374
--- src/doc.c
+++ src/doc.c
@@ -345,11 +345,11 @@
345 ** WEBPAGE: doc
346 ** URL: /doc?name=BASELINE/PATH
347 ** URL: /doc/BASELINE/PATH
348 **
349 ** BASELINE can be either a baseline uuid prefix or magic words "tip"
350 ** to mean the most recently checked in baseline or "ckout" to mean the
351 ** content of the local checkout, if any. PATH is the relative pathname
352 ** of some file. This method returns the file content.
353 **
354 ** If PATH matches the patterns *.wiki or *.txt then formatting content
355 ** is added before returning the file. For all other names, the content
@@ -363,11 +363,11 @@
363 int i; /* Loop counter */
364 Blob filebody; /* Content of the documentation file */
365 char zBaseline[UUID_SIZE+1]; /* Baseline UUID */
366
367 login_check_credentials();
368 if( !g.perm.Read ){ login_needed(); return; }
369 zName = PD("name", "tip/index.wiki");
370 for(i=0; zName[i] && zName[i]!='/'; i++){}
371 if( zName[i]==0 || i>UUID_SIZE ){
372 goto doc_not_found;
373 }
374
+6 -6
--- src/event.c
+++ src/event.c
@@ -36,11 +36,11 @@
3636
char zShort[12];
3737
3838
zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
3939
tagid);
4040
sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId);
41
- if( g.okHistory ){
41
+ if( g.perm.History ){
4242
@ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>]
4343
}else{
4444
@ [%s(zShort)]
4545
}
4646
free(zEventId);
@@ -74,11 +74,11 @@
7474
7575
7676
/* wiki-read privilege is needed in order to read events.
7777
*/
7878
login_check_credentials();
79
- if( !g.okRdWiki ){
79
+ if( !g.perm.RdWiki ){
8080
login_needed();
8181
return;
8282
}
8383
8484
zEventId = P("name");
@@ -123,18 +123,18 @@
123123
style_header(blob_str(&title));
124124
}else{
125125
style_header("Event %S", zEventId);
126126
tail = fullbody;
127127
}
128
- if( g.okWrWiki && g.okWrite && nextRid==0 ){
128
+ if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
129129
style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
130130
g.zTop, zEventId);
131131
}
132132
zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
133133
style_submenu_element("Context", "Context", "%s/timeline?c=%T",
134134
g.zTop, zETime);
135
- if( g.okHistory ){
135
+ if( g.perm.History ){
136136
if( showDetail ){
137137
style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
138138
g.zTop, zEventId, zUuid);
139139
if( nextRid ){
140140
char *zNext;
@@ -157,11 +157,11 @@
157157
"%s/event?name=%s&amp;aid=%s&amp;detail=1",
158158
g.zTop, zEventId, zUuid);
159159
}
160160
}
161161
162
- if( showDetail && g.okHistory ){
162
+ if( showDetail && g.perm.History ){
163163
int i;
164164
const char *zClr = 0;
165165
Blob comment;
166166
167167
zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
@@ -236,11 +236,11 @@
236236
free(zTag);
237237
238238
/* Need both check-in and wiki-write or wiki-create privileges in order
239239
** to edit/create an event.
240240
*/
241
- if( !g.okWrite || (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){
241
+ if( !g.perm.Write || (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
242242
login_needed();
243243
return;
244244
}
245245
246246
/* Figure out the color */
247247
--- src/event.c
+++ src/event.c
@@ -36,11 +36,11 @@
36 char zShort[12];
37
38 zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
39 tagid);
40 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId);
41 if( g.okHistory ){
42 @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>]
43 }else{
44 @ [%s(zShort)]
45 }
46 free(zEventId);
@@ -74,11 +74,11 @@
74
75
76 /* wiki-read privilege is needed in order to read events.
77 */
78 login_check_credentials();
79 if( !g.okRdWiki ){
80 login_needed();
81 return;
82 }
83
84 zEventId = P("name");
@@ -123,18 +123,18 @@
123 style_header(blob_str(&title));
124 }else{
125 style_header("Event %S", zEventId);
126 tail = fullbody;
127 }
128 if( g.okWrWiki && g.okWrite && nextRid==0 ){
129 style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
130 g.zTop, zEventId);
131 }
132 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
133 style_submenu_element("Context", "Context", "%s/timeline?c=%T",
134 g.zTop, zETime);
135 if( g.okHistory ){
136 if( showDetail ){
137 style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
138 g.zTop, zEventId, zUuid);
139 if( nextRid ){
140 char *zNext;
@@ -157,11 +157,11 @@
157 "%s/event?name=%s&amp;aid=%s&amp;detail=1",
158 g.zTop, zEventId, zUuid);
159 }
160 }
161
162 if( showDetail && g.okHistory ){
163 int i;
164 const char *zClr = 0;
165 Blob comment;
166
167 zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
@@ -236,11 +236,11 @@
236 free(zTag);
237
238 /* Need both check-in and wiki-write or wiki-create privileges in order
239 ** to edit/create an event.
240 */
241 if( !g.okWrite || (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){
242 login_needed();
243 return;
244 }
245
246 /* Figure out the color */
247
--- src/event.c
+++ src/event.c
@@ -36,11 +36,11 @@
36 char zShort[12];
37
38 zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
39 tagid);
40 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId);
41 if( g.perm.History ){
42 @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>]
43 }else{
44 @ [%s(zShort)]
45 }
46 free(zEventId);
@@ -74,11 +74,11 @@
74
75
76 /* wiki-read privilege is needed in order to read events.
77 */
78 login_check_credentials();
79 if( !g.perm.RdWiki ){
80 login_needed();
81 return;
82 }
83
84 zEventId = P("name");
@@ -123,18 +123,18 @@
123 style_header(blob_str(&title));
124 }else{
125 style_header("Event %S", zEventId);
126 tail = fullbody;
127 }
128 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
129 style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
130 g.zTop, zEventId);
131 }
132 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
133 style_submenu_element("Context", "Context", "%s/timeline?c=%T",
134 g.zTop, zETime);
135 if( g.perm.History ){
136 if( showDetail ){
137 style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
138 g.zTop, zEventId, zUuid);
139 if( nextRid ){
140 char *zNext;
@@ -157,11 +157,11 @@
157 "%s/event?name=%s&amp;aid=%s&amp;detail=1",
158 g.zTop, zEventId, zUuid);
159 }
160 }
161
162 if( showDetail && g.perm.History ){
163 int i;
164 const char *zClr = 0;
165 Blob comment;
166
167 zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
@@ -236,11 +236,11 @@
236 free(zTag);
237
238 /* Need both check-in and wiki-write or wiki-create privileges in order
239 ** to edit/create an event.
240 */
241 if( !g.perm.Write || (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
242 login_needed();
243 return;
244 }
245
246 /* Figure out the color */
247
+8 -1
--- src/export.c
+++ src/export.c
@@ -84,11 +84,11 @@
8484
#define COMMITMARK(rid) ((rid) * 2 + 1)
8585
8686
/*
8787
** COMMAND: export
8888
**
89
-** Usage: %fossil export --git ?options? ?REPOSITORY?
89
+** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
9090
**
9191
** Write an export of all check-ins to standard output. The export is
9292
** written in the git-fast-export file format assuming the --git option is
9393
** provided. The git-fast-export format is currently the only VCS
9494
** interchange format supported, though other formats may be added in
@@ -103,10 +103,17 @@
103103
** If the "--import-marks FILE" option is used, it contains a list of
104104
** rids to skip.
105105
**
106106
** If the "--export-marks FILE" option is used, the rid of all commits and
107107
** blobs written on exit for use with "--import-marks" on the next run.
108
+**
109
+** Options:
110
+** --export-marks FILE export rids of exported data to FILE
111
+** --import-marks FILE read rids of data to ignore from FILE
112
+** --repository|-R REPOSITORY export the given REPOSITORY
113
+**
114
+** See also: import
108115
*/
109116
void export_cmd(void){
110117
Stmt q, q2, q3;
111118
int i;
112119
Bag blobs, vers;
113120
--- src/export.c
+++ src/export.c
@@ -84,11 +84,11 @@
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
@@ -103,10 +103,17 @@
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
--- src/export.c
+++ src/export.c
@@ -84,11 +84,11 @@
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
@@ -103,10 +103,17 @@
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 ** Options:
110 ** --export-marks FILE export rids of exported data to FILE
111 ** --import-marks FILE read rids of data to ignore from FILE
112 ** --repository|-R REPOSITORY export the given REPOSITORY
113 **
114 ** See also: import
115 */
116 void export_cmd(void){
117 Stmt q, q2, q3;
118 int i;
119 Bag blobs, vers;
120
+129 -78
--- src/file.c
+++ src/file.c
@@ -13,11 +13,16 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** File utilities
18
+** File utilities.
19
+**
20
+** Functions named file_* are generic functions that always follow symlinks.
21
+**
22
+** Functions named file_wd_* are to be used for files inside working
23
+** directories. They follow symlinks depending on 'allow-symlinks' setting.
1924
*/
2025
#include "config.h"
2126
#include <sys/types.h>
2227
#include <sys/stat.h>
2328
#include <unistd.h>
@@ -32,119 +37,129 @@
3237
** larger than 2GB.
3338
*/
3439
#if defined(_WIN32) && defined(__MSVCRT__)
3540
# define stat _stati64
3641
#endif
42
+/*
43
+** On Windows S_ISLNK always returns FALSE.
44
+*/
45
+#if defined(_WIN32)
46
+# define S_ISLNK(x) (0)
47
+#endif
3748
static int fileStatValid = 0;
3849
static struct stat fileStat;
3950
40
-static int fossil_stat(const char *zFilename, struct stat *buf){
51
+/*
52
+** Fill stat buf with information received from stat() or lstat().
53
+** lstat() is called on Unix if isWd is TRUE and allow-symlinks setting is on.
54
+**
55
+*/
56
+static int fossil_stat(const char *zFilename, struct stat *buf, int isWd){
4157
#if !defined(_WIN32)
42
- if( g.allowSymlinks ){
58
+ if( isWd && g.allowSymlinks ){
4359
return lstat(zFilename, buf);
4460
}else{
4561
return stat(zFilename, buf);
4662
}
4763
#else
48
- return stat(zFilename, buf);
64
+ int rc = 0;
65
+ char *zMbcs = fossil_utf8_to_mbcs(zFilename);
66
+ rc = stat(zMbcs, buf);
67
+ fossil_mbcs_free(zMbcs);
68
+ return rc;
4969
#endif
5070
}
5171
5272
/*
5373
** Fill in the fileStat variable for the file named zFilename.
5474
** If zFilename==0, then use the previous value of fileStat if
5575
** there is a previous value.
5676
**
77
+** If isWd is TRUE, do lstat() instead of stat() if allow-symlinks is on.
78
+**
5779
** Return the number of errors. No error messages are generated.
5880
*/
59
-static int getStat(const char *zFilename){
81
+static int getStat(const char *zFilename, int isWd){
6082
int rc = 0;
6183
if( zFilename==0 ){
6284
if( fileStatValid==0 ) rc = 1;
6385
}else{
64
- char *zMbcs = fossil_utf8_to_mbcs(zFilename);
65
- if( fossil_stat(zMbcs, &fileStat)!=0 ){
86
+ if( fossil_stat(zFilename, &fileStat, isWd)!=0 ){
6687
fileStatValid = 0;
6788
rc = 1;
6889
}else{
6990
fileStatValid = 1;
7091
rc = 0;
7192
}
72
- fossil_mbcs_free(zMbcs);
7393
}
7494
return rc;
7595
}
76
-
7796
7897
/*
7998
** Return the size of a file in bytes. Return -1 if the file does not
8099
** exist. If zFilename is NULL, return the size of the most recently
81100
** stat-ed file.
82101
*/
83102
i64 file_size(const char *zFilename){
84
- return getStat(zFilename) ? -1 : fileStat.st_size;
103
+ return getStat(zFilename, 0) ? -1 : fileStat.st_size;
104
+}
105
+
106
+/*
107
+** Same as file_size(), but takes into account symlinks.
108
+*/
109
+i64 file_wd_size(const char *zFilename){
110
+ return getStat(zFilename, 1) ? -1 : fileStat.st_size;
85111
}
86112
87113
/*
88114
** Return the modification time for a file. Return -1 if the file
89115
** does not exist. If zFilename is NULL return the size of the most
90116
** recently stat-ed file.
91117
*/
92118
i64 file_mtime(const char *zFilename){
93
- return getStat(zFilename) ? -1 : fileStat.st_mtime;
119
+ return getStat(zFilename, 0) ? -1 : fileStat.st_mtime;
120
+}
121
+
122
+/*
123
+** Same as file_mtime(), but takes into account symlinks.
124
+*/
125
+i64 file_wd_mtime(const char *zFilename){
126
+ return getStat(zFilename, 1) ? -1 : fileStat.st_mtime;
94127
}
95128
96129
/*
97130
** Return TRUE if the named file is an ordinary file or symlink
98131
** and symlinks are allowed.
99132
** Return false for directories, devices, fifos, etc.
100133
*/
101
-int file_isfile_or_link(const char *zFilename){
102
-#if !defined(_WIN32)
103
- if ( g.allowSymlinks ){
104
- return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode) || S_ISLNK(fileStat.st_mode);
105
- }else{
106
- return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
107
- }
108
-#else
109
- return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
110
-#endif
134
+int file_wd_isfile_or_link(const char *zFilename){
135
+ return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) ||
136
+ S_ISLNK(fileStat.st_mode);
111137
}
112138
113139
/*
114140
** Return TRUE if the named file is an ordinary file. Return false
115141
** for directories, devices, fifos, symlinks, etc.
116142
*/
117143
int file_isfile(const char *zFilename){
118
- return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
144
+ return getStat(zFilename, 0) ? 0 : S_ISREG(fileStat.st_mode);
119145
}
120146
121147
/*
122
-** Return TRUE if the named file is a symlink and symlinks are allowed.
123
-** Return false for all other cases.
124
-**
125
-** On Windows, always return False.
148
+** Same as file_isfile(), but takes into account symlinks.
126149
*/
127
-int file_islink(const char *zFilename){
128
-#if !defined(_WIN32)
129
- if( g.allowSymlinks ){
130
- return getStat(zFilename) ? 0 : S_ISLNK(fileStat.st_mode);
131
- }else{
132
- return 0;
133
- }
134
-#else
135
- return 0;
136
-#endif
150
+int file_wd_isfile(const char *zFilename){
151
+ return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode);
137152
}
138153
139154
/*
140155
** Create symlink to file on Unix, or plain-text file with
141156
** symlink target if "allow-symlinks" is off or we're on Windows.
142157
**
143158
** Arguments: target file (symlink will point to it), link file
144159
**/
145
-void create_symlink(const char *zTargetFile, const char *zLinkFile){
160
+void symlink_create(const char *zTargetFile, const char *zLinkFile){
146161
#if !defined(_WIN32)
147162
if( g.allowSymlinks ){
148163
int i, nName;
149164
char *zName, zBuf[1000];
150165
@@ -180,36 +195,62 @@
180195
blob_reset(&content);
181196
}
182197
}
183198
184199
/*
185
-** Return TRUE if the named file is an executable. Return false
186
-** for directories, devices, fifos, symlinks, etc.
200
+** Copy symbolic link from zFrom to zTo.
201
+*/
202
+void symlink_copy(const char *zFrom, const char *zTo){
203
+ Blob content;
204
+ blob_read_link(&content, zFrom);
205
+ symlink_create(blob_str(&content), zTo);
206
+ blob_reset(&content);
207
+}
208
+
209
+/*
210
+** Return file permissions (normal, executable, or symlink):
211
+** - PERM_EXE if file is executable;
212
+** - PERM_LNK on Unix if file is symlink and allow-symlinks option is on;
213
+** - PERM_REG for all other cases (regular file, directory, fifo, etc).
187214
*/
188
-int file_isexe(const char *zFilename){
189
- if( getStat(zFilename) || !S_ISREG(fileStat.st_mode) ) return 0;
215
+int file_wd_perm(const char *zFilename){
216
+ if( getStat(zFilename, 1) ) return PERM_REG;
190217
#if defined(_WIN32)
191218
# if defined(__DMC__) || defined(_MSC_VER)
192219
# define S_IXUSR _S_IEXEC
193220
# endif
194
- return ((S_IXUSR)&fileStat.st_mode)!=0;
221
+ if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
222
+ return PERM_EXE;
223
+ else
224
+ return PERM_REG;
195225
#else
196
- return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0;
197
-#endif
198
-}
199
-
200
-
201
-/*
202
-** Return file "permissions" (normal, executable, or symlink).
203
-*/
204
-int file_perm(const char *zFilename){
205
- /*TODO(dchest): optimize by calling stat once.*/
206
- if( file_isexe(zFilename) )
226
+ if( S_ISREG(fileStat.st_mode) &&
227
+ ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0 )
207228
return PERM_EXE;
208
- if( file_islink(zFilename) )
229
+ else if( g.allowSymlinks && S_ISLNK(fileStat.st_mode) )
209230
return PERM_LNK;
210
- return PERM_REG;
231
+ else
232
+ return PERM_REG;
233
+#endif
234
+}
235
+
236
+/*
237
+** Return TRUE if the named file is an executable. Return false
238
+** for directories, devices, fifos, symlinks, etc.
239
+*/
240
+int file_wd_isexe(const char *zFilename){
241
+ return file_wd_perm(zFilename)==PERM_EXE;
242
+}
243
+
244
+/*
245
+** Return TRUE if the named file is a symlink and symlinks are allowed.
246
+** Return false for all other cases.
247
+**
248
+** On Windows, always return False.
249
+*/
250
+int file_wd_islink(const char *zFilename){
251
+ return file_wd_perm(zFilename)==PERM_LNK;
211252
}
212253
213254
/*
214255
** Return 1 if zFilename is a directory. Return 0 if zFilename
215256
** does not exist. Return 2 if zFilename exists but is something
@@ -219,25 +260,35 @@
219260
int rc;
220261
221262
if( zFilename ){
222263
char *zFN = mprintf("%s", zFilename);
223264
file_simplify_name(zFN, -1);
224
- rc = getStat(zFN);
265
+ rc = getStat(zFN, 0);
266
+ free(zFN);
267
+ }else{
268
+ rc = getStat(0, 0);
269
+ }
270
+ return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
271
+}
272
+
273
+/*
274
+** Same as file_isdir(), but takes into account symlinks.
275
+*/
276
+int file_wd_isdir(const char *zFilename){
277
+ int rc;
278
+
279
+ if( zFilename ){
280
+ char *zFN = mprintf("%s", zFilename);
281
+ file_simplify_name(zFN, -1);
282
+ rc = getStat(zFN, 1);
225283
free(zFN);
226284
}else{
227
- rc = getStat(0);
228
- }
229
-#if !defined(_WIN32)
230
- if( g.allowSymlinks ){
231
- return rc ? 0 : (S_ISDIR(fileStat.st_mode) && !S_ISLNK(fileStat.st_mode) ? 1 : 2);
232
- }else{
233
- return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
234
- }
235
-#else
236
- return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
237
-#endif
238
-}
285
+ rc = getStat(0, 1);
286
+ }
287
+ return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
288
+}
289
+
239290
240291
/*
241292
** Wrapper around the access() system call.
242293
*/
243294
int file_access(const char *zFilename, int flags){
@@ -305,15 +356,15 @@
305356
306357
/*
307358
** Set or clear the execute bit on a file. Return true if a change
308359
** occurred and false if this routine is a no-op.
309360
*/
310
-int file_setexe(const char *zFilename, int onoff){
361
+int file_wd_setexe(const char *zFilename, int onoff){
311362
int rc = 0;
312363
#if !defined(_WIN32)
313364
struct stat buf;
314
- if( fossil_stat(zFilename, &buf)!=0 || S_ISLNK(buf.st_mode) ) return 0;
365
+ if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0;
315366
if( onoff ){
316367
int targetMode = (buf.st_mode & 0444)>>2;
317368
if( (buf.st_mode & 0111)!=targetMode ){
318369
chmod(zFilename, buf.st_mode | targetMode);
319370
rc = 1;
@@ -574,19 +625,19 @@
574625
char zBuf[100];
575626
const char *zName = g.argv[i];
576627
file_canonical_name(zName, &x);
577628
fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
578629
blob_reset(&x);
579
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName));
630
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
580631
fossil_print(" file_size = %s\n", zBuf);
581
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName));
632
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
582633
fossil_print(" file_mtime = %s\n", zBuf);
583
- fossil_print(" file_isfile = %d\n", file_isfile(zName));
584
- fossil_print(" file_isfile_or_link = %d\n", file_isfile_or_link(zName));
585
- fossil_print(" file_islink = %d\n", file_islink(zName));
586
- fossil_print(" file_isexe = %d\n", file_isexe(zName));
587
- fossil_print(" file_isdir = %d\n", file_isdir(zName));
634
+ fossil_print(" file_isfile = %d\n", file_wd_isfile(zName));
635
+ fossil_print(" file_isfile_or_link = %d\n",file_wd_isfile_or_link(zName));
636
+ fossil_print(" file_islink = %d\n", file_wd_islink(zName));
637
+ fossil_print(" file_isexe = %d\n", file_wd_isexe(zName));
638
+ fossil_print(" file_isdir = %d\n", file_wd_isdir(zName));
588639
}
589640
}
590641
591642
/*
592643
** Return TRUE if the given filename is canonical.
@@ -851,11 +902,11 @@
851902
Blob onDisk;
852903
853904
iSize = file_size(zName);
854905
if( iSize<0 ) return 0;
855906
if( iSize!=blob_size(pContent) ) return 0;
856
- if( file_islink(zName) ){
907
+ if( file_wd_islink(zName) ){
857908
blob_read_link(&onDisk, zName);
858909
}else{
859910
blob_read_from_file(&onDisk, zName);
860911
}
861912
rc = blob_compare(&onDisk, pContent);
862913
--- src/file.c
+++ src/file.c
@@ -13,11 +13,16 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** File utilities
 
 
 
 
 
19 */
20 #include "config.h"
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
@@ -32,119 +37,129 @@
32 ** larger than 2GB.
33 */
34 #if defined(_WIN32) && defined(__MSVCRT__)
35 # define stat _stati64
36 #endif
 
 
 
 
 
 
37 static int fileStatValid = 0;
38 static struct stat fileStat;
39
40 static int fossil_stat(const char *zFilename, struct stat *buf){
 
 
 
 
 
41 #if !defined(_WIN32)
42 if( g.allowSymlinks ){
43 return lstat(zFilename, buf);
44 }else{
45 return stat(zFilename, buf);
46 }
47 #else
48 return stat(zFilename, buf);
 
 
 
 
49 #endif
50 }
51
52 /*
53 ** Fill in the fileStat variable for the file named zFilename.
54 ** If zFilename==0, then use the previous value of fileStat if
55 ** there is a previous value.
56 **
 
 
57 ** Return the number of errors. No error messages are generated.
58 */
59 static int getStat(const char *zFilename){
60 int rc = 0;
61 if( zFilename==0 ){
62 if( fileStatValid==0 ) rc = 1;
63 }else{
64 char *zMbcs = fossil_utf8_to_mbcs(zFilename);
65 if( fossil_stat(zMbcs, &fileStat)!=0 ){
66 fileStatValid = 0;
67 rc = 1;
68 }else{
69 fileStatValid = 1;
70 rc = 0;
71 }
72 fossil_mbcs_free(zMbcs);
73 }
74 return rc;
75 }
76
77
78 /*
79 ** Return the size of a file in bytes. Return -1 if the file does not
80 ** exist. If zFilename is NULL, return the size of the most recently
81 ** stat-ed file.
82 */
83 i64 file_size(const char *zFilename){
84 return getStat(zFilename) ? -1 : fileStat.st_size;
 
 
 
 
 
 
 
85 }
86
87 /*
88 ** Return the modification time for a file. Return -1 if the file
89 ** does not exist. If zFilename is NULL return the size of the most
90 ** recently stat-ed file.
91 */
92 i64 file_mtime(const char *zFilename){
93 return getStat(zFilename) ? -1 : fileStat.st_mtime;
 
 
 
 
 
 
 
94 }
95
96 /*
97 ** Return TRUE if the named file is an ordinary file or symlink
98 ** and symlinks are allowed.
99 ** Return false for directories, devices, fifos, etc.
100 */
101 int file_isfile_or_link(const char *zFilename){
102 #if !defined(_WIN32)
103 if ( g.allowSymlinks ){
104 return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode) || S_ISLNK(fileStat.st_mode);
105 }else{
106 return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
107 }
108 #else
109 return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
110 #endif
111 }
112
113 /*
114 ** Return TRUE if the named file is an ordinary file. Return false
115 ** for directories, devices, fifos, symlinks, etc.
116 */
117 int file_isfile(const char *zFilename){
118 return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
119 }
120
121 /*
122 ** Return TRUE if the named file is a symlink and symlinks are allowed.
123 ** Return false for all other cases.
124 **
125 ** On Windows, always return False.
126 */
127 int file_islink(const char *zFilename){
128 #if !defined(_WIN32)
129 if( g.allowSymlinks ){
130 return getStat(zFilename) ? 0 : S_ISLNK(fileStat.st_mode);
131 }else{
132 return 0;
133 }
134 #else
135 return 0;
136 #endif
137 }
138
139 /*
140 ** Create symlink to file on Unix, or plain-text file with
141 ** symlink target if "allow-symlinks" is off or we're on Windows.
142 **
143 ** Arguments: target file (symlink will point to it), link file
144 **/
145 void create_symlink(const char *zTargetFile, const char *zLinkFile){
146 #if !defined(_WIN32)
147 if( g.allowSymlinks ){
148 int i, nName;
149 char *zName, zBuf[1000];
150
@@ -180,36 +195,62 @@
180 blob_reset(&content);
181 }
182 }
183
184 /*
185 ** Return TRUE if the named file is an executable. Return false
186 ** for directories, devices, fifos, symlinks, etc.
 
 
 
 
 
 
 
 
 
 
 
 
187 */
188 int file_isexe(const char *zFilename){
189 if( getStat(zFilename) || !S_ISREG(fileStat.st_mode) ) return 0;
190 #if defined(_WIN32)
191 # if defined(__DMC__) || defined(_MSC_VER)
192 # define S_IXUSR _S_IEXEC
193 # endif
194 return ((S_IXUSR)&fileStat.st_mode)!=0;
 
 
 
195 #else
196 return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0;
197 #endif
198 }
199
200
201 /*
202 ** Return file "permissions" (normal, executable, or symlink).
203 */
204 int file_perm(const char *zFilename){
205 /*TODO(dchest): optimize by calling stat once.*/
206 if( file_isexe(zFilename) )
207 return PERM_EXE;
208 if( file_islink(zFilename) )
209 return PERM_LNK;
210 return PERM_REG;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211 }
212
213 /*
214 ** Return 1 if zFilename is a directory. Return 0 if zFilename
215 ** does not exist. Return 2 if zFilename exists but is something
@@ -219,25 +260,35 @@
219 int rc;
220
221 if( zFilename ){
222 char *zFN = mprintf("%s", zFilename);
223 file_simplify_name(zFN, -1);
224 rc = getStat(zFN);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225 free(zFN);
226 }else{
227 rc = getStat(0);
228 }
229 #if !defined(_WIN32)
230 if( g.allowSymlinks ){
231 return rc ? 0 : (S_ISDIR(fileStat.st_mode) && !S_ISLNK(fileStat.st_mode) ? 1 : 2);
232 }else{
233 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
234 }
235 #else
236 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
237 #endif
238 }
239
240 /*
241 ** Wrapper around the access() system call.
242 */
243 int file_access(const char *zFilename, int flags){
@@ -305,15 +356,15 @@
305
306 /*
307 ** Set or clear the execute bit on a file. Return true if a change
308 ** occurred and false if this routine is a no-op.
309 */
310 int file_setexe(const char *zFilename, int onoff){
311 int rc = 0;
312 #if !defined(_WIN32)
313 struct stat buf;
314 if( fossil_stat(zFilename, &buf)!=0 || S_ISLNK(buf.st_mode) ) return 0;
315 if( onoff ){
316 int targetMode = (buf.st_mode & 0444)>>2;
317 if( (buf.st_mode & 0111)!=targetMode ){
318 chmod(zFilename, buf.st_mode | targetMode);
319 rc = 1;
@@ -574,19 +625,19 @@
574 char zBuf[100];
575 const char *zName = g.argv[i];
576 file_canonical_name(zName, &x);
577 fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
578 blob_reset(&x);
579 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName));
580 fossil_print(" file_size = %s\n", zBuf);
581 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName));
582 fossil_print(" file_mtime = %s\n", zBuf);
583 fossil_print(" file_isfile = %d\n", file_isfile(zName));
584 fossil_print(" file_isfile_or_link = %d\n", file_isfile_or_link(zName));
585 fossil_print(" file_islink = %d\n", file_islink(zName));
586 fossil_print(" file_isexe = %d\n", file_isexe(zName));
587 fossil_print(" file_isdir = %d\n", file_isdir(zName));
588 }
589 }
590
591 /*
592 ** Return TRUE if the given filename is canonical.
@@ -851,11 +902,11 @@
851 Blob onDisk;
852
853 iSize = file_size(zName);
854 if( iSize<0 ) return 0;
855 if( iSize!=blob_size(pContent) ) return 0;
856 if( file_islink(zName) ){
857 blob_read_link(&onDisk, zName);
858 }else{
859 blob_read_from_file(&onDisk, zName);
860 }
861 rc = blob_compare(&onDisk, pContent);
862
--- src/file.c
+++ src/file.c
@@ -13,11 +13,16 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** File utilities.
19 **
20 ** Functions named file_* are generic functions that always follow symlinks.
21 **
22 ** Functions named file_wd_* are to be used for files inside working
23 ** directories. They follow symlinks depending on 'allow-symlinks' setting.
24 */
25 #include "config.h"
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
@@ -32,119 +37,129 @@
37 ** larger than 2GB.
38 */
39 #if defined(_WIN32) && defined(__MSVCRT__)
40 # define stat _stati64
41 #endif
42 /*
43 ** On Windows S_ISLNK always returns FALSE.
44 */
45 #if defined(_WIN32)
46 # define S_ISLNK(x) (0)
47 #endif
48 static int fileStatValid = 0;
49 static struct stat fileStat;
50
51 /*
52 ** Fill stat buf with information received from stat() or lstat().
53 ** lstat() is called on Unix if isWd is TRUE and allow-symlinks setting is on.
54 **
55 */
56 static int fossil_stat(const char *zFilename, struct stat *buf, int isWd){
57 #if !defined(_WIN32)
58 if( isWd && g.allowSymlinks ){
59 return lstat(zFilename, buf);
60 }else{
61 return stat(zFilename, buf);
62 }
63 #else
64 int rc = 0;
65 char *zMbcs = fossil_utf8_to_mbcs(zFilename);
66 rc = stat(zMbcs, buf);
67 fossil_mbcs_free(zMbcs);
68 return rc;
69 #endif
70 }
71
72 /*
73 ** Fill in the fileStat variable for the file named zFilename.
74 ** If zFilename==0, then use the previous value of fileStat if
75 ** there is a previous value.
76 **
77 ** If isWd is TRUE, do lstat() instead of stat() if allow-symlinks is on.
78 **
79 ** Return the number of errors. No error messages are generated.
80 */
81 static int getStat(const char *zFilename, int isWd){
82 int rc = 0;
83 if( zFilename==0 ){
84 if( fileStatValid==0 ) rc = 1;
85 }else{
86 if( fossil_stat(zFilename, &fileStat, isWd)!=0 ){
 
87 fileStatValid = 0;
88 rc = 1;
89 }else{
90 fileStatValid = 1;
91 rc = 0;
92 }
 
93 }
94 return rc;
95 }
 
96
97 /*
98 ** Return the size of a file in bytes. Return -1 if the file does not
99 ** exist. If zFilename is NULL, return the size of the most recently
100 ** stat-ed file.
101 */
102 i64 file_size(const char *zFilename){
103 return getStat(zFilename, 0) ? -1 : fileStat.st_size;
104 }
105
106 /*
107 ** Same as file_size(), but takes into account symlinks.
108 */
109 i64 file_wd_size(const char *zFilename){
110 return getStat(zFilename, 1) ? -1 : fileStat.st_size;
111 }
112
113 /*
114 ** Return the modification time for a file. Return -1 if the file
115 ** does not exist. If zFilename is NULL return the size of the most
116 ** recently stat-ed file.
117 */
118 i64 file_mtime(const char *zFilename){
119 return getStat(zFilename, 0) ? -1 : fileStat.st_mtime;
120 }
121
122 /*
123 ** Same as file_mtime(), but takes into account symlinks.
124 */
125 i64 file_wd_mtime(const char *zFilename){
126 return getStat(zFilename, 1) ? -1 : fileStat.st_mtime;
127 }
128
129 /*
130 ** Return TRUE if the named file is an ordinary file or symlink
131 ** and symlinks are allowed.
132 ** Return false for directories, devices, fifos, etc.
133 */
134 int file_wd_isfile_or_link(const char *zFilename){
135 return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) ||
136 S_ISLNK(fileStat.st_mode);
 
 
 
 
 
 
 
137 }
138
139 /*
140 ** Return TRUE if the named file is an ordinary file. Return false
141 ** for directories, devices, fifos, symlinks, etc.
142 */
143 int file_isfile(const char *zFilename){
144 return getStat(zFilename, 0) ? 0 : S_ISREG(fileStat.st_mode);
145 }
146
147 /*
148 ** Same as file_isfile(), but takes into account symlinks.
 
 
 
149 */
150 int file_wd_isfile(const char *zFilename){
151 return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode);
 
 
 
 
 
 
 
 
152 }
153
154 /*
155 ** Create symlink to file on Unix, or plain-text file with
156 ** symlink target if "allow-symlinks" is off or we're on Windows.
157 **
158 ** Arguments: target file (symlink will point to it), link file
159 **/
160 void symlink_create(const char *zTargetFile, const char *zLinkFile){
161 #if !defined(_WIN32)
162 if( g.allowSymlinks ){
163 int i, nName;
164 char *zName, zBuf[1000];
165
@@ -180,36 +195,62 @@
195 blob_reset(&content);
196 }
197 }
198
199 /*
200 ** Copy symbolic link from zFrom to zTo.
201 */
202 void symlink_copy(const char *zFrom, const char *zTo){
203 Blob content;
204 blob_read_link(&content, zFrom);
205 symlink_create(blob_str(&content), zTo);
206 blob_reset(&content);
207 }
208
209 /*
210 ** Return file permissions (normal, executable, or symlink):
211 ** - PERM_EXE if file is executable;
212 ** - PERM_LNK on Unix if file is symlink and allow-symlinks option is on;
213 ** - PERM_REG for all other cases (regular file, directory, fifo, etc).
214 */
215 int file_wd_perm(const char *zFilename){
216 if( getStat(zFilename, 1) ) return PERM_REG;
217 #if defined(_WIN32)
218 # if defined(__DMC__) || defined(_MSC_VER)
219 # define S_IXUSR _S_IEXEC
220 # endif
221 if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
222 return PERM_EXE;
223 else
224 return PERM_REG;
225 #else
226 if( S_ISREG(fileStat.st_mode) &&
227 ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0 )
 
 
 
 
 
 
 
 
 
228 return PERM_EXE;
229 else if( g.allowSymlinks && S_ISLNK(fileStat.st_mode) )
230 return PERM_LNK;
231 else
232 return PERM_REG;
233 #endif
234 }
235
236 /*
237 ** Return TRUE if the named file is an executable. Return false
238 ** for directories, devices, fifos, symlinks, etc.
239 */
240 int file_wd_isexe(const char *zFilename){
241 return file_wd_perm(zFilename)==PERM_EXE;
242 }
243
244 /*
245 ** Return TRUE if the named file is a symlink and symlinks are allowed.
246 ** Return false for all other cases.
247 **
248 ** On Windows, always return False.
249 */
250 int file_wd_islink(const char *zFilename){
251 return file_wd_perm(zFilename)==PERM_LNK;
252 }
253
254 /*
255 ** Return 1 if zFilename is a directory. Return 0 if zFilename
256 ** does not exist. Return 2 if zFilename exists but is something
@@ -219,25 +260,35 @@
260 int rc;
261
262 if( zFilename ){
263 char *zFN = mprintf("%s", zFilename);
264 file_simplify_name(zFN, -1);
265 rc = getStat(zFN, 0);
266 free(zFN);
267 }else{
268 rc = getStat(0, 0);
269 }
270 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
271 }
272
273 /*
274 ** Same as file_isdir(), but takes into account symlinks.
275 */
276 int file_wd_isdir(const char *zFilename){
277 int rc;
278
279 if( zFilename ){
280 char *zFN = mprintf("%s", zFilename);
281 file_simplify_name(zFN, -1);
282 rc = getStat(zFN, 1);
283 free(zFN);
284 }else{
285 rc = getStat(0, 1);
286 }
287 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
288 }
289
 
 
 
 
 
 
 
290
291 /*
292 ** Wrapper around the access() system call.
293 */
294 int file_access(const char *zFilename, int flags){
@@ -305,15 +356,15 @@
356
357 /*
358 ** Set or clear the execute bit on a file. Return true if a change
359 ** occurred and false if this routine is a no-op.
360 */
361 int file_wd_setexe(const char *zFilename, int onoff){
362 int rc = 0;
363 #if !defined(_WIN32)
364 struct stat buf;
365 if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0;
366 if( onoff ){
367 int targetMode = (buf.st_mode & 0444)>>2;
368 if( (buf.st_mode & 0111)!=targetMode ){
369 chmod(zFilename, buf.st_mode | targetMode);
370 rc = 1;
@@ -574,19 +625,19 @@
625 char zBuf[100];
626 const char *zName = g.argv[i];
627 file_canonical_name(zName, &x);
628 fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
629 blob_reset(&x);
630 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
631 fossil_print(" file_size = %s\n", zBuf);
632 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
633 fossil_print(" file_mtime = %s\n", zBuf);
634 fossil_print(" file_isfile = %d\n", file_wd_isfile(zName));
635 fossil_print(" file_isfile_or_link = %d\n",file_wd_isfile_or_link(zName));
636 fossil_print(" file_islink = %d\n", file_wd_islink(zName));
637 fossil_print(" file_isexe = %d\n", file_wd_isexe(zName));
638 fossil_print(" file_isdir = %d\n", file_wd_isdir(zName));
639 }
640 }
641
642 /*
643 ** Return TRUE if the given filename is canonical.
@@ -851,11 +902,11 @@
902 Blob onDisk;
903
904 iSize = file_size(zName);
905 if( iSize<0 ) return 0;
906 if( iSize!=blob_size(pContent) ) return 0;
907 if( file_wd_islink(zName) ){
908 blob_read_link(&onDisk, zName);
909 }else{
910 blob_read_from_file(&onDisk, zName);
911 }
912 rc = blob_compare(&onDisk, pContent);
913
+19 -7
--- src/finfo.c
+++ src/finfo.c
@@ -21,11 +21,11 @@
2121
#include "finfo.h"
2222
2323
/*
2424
** COMMAND: finfo
2525
**
26
-** Usage: %fossil finfo {?-l|--log? / -s|--status / --p|--print} FILENAME
26
+** Usage: %fossil finfo ?OPTIONS? FILENAME
2727
**
2828
** Print the complete change history for a single file going backwards
2929
** in time. The default is -l.
3030
**
3131
** For the -l|--log option: If "-b|--brief" is specified one line per revision
@@ -34,13 +34,25 @@
3434
** after skipping P changes.
3535
**
3636
** In the -s form prints the status as <status> <revision>. This is
3737
** a quick status and does not check for up-to-date-ness of the file.
3838
**
39
-** The -p form, there's an optional flag "-r|--revision REVISION". The
40
-** specified version (or the latest checked out version) is printed to
41
-** stdout.
39
+** In the -p form, there's an optional flag "-r|--revision REVISION".
40
+** The specified version (or the latest checked out version) is printed
41
+** to stdout.
42
+**
43
+** Options:
44
+** --brief|-b display a brief (one line / revision) summary
45
+** --limit N display the first N changes
46
+** --log|-l select log mode (the default)
47
+** --offset P skip P changes
48
+** -p select print mode
49
+** --revision|-r R print the given revision (or ckout, if none is given)
50
+** to stdout (only in print mode)
51
+** -s select status mode (print a status indicator for FILE)
52
+**
53
+** See also: descendants, info, leaves
4254
*/
4355
void finfo_cmd(void){
4456
db_must_be_within_tree();
4557
if (find_option("status","s",0)) {
4658
Stmt q;
@@ -210,11 +222,11 @@
210222
GraphContext *pGraph;
211223
int brBg = P("brbg")!=0;
212224
int uBg = P("ubg")!=0;
213225
214226
login_check_credentials();
215
- if( !g.okRead ){ login_needed(); return; }
227
+ if( !g.perm.Read ){ login_needed(); return; }
216228
style_header("File History");
217229
login_anonymous_available();
218230
219231
zPrevDate[0] = 0;
220232
zFilename = PD("name","");
@@ -297,11 +309,11 @@
297309
@ <td class="timelineTableCell">
298310
}
299311
sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
300312
sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
301313
if( zUuid ){
302
- if( g.okHistory ){
314
+ if( g.perm.History ){
303315
@ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a>
304316
}else{
305317
@ [%S(zUuid)]
306318
}
307319
@ part of check-in
@@ -310,11 +322,11 @@
310322
}
311323
hyperlink_to_uuid(zShortCkin);
312324
@ %h(zCom) (user:
313325
hyperlink_to_user(zUser, zDate, "");
314326
@ branch: %h(zBr))
315
- if( g.okHistory && zUuid ){
327
+ if( g.perm.History && zUuid ){
316328
const char *z = zFilename;
317329
if( fpid ){
318330
@ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
319331
}
320332
@ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
321333
--- src/finfo.c
+++ src/finfo.c
@@ -21,11 +21,11 @@
21 #include "finfo.h"
22
23 /*
24 ** COMMAND: finfo
25 **
26 ** Usage: %fossil finfo {?-l|--log? / -s|--status / --p|--print} FILENAME
27 **
28 ** Print the complete change history for a single file going backwards
29 ** in time. The default is -l.
30 **
31 ** For the -l|--log option: If "-b|--brief" is specified one line per revision
@@ -34,13 +34,25 @@
34 ** after skipping P changes.
35 **
36 ** In the -s form prints the status as <status> <revision>. This is
37 ** a quick status and does not check for up-to-date-ness of the file.
38 **
39 ** The -p form, there's an optional flag "-r|--revision REVISION". The
40 ** specified version (or the latest checked out version) is printed to
41 ** stdout.
 
 
 
 
 
 
 
 
 
 
 
 
42 */
43 void finfo_cmd(void){
44 db_must_be_within_tree();
45 if (find_option("status","s",0)) {
46 Stmt q;
@@ -210,11 +222,11 @@
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();
218
219 zPrevDate[0] = 0;
220 zFilename = PD("name","");
@@ -297,11 +309,11 @@
297 @ <td class="timelineTableCell">
298 }
299 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
300 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
301 if( zUuid ){
302 if( g.okHistory ){
303 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a>
304 }else{
305 @ [%S(zUuid)]
306 }
307 @ part of check-in
@@ -310,11 +322,11 @@
310 }
311 hyperlink_to_uuid(zShortCkin);
312 @ %h(zCom) (user:
313 hyperlink_to_user(zUser, zDate, "");
314 @ branch: %h(zBr))
315 if( g.okHistory && zUuid ){
316 const char *z = zFilename;
317 if( fpid ){
318 @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
319 }
320 @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
321
--- src/finfo.c
+++ src/finfo.c
@@ -21,11 +21,11 @@
21 #include "finfo.h"
22
23 /*
24 ** COMMAND: finfo
25 **
26 ** Usage: %fossil finfo ?OPTIONS? FILENAME
27 **
28 ** Print the complete change history for a single file going backwards
29 ** in time. The default is -l.
30 **
31 ** For the -l|--log option: If "-b|--brief" is specified one line per revision
@@ -34,13 +34,25 @@
34 ** after skipping P changes.
35 **
36 ** In the -s form prints the status as <status> <revision>. This is
37 ** a quick status and does not check for up-to-date-ness of the file.
38 **
39 ** In the -p form, there's an optional flag "-r|--revision REVISION".
40 ** The specified version (or the latest checked out version) is printed
41 ** to stdout.
42 **
43 ** Options:
44 ** --brief|-b display a brief (one line / revision) summary
45 ** --limit N display the first N changes
46 ** --log|-l select log mode (the default)
47 ** --offset P skip P changes
48 ** -p select print mode
49 ** --revision|-r R print the given revision (or ckout, if none is given)
50 ** to stdout (only in print mode)
51 ** -s select status mode (print a status indicator for FILE)
52 **
53 ** See also: descendants, info, leaves
54 */
55 void finfo_cmd(void){
56 db_must_be_within_tree();
57 if (find_option("status","s",0)) {
58 Stmt q;
@@ -210,11 +222,11 @@
222 GraphContext *pGraph;
223 int brBg = P("brbg")!=0;
224 int uBg = P("ubg")!=0;
225
226 login_check_credentials();
227 if( !g.perm.Read ){ login_needed(); return; }
228 style_header("File History");
229 login_anonymous_available();
230
231 zPrevDate[0] = 0;
232 zFilename = PD("name","");
@@ -297,11 +309,11 @@
309 @ <td class="timelineTableCell">
310 }
311 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
312 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
313 if( zUuid ){
314 if( g.perm.History ){
315 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a>
316 }else{
317 @ [%S(zUuid)]
318 }
319 @ part of check-in
@@ -310,11 +322,11 @@
322 }
323 hyperlink_to_uuid(zShortCkin);
324 @ %h(zCom) (user:
325 hyperlink_to_user(zUser, zDate, "");
326 @ branch: %h(zBr))
327 if( g.perm.History && zUuid ){
328 const char *z = zFilename;
329 if( fpid ){
330 @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
331 }
332 @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
333
+4 -2
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -104,10 +104,12 @@
104104
SSL_library_init();
105105
SSL_load_error_strings();
106106
ERR_load_BIO_strings();
107107
OpenSSL_add_all_algorithms();
108108
sslCtx = SSL_CTX_new(SSLv23_client_method());
109
+ /* Disable SSLv2 */
110
+ SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2);
109111
110112
/* Set up acceptable CA root certificates */
111113
zCaSetting = db_get("ssl-ca-location", 0);
112114
if( zCaSetting==0 || zCaSetting[0]=='\0' ){
113115
/* CA location not specified, use platform's default certificate store */
@@ -249,11 +251,11 @@
249251
int j;
250252
for( j = 0; j < mdLength; ++j ) {
251253
BIO_printf(mem, " %02x", md[j]);
252254
}
253255
}
254
- BIO_write(mem, "", 1); // null-terminate mem buffer
256
+ BIO_write(mem, "", 1); /* nul-terminate mem buffer */
255257
BIO_get_mem_data(mem, &desc);
256258
257259
if( hasSavedCertificate ){
258260
warning = "WARNING: Certificate doesn't match the "
259261
"saved certificate for this host!";
@@ -304,11 +306,11 @@
304306
BIO *mem;
305307
char *zCert, *zHost;
306308
307309
mem = BIO_new(BIO_s_mem());
308310
PEM_write_bio_X509(mem, cert);
309
- BIO_write(mem, "", 1); // null-terminate mem buffer
311
+ BIO_write(mem, "", 1); /* nul-terminate mem buffer */
310312
BIO_get_mem_data(mem, &zCert);
311313
zHost = mprintf("cert:%s", g.urlName);
312314
db_set(zHost, zCert, 1);
313315
free(zHost);
314316
BIO_free(mem);
315317
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -104,10 +104,12 @@
104 SSL_library_init();
105 SSL_load_error_strings();
106 ERR_load_BIO_strings();
107 OpenSSL_add_all_algorithms();
108 sslCtx = SSL_CTX_new(SSLv23_client_method());
 
 
109
110 /* Set up acceptable CA root certificates */
111 zCaSetting = db_get("ssl-ca-location", 0);
112 if( zCaSetting==0 || zCaSetting[0]=='\0' ){
113 /* CA location not specified, use platform's default certificate store */
@@ -249,11 +251,11 @@
249 int j;
250 for( j = 0; j < mdLength; ++j ) {
251 BIO_printf(mem, " %02x", md[j]);
252 }
253 }
254 BIO_write(mem, "", 1); // null-terminate mem buffer
255 BIO_get_mem_data(mem, &desc);
256
257 if( hasSavedCertificate ){
258 warning = "WARNING: Certificate doesn't match the "
259 "saved certificate for this host!";
@@ -304,11 +306,11 @@
304 BIO *mem;
305 char *zCert, *zHost;
306
307 mem = BIO_new(BIO_s_mem());
308 PEM_write_bio_X509(mem, cert);
309 BIO_write(mem, "", 1); // null-terminate mem buffer
310 BIO_get_mem_data(mem, &zCert);
311 zHost = mprintf("cert:%s", g.urlName);
312 db_set(zHost, zCert, 1);
313 free(zHost);
314 BIO_free(mem);
315
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -104,10 +104,12 @@
104 SSL_library_init();
105 SSL_load_error_strings();
106 ERR_load_BIO_strings();
107 OpenSSL_add_all_algorithms();
108 sslCtx = SSL_CTX_new(SSLv23_client_method());
109 /* Disable SSLv2 */
110 SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2);
111
112 /* Set up acceptable CA root certificates */
113 zCaSetting = db_get("ssl-ca-location", 0);
114 if( zCaSetting==0 || zCaSetting[0]=='\0' ){
115 /* CA location not specified, use platform's default certificate store */
@@ -249,11 +251,11 @@
251 int j;
252 for( j = 0; j < mdLength; ++j ) {
253 BIO_printf(mem, " %02x", md[j]);
254 }
255 }
256 BIO_write(mem, "", 1); /* nul-terminate mem buffer */
257 BIO_get_mem_data(mem, &desc);
258
259 if( hasSavedCertificate ){
260 warning = "WARNING: Certificate doesn't match the "
261 "saved certificate for this host!";
@@ -304,11 +306,11 @@
306 BIO *mem;
307 char *zCert, *zHost;
308
309 mem = BIO_new(BIO_s_mem());
310 PEM_write_bio_X509(mem, cert);
311 BIO_write(mem, "", 1); /* nul-terminate mem buffer */
312 BIO_get_mem_data(mem, &zCert);
313 zHost = mprintf("cert:%s", g.urlName);
314 db_set(zHost, zCert, 1);
315 free(zHost);
316 BIO_free(mem);
317
+6 -1
--- src/import.c
+++ src/import.c
@@ -701,11 +701,11 @@
701701
}
702702
703703
/*
704704
** COMMAND: import
705705
**
706
-** Usage: %fossil import --git NEW-REPOSITORY
706
+** Usage: %fossil import --git ?OPTIONS? NEW-REPOSITORY
707707
**
708708
** Read text generated by the git-fast-export command and use it to
709709
** construct a new Fossil repository named by the NEW-REPOSITORY
710710
** argument. The git-fast-export text is read from standard input.
711711
**
@@ -713,10 +713,15 @@
713713
** format that is understood, though other interchange formats may be added
714714
** in the future.
715715
**
716716
** The --incremental option allows an existing repository to be extended
717717
** with new content.
718
+**
719
+** Options:
720
+** --incremental allow importing into an existing repository
721
+**
722
+** See also: export
718723
*/
719724
void git_import_cmd(void){
720725
char *zPassword;
721726
FILE *pIn;
722727
Stmt q;
723728
--- src/import.c
+++ src/import.c
@@ -701,11 +701,11 @@
701 }
702
703 /*
704 ** COMMAND: import
705 **
706 ** Usage: %fossil import --git NEW-REPOSITORY
707 **
708 ** Read text generated by the git-fast-export command and use it to
709 ** construct a new Fossil repository named by the NEW-REPOSITORY
710 ** argument. The git-fast-export text is read from standard input.
711 **
@@ -713,10 +713,15 @@
713 ** format that is understood, though other interchange formats may be added
714 ** in the future.
715 **
716 ** The --incremental option allows an existing repository to be extended
717 ** with new content.
 
 
 
 
 
718 */
719 void git_import_cmd(void){
720 char *zPassword;
721 FILE *pIn;
722 Stmt q;
723
--- src/import.c
+++ src/import.c
@@ -701,11 +701,11 @@
701 }
702
703 /*
704 ** COMMAND: import
705 **
706 ** Usage: %fossil import --git ?OPTIONS? NEW-REPOSITORY
707 **
708 ** Read text generated by the git-fast-export command and use it to
709 ** construct a new Fossil repository named by the NEW-REPOSITORY
710 ** argument. The git-fast-export text is read from standard input.
711 **
@@ -713,10 +713,15 @@
713 ** format that is understood, though other interchange formats may be added
714 ** in the future.
715 **
716 ** The --incremental option allows an existing repository to be extended
717 ** with new content.
718 **
719 ** Options:
720 ** --incremental allow importing into an existing repository
721 **
722 ** See also: export
723 */
724 void git_import_cmd(void){
725 char *zPassword;
726 FILE *pIn;
727 Stmt q;
728
+50 -45
--- src/info.c
+++ src/info.c
@@ -80,31 +80,35 @@
8080
" FROM event WHERE objid=%d",
8181
rid
8282
);
8383
}
8484
if( showFamily ){
85
- db_prepare(&q, "SELECT uuid, pid FROM plink JOIN blob ON pid=rid "
86
- " WHERE cid=%d", rid);
85
+ db_prepare(&q, "SELECT uuid, pid, isprim FROM plink JOIN blob ON pid=rid "
86
+ " WHERE cid=%d"
87
+ " ORDER BY isprim DESC, mtime DESC /*sort*/", rid);
8788
while( db_step(&q)==SQLITE_ROW ){
8889
const char *zUuid = db_column_text(&q, 0);
90
+ const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:";
8991
zDate = db_text("",
9092
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
9193
db_column_int(&q, 1)
9294
);
93
- fossil_print("parent: %s %s\n", zUuid, zDate);
95
+ fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
9496
free(zDate);
9597
}
9698
db_finalize(&q);
97
- db_prepare(&q, "SELECT uuid, cid FROM plink JOIN blob ON cid=rid "
98
- " WHERE pid=%d", rid);
99
+ db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid "
100
+ " WHERE pid=%d"
101
+ " ORDER BY isprim DESC, mtime DESC /*sort*/", rid);
99102
while( db_step(&q)==SQLITE_ROW ){
100103
const char *zUuid = db_column_text(&q, 0);
104
+ const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:";
101105
zDate = db_text("",
102106
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
103107
db_column_int(&q, 1)
104108
);
105
- fossil_print("child: %s %s\n", zUuid, zDate);
109
+ fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
106110
free(zDate);
107111
}
108112
db_finalize(&q);
109113
}
110114
zTags = info_tags_of_checkin(rid, 0);
@@ -121,54 +125,55 @@
121125
122126
123127
/*
124128
** COMMAND: info
125129
**
126
-** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME?
130
+** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME? ?OPTIONS?
127131
**
128132
** With no arguments, provide information about the current tree.
129133
** If an argument is specified, provide information about the object
130134
** in the respository of the current tree that the argument refers
131135
** to. Or if the argument is the name of a repository, show
132136
** information about that repository.
133137
**
134138
** Use the "finfo" command to get information about a specific
135139
** file in a checkout.
140
+**
141
+** Options:
142
+**
143
+** -R|--repository FILE Extract info from repository FILE
136144
*/
137145
void info_cmd(void){
138146
i64 fsize;
139
- if( g.argc!=2 && g.argc!=3 ){
140
- usage("?FILENAME|ARTIFACT-ID?");
141
- }
142147
if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
143148
db_open_config(0);
144149
db_record_repository_filename(g.argv[2]);
145150
db_open_repository(g.argv[2]);
146151
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
147152
fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
148153
fossil_print("server-code: %s\n", db_get("server-code", "<none>"));
149154
return;
150155
}
151
- db_must_be_within_tree();
156
+ db_find_and_open_repository(0,0);
152157
if( g.argc==2 ){
153158
int vid;
154159
/* 012345678901234 */
155160
db_record_repository_filename(0);
156161
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
157
- fossil_print("repository: %s\n", db_lget("repository", ""));
158
- fossil_print("local-root: %s\n", g.zLocalRoot);
162
+ if( g.localOpen ){
163
+ fossil_print("repository: %s\n", db_lget("repository", ""));
164
+ fossil_print("local-root: %s\n", g.zLocalRoot);
165
+ }
159166
#if defined(_WIN32)
160167
if( g.zHome ){
161168
fossil_print("user-home: %s\n", g.zHome);
162169
}
163170
#endif
164171
fossil_print("project-code: %s\n", db_get("project-code", ""));
165172
fossil_print("server-code: %s\n", db_get("server-code", ""));
166
- vid = db_lget_int("checkout", 0);
167
- if( vid==0 ){
168
- fossil_print("checkout: nil\n");
169
- }else{
173
+ vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
174
+ if( vid ){
170175
show_common_info(vid, "checkout:", 1, 1);
171176
}
172177
}else{
173178
int rid;
174179
rid = name_to_rid(g.argv[2]);
@@ -284,11 +289,11 @@
284289
const char *zNew, /* blob.uuid after change. NULL for deletes */
285290
const char *zOldName, /* Prior name. NULL if no name change. */
286291
int showDiff, /* Show edit diffs if true */
287292
int mperm /* executable or symlink permission for zNew */
288293
){
289
- if( !g.okHistory ){
294
+ if( !g.perm.History ){
290295
if( zNew==0 ){
291296
@ <p>Deleted %h(zName)</p>
292297
}else if( zOld==0 ){
293298
@ <p>Added %h(zName)</p>
294299
}else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
@@ -361,11 +366,11 @@
361366
const char *zName; /* Name of the checkin to be displayed */
362367
const char *zUuid; /* UUID of zName */
363368
const char *zParent; /* UUID of the parent checkin (if any) */
364369
365370
login_check_credentials();
366
- if( !g.okRead ){ login_needed(); return; }
371
+ if( !g.perm.Read ){ login_needed(); return; }
367372
zName = P("name");
368373
rid = name_to_rid_www("name");
369374
if( rid==0 ){
370375
style_header("Check-in Information Error");
371376
@ No such object: %h(g.argv[2])
@@ -409,11 +414,11 @@
409414
zDate = db_column_text(&q,1);
410415
zOrigDate = db_column_text(&q, 4);
411416
@ <div class="section">Overview</div>
412417
@ <table class="label-value">
413418
@ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
414
- if( g.okSetup ){
419
+ if( g.perm.Setup ){
415420
@ (Record ID: %d(rid))
416421
}
417422
@ </td></tr>
418423
@ <tr><th>Date:</th><td>
419424
hyperlink_to_date(zDate, "</td></tr>");
@@ -434,11 +439,11 @@
434439
@ <tr><th>Edited&nbsp;Comment:</th><td>%w(zEComment)</td></tr>
435440
@ <tr><th>Original&nbsp;Comment:</th><td>%w(zComment)</td></tr>
436441
}else{
437442
@ <tr><th>Comment:</th><td>%w(zComment)</td></tr>
438443
}
439
- if( g.okAdmin ){
444
+ if( g.perm.Admin ){
440445
db_prepare(&q,
441446
"SELECT rcvfrom.ipaddr, user.login, datetime(rcvfrom.mtime)"
442447
" FROM blob JOIN rcvfrom USING(rcvid) LEFT JOIN user USING(uid)"
443448
" WHERE blob.rid=%d",
444449
rid
@@ -451,11 +456,11 @@
451456
@ <tr><th>Received&nbsp;From:</th>
452457
@ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
453458
}
454459
db_finalize(&q);
455460
}
456
- if( g.okHistory ){
461
+ if( g.perm.History ){
457462
const char *zProjName = db_get("project-name", "unnamed");
458463
@ <tr><th>Timelines:</th><td>
459464
@ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a>
460465
if( zParent ){
461466
@ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a>
@@ -477,20 +482,20 @@
477482
db_finalize(&q);
478483
@ </td></tr>
479484
@ <tr><th>Other&nbsp;Links:</th>
480485
@ <td>
481486
@ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a>
482
- if( g.okZip ){
487
+ if( g.perm.Zip ){
483488
char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s",
484489
g.zTop, zProjName, zUuid, zUuid);
485490
@ | <a href="%s(zUrl)">Tarball</a>
486491
@ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)">
487492
@ ZIP archive</a>
488493
fossil_free(zUrl);
489494
}
490495
@ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a>
491
- if( g.okWrite ){
496
+ if( g.perm.Write ){
492497
@ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
493498
}
494499
@ </td>
495500
@ </tr>
496501
}
@@ -553,11 +558,11 @@
553558
void winfo_page(void){
554559
Stmt q;
555560
int rid;
556561
557562
login_check_credentials();
558
- if( !g.okRdWiki ){ login_needed(); return; }
563
+ if( !g.perm.RdWiki ){ login_needed(); return; }
559564
rid = name_to_rid_www("name");
560565
if( rid==0 ){
561566
style_header("Wiki Page Information Error");
562567
@ No such object: %h(g.argv[2])
563568
style_footer();
@@ -586,16 +591,16 @@
586591
@ <div class="section">Overview</div>
587592
@ <p><table class="label-value">
588593
@ <tr><th>Version:</th><td>%s(zUuid)</td></tr>
589594
@ <tr><th>Date:</th><td>
590595
hyperlink_to_date(zDate, "</td></tr>");
591
- if( g.okSetup ){
596
+ if( g.perm.Setup ){
592597
@ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
593598
}
594599
@ <tr><th>Original&nbsp;User:</th><td>
595600
hyperlink_to_user(zUser, zDate, "</td></tr>");
596
- if( g.okHistory ){
601
+ if( g.perm.History ){
597602
@ <tr><th>Commands:</th>
598603
@ <td>
599604
@ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a>
600605
@ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a>
601606
@ </td>
@@ -696,11 +701,11 @@
696701
int showDetail = 0;
697702
Manifest *pFrom, *pTo;
698703
ManifestFile *pFileFrom, *pFileTo;
699704
700705
login_check_credentials();
701
- if( !g.okRead ){ login_needed(); return; }
706
+ if( !g.perm.Read ){ login_needed(); return; }
702707
login_anonymous_available();
703708
704709
pFrom = vdiff_parse_manifest("from", &ridFrom);
705710
if( pFrom==0 ) return;
706711
pTo = vdiff_parse_manifest("to", &ridTo);
@@ -815,11 +820,11 @@
815820
}else if( mPerm==PERM_EXE ){
816821
@ <li>Executable file
817822
}else{
818823
@ <li>File
819824
}
820
- if( g.okHistory ){
825
+ if( g.perm.History ){
821826
@ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
822827
}else{
823828
@ %h(zName)
824829
}
825830
@ <ul>
@@ -828,20 +833,20 @@
828833
@ <li>
829834
hyperlink_to_date(zDate,"");
830835
@ - part of checkin
831836
hyperlink_to_uuid(zVers);
832837
if( zBr && zBr[0] ){
833
- if( g.okHistory ){
838
+ if( g.perm.History ){
834839
@ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a>
835840
}else{
836841
@ on branch %h(zBr)
837842
}
838843
}
839844
@ - %w(zCom) (user:
840845
hyperlink_to_user(zUser,zDate,"");
841846
@ )
842
- if( g.okHistory ){
847
+ if( g.perm.History ){
843848
@ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">
844849
@ [annotate]</a>
845850
}
846851
cnt++;
847852
if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -868,11 +873,11 @@
868873
if( cnt>0 ){
869874
@ Also wiki page
870875
}else{
871876
@ Wiki page
872877
}
873
- if( g.okHistory ){
878
+ if( g.perm.History ){
874879
@ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
875880
}else{
876881
@ [%h(zPagename)]
877882
}
878883
@ by
@@ -944,17 +949,17 @@
944949
@ Also attachment "%h(zFilename)" to
945950
}else{
946951
@ Attachment "%h(zFilename)" to
947952
}
948953
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
949
- if( g.okHistory && g.okRdTkt ){
954
+ if( g.perm.History && g.perm.RdTkt ){
950955
@ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>]
951956
}else{
952957
@ ticket [%S(zTarget)]
953958
}
954959
}else{
955
- if( g.okHistory && g.okRdWiki ){
960
+ if( g.perm.History && g.perm.RdWiki ){
956961
@ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>]
957962
}else{
958963
@ wiki page [%h(zTarget)]
959964
}
960965
}
@@ -970,11 +975,11 @@
970975
if( cnt==0 ){
971976
@ Control artifact.
972977
if( pDownloadName && blob_size(pDownloadName)==0 ){
973978
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
974979
}
975
- }else if( linkToView && g.okHistory ){
980
+ }else if( linkToView && g.perm.History ){
976981
@ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a>
977982
}
978983
}
979984
980985
@@ -992,11 +997,11 @@
992997
Blob c1, c2, diff, *pOut;
993998
char *zV1;
994999
char *zV2;
9951000
9961001
login_check_credentials();
997
- if( !g.okRead ){ login_needed(); return; }
1002
+ if( !g.perm.Read ){ login_needed(); return; }
9981003
v1 = name_to_rid_www("v1");
9991004
v2 = name_to_rid_www("v2");
10001005
if( v1==0 || v2==0 ) fossil_redirect_home();
10011006
zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
10021007
zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
@@ -1044,11 +1049,11 @@
10441049
Blob content;
10451050
10461051
rid = name_to_rid_www("name");
10471052
zMime = PD("m","application/x-fossil-artifact");
10481053
login_check_credentials();
1049
- if( !g.okRead ){ login_needed(); return; }
1054
+ if( !g.perm.Read ){ login_needed(); return; }
10501055
if( rid==0 ) fossil_redirect_home();
10511056
content_get(rid, &content);
10521057
cgi_set_content_type(zMime);
10531058
cgi_set_content(&content);
10541059
}
@@ -1117,13 +1122,13 @@
11171122
Blob downloadName;
11181123
char *zUuid;
11191124
11201125
rid = name_to_rid_www("name");
11211126
login_check_credentials();
1122
- if( !g.okRead ){ login_needed(); return; }
1127
+ if( !g.perm.Read ){ login_needed(); return; }
11231128
if( rid==0 ) fossil_redirect_home();
1124
- if( g.okAdmin ){
1129
+ if( g.perm.Admin ){
11251130
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
11261131
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
11271132
style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
11281133
g.zTop, zUuid);
11291134
}else{
@@ -1264,13 +1269,13 @@
12641269
if( rid==0 ){
12651270
rid = name_to_rid_www("name");
12661271
}
12671272
12681273
login_check_credentials();
1269
- if( !g.okRead ){ login_needed(); return; }
1274
+ if( !g.perm.Read ){ login_needed(); return; }
12701275
if( rid==0 ) fossil_redirect_home();
1271
- if( g.okAdmin ){
1276
+ if( g.perm.Admin ){
12721277
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
12731278
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
12741279
style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
12751280
g.zTop, zUuid);
12761281
}else{
@@ -1351,15 +1356,15 @@
13511356
const char *zUuid;
13521357
char zTktName[20];
13531358
Manifest *pTktChng;
13541359
13551360
login_check_credentials();
1356
- if( !g.okRdTkt ){ login_needed(); return; }
1361
+ if( !g.perm.RdTkt ){ login_needed(); return; }
13571362
rid = name_to_rid_www("name");
13581363
if( rid==0 ){ fossil_redirect_home(); }
13591364
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1360
- if( g.okAdmin ){
1365
+ if( g.perm.Admin ){
13611366
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
13621367
style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
13631368
g.zTop, zUuid);
13641369
}else{
13651370
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
@@ -1372,11 +1377,11 @@
13721377
}
13731378
style_header("Ticket Change Details");
13741379
zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
13751380
memcpy(zTktName, pTktChng->zTicketUuid, 10);
13761381
zTktName[10] = 0;
1377
- if( g.okHistory ){
1382
+ if( g.perm.History ){
13781383
@ <h2>Changes to ticket
13791384
@ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2>
13801385
@
13811386
@ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
13821387
@ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and
@@ -1612,11 +1617,11 @@
16121617
char *zUuid;
16131618
Blob comment;
16141619
Stmt q;
16151620
16161621
login_check_credentials();
1617
- if( !g.okWrite ){ login_needed(); return; }
1622
+ if( !g.perm.Write ){ login_needed(); return; }
16181623
rid = name_to_typed_rid(P("r"), "ci");
16191624
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
16201625
zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
16211626
" FROM event WHERE objid=%d", rid);
16221627
if( zComment==0 ) fossil_redirect_home();
16231628
--- src/info.c
+++ src/info.c
@@ -80,31 +80,35 @@
80 " FROM event WHERE objid=%d",
81 rid
82 );
83 }
84 if( showFamily ){
85 db_prepare(&q, "SELECT uuid, pid FROM plink JOIN blob ON pid=rid "
86 " WHERE cid=%d", rid);
 
87 while( db_step(&q)==SQLITE_ROW ){
88 const char *zUuid = db_column_text(&q, 0);
 
89 zDate = db_text("",
90 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
91 db_column_int(&q, 1)
92 );
93 fossil_print("parent: %s %s\n", zUuid, zDate);
94 free(zDate);
95 }
96 db_finalize(&q);
97 db_prepare(&q, "SELECT uuid, cid FROM plink JOIN blob ON cid=rid "
98 " WHERE pid=%d", rid);
 
99 while( db_step(&q)==SQLITE_ROW ){
100 const char *zUuid = db_column_text(&q, 0);
 
101 zDate = db_text("",
102 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
103 db_column_int(&q, 1)
104 );
105 fossil_print("child: %s %s\n", zUuid, zDate);
106 free(zDate);
107 }
108 db_finalize(&q);
109 }
110 zTags = info_tags_of_checkin(rid, 0);
@@ -121,54 +125,55 @@
121
122
123 /*
124 ** COMMAND: info
125 **
126 ** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME?
127 **
128 ** With no arguments, provide information about the current tree.
129 ** If an argument is specified, provide information about the object
130 ** in the respository of the current tree that the argument refers
131 ** to. Or if the argument is the name of a repository, show
132 ** information about that repository.
133 **
134 ** Use the "finfo" command to get information about a specific
135 ** file in a checkout.
 
 
 
 
136 */
137 void info_cmd(void){
138 i64 fsize;
139 if( g.argc!=2 && g.argc!=3 ){
140 usage("?FILENAME|ARTIFACT-ID?");
141 }
142 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
143 db_open_config(0);
144 db_record_repository_filename(g.argv[2]);
145 db_open_repository(g.argv[2]);
146 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
147 fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
148 fossil_print("server-code: %s\n", db_get("server-code", "<none>"));
149 return;
150 }
151 db_must_be_within_tree();
152 if( g.argc==2 ){
153 int vid;
154 /* 012345678901234 */
155 db_record_repository_filename(0);
156 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
157 fossil_print("repository: %s\n", db_lget("repository", ""));
158 fossil_print("local-root: %s\n", g.zLocalRoot);
 
 
159 #if defined(_WIN32)
160 if( g.zHome ){
161 fossil_print("user-home: %s\n", g.zHome);
162 }
163 #endif
164 fossil_print("project-code: %s\n", db_get("project-code", ""));
165 fossil_print("server-code: %s\n", db_get("server-code", ""));
166 vid = db_lget_int("checkout", 0);
167 if( vid==0 ){
168 fossil_print("checkout: nil\n");
169 }else{
170 show_common_info(vid, "checkout:", 1, 1);
171 }
172 }else{
173 int rid;
174 rid = name_to_rid(g.argv[2]);
@@ -284,11 +289,11 @@
284 const char *zNew, /* blob.uuid after change. NULL for deletes */
285 const char *zOldName, /* Prior name. NULL if no name change. */
286 int showDiff, /* Show edit diffs if true */
287 int mperm /* executable or symlink permission for zNew */
288 ){
289 if( !g.okHistory ){
290 if( zNew==0 ){
291 @ <p>Deleted %h(zName)</p>
292 }else if( zOld==0 ){
293 @ <p>Added %h(zName)</p>
294 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
@@ -361,11 +366,11 @@
361 const char *zName; /* Name of the checkin to be displayed */
362 const char *zUuid; /* UUID of zName */
363 const char *zParent; /* UUID of the parent checkin (if any) */
364
365 login_check_credentials();
366 if( !g.okRead ){ login_needed(); return; }
367 zName = P("name");
368 rid = name_to_rid_www("name");
369 if( rid==0 ){
370 style_header("Check-in Information Error");
371 @ No such object: %h(g.argv[2])
@@ -409,11 +414,11 @@
409 zDate = db_column_text(&q,1);
410 zOrigDate = db_column_text(&q, 4);
411 @ <div class="section">Overview</div>
412 @ <table class="label-value">
413 @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
414 if( g.okSetup ){
415 @ (Record ID: %d(rid))
416 }
417 @ </td></tr>
418 @ <tr><th>Date:</th><td>
419 hyperlink_to_date(zDate, "</td></tr>");
@@ -434,11 +439,11 @@
434 @ <tr><th>Edited&nbsp;Comment:</th><td>%w(zEComment)</td></tr>
435 @ <tr><th>Original&nbsp;Comment:</th><td>%w(zComment)</td></tr>
436 }else{
437 @ <tr><th>Comment:</th><td>%w(zComment)</td></tr>
438 }
439 if( g.okAdmin ){
440 db_prepare(&q,
441 "SELECT rcvfrom.ipaddr, user.login, datetime(rcvfrom.mtime)"
442 " FROM blob JOIN rcvfrom USING(rcvid) LEFT JOIN user USING(uid)"
443 " WHERE blob.rid=%d",
444 rid
@@ -451,11 +456,11 @@
451 @ <tr><th>Received&nbsp;From:</th>
452 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
453 }
454 db_finalize(&q);
455 }
456 if( g.okHistory ){
457 const char *zProjName = db_get("project-name", "unnamed");
458 @ <tr><th>Timelines:</th><td>
459 @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a>
460 if( zParent ){
461 @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a>
@@ -477,20 +482,20 @@
477 db_finalize(&q);
478 @ </td></tr>
479 @ <tr><th>Other&nbsp;Links:</th>
480 @ <td>
481 @ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a>
482 if( g.okZip ){
483 char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s",
484 g.zTop, zProjName, zUuid, zUuid);
485 @ | <a href="%s(zUrl)">Tarball</a>
486 @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)">
487 @ ZIP archive</a>
488 fossil_free(zUrl);
489 }
490 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a>
491 if( g.okWrite ){
492 @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
493 }
494 @ </td>
495 @ </tr>
496 }
@@ -553,11 +558,11 @@
553 void winfo_page(void){
554 Stmt q;
555 int rid;
556
557 login_check_credentials();
558 if( !g.okRdWiki ){ login_needed(); return; }
559 rid = name_to_rid_www("name");
560 if( rid==0 ){
561 style_header("Wiki Page Information Error");
562 @ No such object: %h(g.argv[2])
563 style_footer();
@@ -586,16 +591,16 @@
586 @ <div class="section">Overview</div>
587 @ <p><table class="label-value">
588 @ <tr><th>Version:</th><td>%s(zUuid)</td></tr>
589 @ <tr><th>Date:</th><td>
590 hyperlink_to_date(zDate, "</td></tr>");
591 if( g.okSetup ){
592 @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
593 }
594 @ <tr><th>Original&nbsp;User:</th><td>
595 hyperlink_to_user(zUser, zDate, "</td></tr>");
596 if( g.okHistory ){
597 @ <tr><th>Commands:</th>
598 @ <td>
599 @ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a>
600 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a>
601 @ </td>
@@ -696,11 +701,11 @@
696 int showDetail = 0;
697 Manifest *pFrom, *pTo;
698 ManifestFile *pFileFrom, *pFileTo;
699
700 login_check_credentials();
701 if( !g.okRead ){ login_needed(); return; }
702 login_anonymous_available();
703
704 pFrom = vdiff_parse_manifest("from", &ridFrom);
705 if( pFrom==0 ) return;
706 pTo = vdiff_parse_manifest("to", &ridTo);
@@ -815,11 +820,11 @@
815 }else if( mPerm==PERM_EXE ){
816 @ <li>Executable file
817 }else{
818 @ <li>File
819 }
820 if( g.okHistory ){
821 @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
822 }else{
823 @ %h(zName)
824 }
825 @ <ul>
@@ -828,20 +833,20 @@
828 @ <li>
829 hyperlink_to_date(zDate,"");
830 @ - part of checkin
831 hyperlink_to_uuid(zVers);
832 if( zBr && zBr[0] ){
833 if( g.okHistory ){
834 @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a>
835 }else{
836 @ on branch %h(zBr)
837 }
838 }
839 @ - %w(zCom) (user:
840 hyperlink_to_user(zUser,zDate,"");
841 @ )
842 if( g.okHistory ){
843 @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">
844 @ [annotate]</a>
845 }
846 cnt++;
847 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -868,11 +873,11 @@
868 if( cnt>0 ){
869 @ Also wiki page
870 }else{
871 @ Wiki page
872 }
873 if( g.okHistory ){
874 @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
875 }else{
876 @ [%h(zPagename)]
877 }
878 @ by
@@ -944,17 +949,17 @@
944 @ Also attachment "%h(zFilename)" to
945 }else{
946 @ Attachment "%h(zFilename)" to
947 }
948 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
949 if( g.okHistory && g.okRdTkt ){
950 @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>]
951 }else{
952 @ ticket [%S(zTarget)]
953 }
954 }else{
955 if( g.okHistory && g.okRdWiki ){
956 @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>]
957 }else{
958 @ wiki page [%h(zTarget)]
959 }
960 }
@@ -970,11 +975,11 @@
970 if( cnt==0 ){
971 @ Control artifact.
972 if( pDownloadName && blob_size(pDownloadName)==0 ){
973 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
974 }
975 }else if( linkToView && g.okHistory ){
976 @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a>
977 }
978 }
979
980
@@ -992,11 +997,11 @@
992 Blob c1, c2, diff, *pOut;
993 char *zV1;
994 char *zV2;
995
996 login_check_credentials();
997 if( !g.okRead ){ login_needed(); return; }
998 v1 = name_to_rid_www("v1");
999 v2 = name_to_rid_www("v2");
1000 if( v1==0 || v2==0 ) fossil_redirect_home();
1001 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
1002 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
@@ -1044,11 +1049,11 @@
1044 Blob content;
1045
1046 rid = name_to_rid_www("name");
1047 zMime = PD("m","application/x-fossil-artifact");
1048 login_check_credentials();
1049 if( !g.okRead ){ login_needed(); return; }
1050 if( rid==0 ) fossil_redirect_home();
1051 content_get(rid, &content);
1052 cgi_set_content_type(zMime);
1053 cgi_set_content(&content);
1054 }
@@ -1117,13 +1122,13 @@
1117 Blob downloadName;
1118 char *zUuid;
1119
1120 rid = name_to_rid_www("name");
1121 login_check_credentials();
1122 if( !g.okRead ){ login_needed(); return; }
1123 if( rid==0 ) fossil_redirect_home();
1124 if( g.okAdmin ){
1125 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1126 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1127 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1128 g.zTop, zUuid);
1129 }else{
@@ -1264,13 +1269,13 @@
1264 if( rid==0 ){
1265 rid = name_to_rid_www("name");
1266 }
1267
1268 login_check_credentials();
1269 if( !g.okRead ){ login_needed(); return; }
1270 if( rid==0 ) fossil_redirect_home();
1271 if( g.okAdmin ){
1272 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1273 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1274 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1275 g.zTop, zUuid);
1276 }else{
@@ -1351,15 +1356,15 @@
1351 const char *zUuid;
1352 char zTktName[20];
1353 Manifest *pTktChng;
1354
1355 login_check_credentials();
1356 if( !g.okRdTkt ){ login_needed(); return; }
1357 rid = name_to_rid_www("name");
1358 if( rid==0 ){ fossil_redirect_home(); }
1359 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1360 if( g.okAdmin ){
1361 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1362 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1363 g.zTop, zUuid);
1364 }else{
1365 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
@@ -1372,11 +1377,11 @@
1372 }
1373 style_header("Ticket Change Details");
1374 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
1375 memcpy(zTktName, pTktChng->zTicketUuid, 10);
1376 zTktName[10] = 0;
1377 if( g.okHistory ){
1378 @ <h2>Changes to ticket
1379 @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2>
1380 @
1381 @ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
1382 @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and
@@ -1612,11 +1617,11 @@
1612 char *zUuid;
1613 Blob comment;
1614 Stmt q;
1615
1616 login_check_credentials();
1617 if( !g.okWrite ){ login_needed(); return; }
1618 rid = name_to_typed_rid(P("r"), "ci");
1619 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1620 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
1621 " FROM event WHERE objid=%d", rid);
1622 if( zComment==0 ) fossil_redirect_home();
1623
--- src/info.c
+++ src/info.c
@@ -80,31 +80,35 @@
80 " FROM event WHERE objid=%d",
81 rid
82 );
83 }
84 if( showFamily ){
85 db_prepare(&q, "SELECT uuid, pid, isprim FROM plink JOIN blob ON pid=rid "
86 " WHERE cid=%d"
87 " ORDER BY isprim DESC, mtime DESC /*sort*/", rid);
88 while( db_step(&q)==SQLITE_ROW ){
89 const char *zUuid = db_column_text(&q, 0);
90 const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:";
91 zDate = db_text("",
92 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
93 db_column_int(&q, 1)
94 );
95 fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
96 free(zDate);
97 }
98 db_finalize(&q);
99 db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid "
100 " WHERE pid=%d"
101 " ORDER BY isprim DESC, mtime DESC /*sort*/", rid);
102 while( db_step(&q)==SQLITE_ROW ){
103 const char *zUuid = db_column_text(&q, 0);
104 const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:";
105 zDate = db_text("",
106 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
107 db_column_int(&q, 1)
108 );
109 fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
110 free(zDate);
111 }
112 db_finalize(&q);
113 }
114 zTags = info_tags_of_checkin(rid, 0);
@@ -121,54 +125,55 @@
125
126
127 /*
128 ** COMMAND: info
129 **
130 ** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME? ?OPTIONS?
131 **
132 ** With no arguments, provide information about the current tree.
133 ** If an argument is specified, provide information about the object
134 ** in the respository of the current tree that the argument refers
135 ** to. Or if the argument is the name of a repository, show
136 ** information about that repository.
137 **
138 ** Use the "finfo" command to get information about a specific
139 ** file in a checkout.
140 **
141 ** Options:
142 **
143 ** -R|--repository FILE Extract info from repository FILE
144 */
145 void info_cmd(void){
146 i64 fsize;
 
 
 
147 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
148 db_open_config(0);
149 db_record_repository_filename(g.argv[2]);
150 db_open_repository(g.argv[2]);
151 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
152 fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
153 fossil_print("server-code: %s\n", db_get("server-code", "<none>"));
154 return;
155 }
156 db_find_and_open_repository(0,0);
157 if( g.argc==2 ){
158 int vid;
159 /* 012345678901234 */
160 db_record_repository_filename(0);
161 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
162 if( g.localOpen ){
163 fossil_print("repository: %s\n", db_lget("repository", ""));
164 fossil_print("local-root: %s\n", g.zLocalRoot);
165 }
166 #if defined(_WIN32)
167 if( g.zHome ){
168 fossil_print("user-home: %s\n", g.zHome);
169 }
170 #endif
171 fossil_print("project-code: %s\n", db_get("project-code", ""));
172 fossil_print("server-code: %s\n", db_get("server-code", ""));
173 vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
174 if( vid ){
 
 
175 show_common_info(vid, "checkout:", 1, 1);
176 }
177 }else{
178 int rid;
179 rid = name_to_rid(g.argv[2]);
@@ -284,11 +289,11 @@
289 const char *zNew, /* blob.uuid after change. NULL for deletes */
290 const char *zOldName, /* Prior name. NULL if no name change. */
291 int showDiff, /* Show edit diffs if true */
292 int mperm /* executable or symlink permission for zNew */
293 ){
294 if( !g.perm.History ){
295 if( zNew==0 ){
296 @ <p>Deleted %h(zName)</p>
297 }else if( zOld==0 ){
298 @ <p>Added %h(zName)</p>
299 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
@@ -361,11 +366,11 @@
366 const char *zName; /* Name of the checkin to be displayed */
367 const char *zUuid; /* UUID of zName */
368 const char *zParent; /* UUID of the parent checkin (if any) */
369
370 login_check_credentials();
371 if( !g.perm.Read ){ login_needed(); return; }
372 zName = P("name");
373 rid = name_to_rid_www("name");
374 if( rid==0 ){
375 style_header("Check-in Information Error");
376 @ No such object: %h(g.argv[2])
@@ -409,11 +414,11 @@
414 zDate = db_column_text(&q,1);
415 zOrigDate = db_column_text(&q, 4);
416 @ <div class="section">Overview</div>
417 @ <table class="label-value">
418 @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
419 if( g.perm.Setup ){
420 @ (Record ID: %d(rid))
421 }
422 @ </td></tr>
423 @ <tr><th>Date:</th><td>
424 hyperlink_to_date(zDate, "</td></tr>");
@@ -434,11 +439,11 @@
439 @ <tr><th>Edited&nbsp;Comment:</th><td>%w(zEComment)</td></tr>
440 @ <tr><th>Original&nbsp;Comment:</th><td>%w(zComment)</td></tr>
441 }else{
442 @ <tr><th>Comment:</th><td>%w(zComment)</td></tr>
443 }
444 if( g.perm.Admin ){
445 db_prepare(&q,
446 "SELECT rcvfrom.ipaddr, user.login, datetime(rcvfrom.mtime)"
447 " FROM blob JOIN rcvfrom USING(rcvid) LEFT JOIN user USING(uid)"
448 " WHERE blob.rid=%d",
449 rid
@@ -451,11 +456,11 @@
456 @ <tr><th>Received&nbsp;From:</th>
457 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
458 }
459 db_finalize(&q);
460 }
461 if( g.perm.History ){
462 const char *zProjName = db_get("project-name", "unnamed");
463 @ <tr><th>Timelines:</th><td>
464 @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a>
465 if( zParent ){
466 @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a>
@@ -477,20 +482,20 @@
482 db_finalize(&q);
483 @ </td></tr>
484 @ <tr><th>Other&nbsp;Links:</th>
485 @ <td>
486 @ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a>
487 if( g.perm.Zip ){
488 char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s",
489 g.zTop, zProjName, zUuid, zUuid);
490 @ | <a href="%s(zUrl)">Tarball</a>
491 @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)">
492 @ ZIP archive</a>
493 fossil_free(zUrl);
494 }
495 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a>
496 if( g.perm.Write ){
497 @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
498 }
499 @ </td>
500 @ </tr>
501 }
@@ -553,11 +558,11 @@
558 void winfo_page(void){
559 Stmt q;
560 int rid;
561
562 login_check_credentials();
563 if( !g.perm.RdWiki ){ login_needed(); return; }
564 rid = name_to_rid_www("name");
565 if( rid==0 ){
566 style_header("Wiki Page Information Error");
567 @ No such object: %h(g.argv[2])
568 style_footer();
@@ -586,16 +591,16 @@
591 @ <div class="section">Overview</div>
592 @ <p><table class="label-value">
593 @ <tr><th>Version:</th><td>%s(zUuid)</td></tr>
594 @ <tr><th>Date:</th><td>
595 hyperlink_to_date(zDate, "</td></tr>");
596 if( g.perm.Setup ){
597 @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
598 }
599 @ <tr><th>Original&nbsp;User:</th><td>
600 hyperlink_to_user(zUser, zDate, "</td></tr>");
601 if( g.perm.History ){
602 @ <tr><th>Commands:</th>
603 @ <td>
604 @ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a>
605 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a>
606 @ </td>
@@ -696,11 +701,11 @@
701 int showDetail = 0;
702 Manifest *pFrom, *pTo;
703 ManifestFile *pFileFrom, *pFileTo;
704
705 login_check_credentials();
706 if( !g.perm.Read ){ login_needed(); return; }
707 login_anonymous_available();
708
709 pFrom = vdiff_parse_manifest("from", &ridFrom);
710 if( pFrom==0 ) return;
711 pTo = vdiff_parse_manifest("to", &ridTo);
@@ -815,11 +820,11 @@
820 }else if( mPerm==PERM_EXE ){
821 @ <li>Executable file
822 }else{
823 @ <li>File
824 }
825 if( g.perm.History ){
826 @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
827 }else{
828 @ %h(zName)
829 }
830 @ <ul>
@@ -828,20 +833,20 @@
833 @ <li>
834 hyperlink_to_date(zDate,"");
835 @ - part of checkin
836 hyperlink_to_uuid(zVers);
837 if( zBr && zBr[0] ){
838 if( g.perm.History ){
839 @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a>
840 }else{
841 @ on branch %h(zBr)
842 }
843 }
844 @ - %w(zCom) (user:
845 hyperlink_to_user(zUser,zDate,"");
846 @ )
847 if( g.perm.History ){
848 @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">
849 @ [annotate]</a>
850 }
851 cnt++;
852 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -868,11 +873,11 @@
873 if( cnt>0 ){
874 @ Also wiki page
875 }else{
876 @ Wiki page
877 }
878 if( g.perm.History ){
879 @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
880 }else{
881 @ [%h(zPagename)]
882 }
883 @ by
@@ -944,17 +949,17 @@
949 @ Also attachment "%h(zFilename)" to
950 }else{
951 @ Attachment "%h(zFilename)" to
952 }
953 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
954 if( g.perm.History && g.perm.RdTkt ){
955 @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>]
956 }else{
957 @ ticket [%S(zTarget)]
958 }
959 }else{
960 if( g.perm.History && g.perm.RdWiki ){
961 @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>]
962 }else{
963 @ wiki page [%h(zTarget)]
964 }
965 }
@@ -970,11 +975,11 @@
975 if( cnt==0 ){
976 @ Control artifact.
977 if( pDownloadName && blob_size(pDownloadName)==0 ){
978 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
979 }
980 }else if( linkToView && g.perm.History ){
981 @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a>
982 }
983 }
984
985
@@ -992,11 +997,11 @@
997 Blob c1, c2, diff, *pOut;
998 char *zV1;
999 char *zV2;
1000
1001 login_check_credentials();
1002 if( !g.perm.Read ){ login_needed(); return; }
1003 v1 = name_to_rid_www("v1");
1004 v2 = name_to_rid_www("v2");
1005 if( v1==0 || v2==0 ) fossil_redirect_home();
1006 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
1007 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
@@ -1044,11 +1049,11 @@
1049 Blob content;
1050
1051 rid = name_to_rid_www("name");
1052 zMime = PD("m","application/x-fossil-artifact");
1053 login_check_credentials();
1054 if( !g.perm.Read ){ login_needed(); return; }
1055 if( rid==0 ) fossil_redirect_home();
1056 content_get(rid, &content);
1057 cgi_set_content_type(zMime);
1058 cgi_set_content(&content);
1059 }
@@ -1117,13 +1122,13 @@
1122 Blob downloadName;
1123 char *zUuid;
1124
1125 rid = name_to_rid_www("name");
1126 login_check_credentials();
1127 if( !g.perm.Read ){ login_needed(); return; }
1128 if( rid==0 ) fossil_redirect_home();
1129 if( g.perm.Admin ){
1130 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1131 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1132 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1133 g.zTop, zUuid);
1134 }else{
@@ -1264,13 +1269,13 @@
1269 if( rid==0 ){
1270 rid = name_to_rid_www("name");
1271 }
1272
1273 login_check_credentials();
1274 if( !g.perm.Read ){ login_needed(); return; }
1275 if( rid==0 ) fossil_redirect_home();
1276 if( g.perm.Admin ){
1277 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1278 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1279 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1280 g.zTop, zUuid);
1281 }else{
@@ -1351,15 +1356,15 @@
1356 const char *zUuid;
1357 char zTktName[20];
1358 Manifest *pTktChng;
1359
1360 login_check_credentials();
1361 if( !g.perm.RdTkt ){ login_needed(); return; }
1362 rid = name_to_rid_www("name");
1363 if( rid==0 ){ fossil_redirect_home(); }
1364 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1365 if( g.perm.Admin ){
1366 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1367 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1368 g.zTop, zUuid);
1369 }else{
1370 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
@@ -1372,11 +1377,11 @@
1377 }
1378 style_header("Ticket Change Details");
1379 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
1380 memcpy(zTktName, pTktChng->zTicketUuid, 10);
1381 zTktName[10] = 0;
1382 if( g.perm.History ){
1383 @ <h2>Changes to ticket
1384 @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2>
1385 @
1386 @ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
1387 @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and
@@ -1612,11 +1617,11 @@
1617 char *zUuid;
1618 Blob comment;
1619 Stmt q;
1620
1621 login_check_credentials();
1622 if( !g.perm.Write ){ login_needed(); return; }
1623 rid = name_to_typed_rid(P("r"), "ci");
1624 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1625 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
1626 " FROM event WHERE objid=%d", rid);
1627 if( zComment==0 ) fossil_redirect_home();
1628
+55 -76
--- src/login.c
+++ src/login.c
@@ -226,11 +226,11 @@
226226
/* To logout, change the cookie value to an empty string */
227227
const char *zCookieName = login_cookie_name();
228228
cgi_set_cookie(zCookieName, "", login_cookie_path(), -86400);
229229
redirect_to_g();
230230
}
231
- if( g.okPassword && zPasswd && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0 ){
231
+ if( g.perm.Password && zPasswd && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0 ){
232232
/* The user requests a password change */
233233
zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
234234
if( db_int(1, "SELECT 0 FROM user"
235235
" WHERE uid=%d AND (pw=%Q OR pw=%Q)",
236236
g.userUid, zPasswd, zSha1Pw) ){
@@ -431,11 +431,11 @@
431431
@ <p>To log off the system (and delete your login cookie)
432432
@ press the following button:<br />
433433
@ <input type="submit" name="out" value="Logout" /></p>
434434
}
435435
@ </form>
436
- if( g.okPassword ){
436
+ if( g.perm.Password ){
437437
@ <hr />
438438
@ <p>To change your password, enter your old password and your
439439
@ new password twice below then press the "Change Password"
440440
@ button.</p>
441441
@ <form action="login" method="post">
@@ -541,11 +541,11 @@
541541
542542
/*
543543
** This routine examines the login cookie to see if it exists and
544544
** and is valid. If the login cookie checks out, it then sets
545545
** global variables appropriately. Global variables set include
546
-** g.userUid and g.zLogin and of the g.okRead family of permission
546
+** g.userUid and g.zLogin and of the g.perm.Read family of permission
547547
** booleans.
548548
**
549549
*/
550550
void login_check_credentials(void){
551551
int uid = 0; /* User id */
@@ -725,40 +725,40 @@
725725
*/
726726
void login_set_capabilities(const char *zCap, unsigned flags){
727727
int i;
728728
for(i=0; zCap[i]; i++){
729729
switch( zCap[i] ){
730
- case 's': g.okSetup = 1; /* Fall thru into Admin */
731
- case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okZip =
732
- g.okRdWiki = g.okWrWiki = g.okNewWiki =
733
- g.okApndWiki = g.okHistory = g.okClone =
734
- g.okNewTkt = g.okPassword = g.okRdAddr =
735
- g.okTktFmt = g.okAttach = g.okApndTkt = 1;
730
+ case 's': g.perm.Setup = 1; /* Fall thru into Admin */
731
+ case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
732
+ g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
733
+ g.perm.ApndWiki = g.perm.History = g.perm.Clone =
734
+ g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
735
+ g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
736736
/* Fall thru into Read/Write */
737
- case 'i': g.okRead = g.okWrite = 1; break;
738
- case 'o': g.okRead = 1; break;
739
- case 'z': g.okZip = 1; break;
740
-
741
- case 'd': g.okDelete = 1; break;
742
- case 'h': g.okHistory = 1; break;
743
- case 'g': g.okClone = 1; break;
744
- case 'p': g.okPassword = 1; break;
745
-
746
- case 'j': g.okRdWiki = 1; break;
747
- case 'k': g.okWrWiki = g.okRdWiki = g.okApndWiki =1; break;
748
- case 'm': g.okApndWiki = 1; break;
749
- case 'f': g.okNewWiki = 1; break;
750
-
751
- case 'e': g.okRdAddr = 1; break;
752
- case 'r': g.okRdTkt = 1; break;
753
- case 'n': g.okNewTkt = 1; break;
754
- case 'w': g.okWrTkt = g.okRdTkt = g.okNewTkt =
755
- g.okApndTkt = 1; break;
756
- case 'c': g.okApndTkt = 1; break;
757
- case 't': g.okTktFmt = 1; break;
758
- case 'b': g.okAttach = 1; break;
759
- case 'x': g.okPrivate = 1; break;
737
+ case 'i': g.perm.Read = g.perm.Write = 1; break;
738
+ case 'o': g.perm.Read = 1; break;
739
+ case 'z': g.perm.Zip = 1; break;
740
+
741
+ case 'd': g.perm.Delete = 1; break;
742
+ case 'h': g.perm.History = 1; break;
743
+ case 'g': g.perm.Clone = 1; break;
744
+ case 'p': g.perm.Password = 1; break;
745
+
746
+ case 'j': g.perm.RdWiki = 1; break;
747
+ case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
748
+ case 'm': g.perm.ApndWiki = 1; break;
749
+ case 'f': g.perm.NewWiki = 1; break;
750
+
751
+ case 'e': g.perm.RdAddr = 1; break;
752
+ case 'r': g.perm.RdTkt = 1; break;
753
+ case 'n': g.perm.NewTkt = 1; break;
754
+ case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
755
+ g.perm.ApndTkt = 1; break;
756
+ case 'c': g.perm.ApndTkt = 1; break;
757
+ case 't': g.perm.TktFmt = 1; break;
758
+ case 'b': g.perm.Attach = 1; break;
759
+ case 'x': g.perm.Private = 1; break;
760760
761761
/* The "u" privileges is a little different. It recursively
762762
** inherits all privileges of the user named "reader" */
763763
case 'u': {
764764
if( (flags & LOGIN_IGNORE_U)==0 ){
@@ -792,36 +792,36 @@
792792
int i;
793793
int rc = 1;
794794
if( nCap<0 ) nCap = strlen(zCap);
795795
for(i=0; i<nCap && rc && zCap[i]; i++){
796796
switch( zCap[i] ){
797
- case 'a': rc = g.okAdmin; break;
798
- case 'b': rc = g.okAttach; break;
799
- case 'c': rc = g.okApndTkt; break;
800
- case 'd': rc = g.okDelete; break;
801
- case 'e': rc = g.okRdAddr; break;
802
- case 'f': rc = g.okNewWiki; break;
803
- case 'g': rc = g.okClone; break;
804
- case 'h': rc = g.okHistory; break;
805
- case 'i': rc = g.okWrite; break;
806
- case 'j': rc = g.okRdWiki; break;
807
- case 'k': rc = g.okWrWiki; break;
797
+ case 'a': rc = g.perm.Admin; break;
798
+ case 'b': rc = g.perm.Attach; break;
799
+ case 'c': rc = g.perm.ApndTkt; break;
800
+ case 'd': rc = g.perm.Delete; break;
801
+ case 'e': rc = g.perm.RdAddr; break;
802
+ case 'f': rc = g.perm.NewWiki; break;
803
+ case 'g': rc = g.perm.Clone; break;
804
+ case 'h': rc = g.perm.History; break;
805
+ case 'i': rc = g.perm.Write; break;
806
+ case 'j': rc = g.perm.RdWiki; break;
807
+ case 'k': rc = g.perm.WrWiki; break;
808808
/* case 'l': */
809
- case 'm': rc = g.okApndWiki; break;
810
- case 'n': rc = g.okNewTkt; break;
811
- case 'o': rc = g.okRead; break;
812
- case 'p': rc = g.okPassword; break;
809
+ case 'm': rc = g.perm.ApndWiki; break;
810
+ case 'n': rc = g.perm.NewTkt; break;
811
+ case 'o': rc = g.perm.Read; break;
812
+ case 'p': rc = g.perm.Password; break;
813813
/* case 'q': */
814
- case 'r': rc = g.okRdTkt; break;
815
- case 's': rc = g.okSetup; break;
816
- case 't': rc = g.okTktFmt; break;
814
+ case 'r': rc = g.perm.RdTkt; break;
815
+ case 's': rc = g.perm.Setup; break;
816
+ case 't': rc = g.perm.TktFmt; break;
817817
/* case 'u': READER */
818818
/* case 'v': DEVELOPER */
819
- case 'w': rc = g.okWrTkt; break;
820
- case 'x': rc = g.okPrivate; break;
819
+ case 'w': rc = g.perm.WrTkt; break;
820
+ case 'x': rc = g.perm.Private; break;
821821
/* case 'y': */
822
- case 'z': rc = g.okZip; break;
822
+ case 'z': rc = g.perm.Zip; break;
823823
default: rc = 0; break;
824824
}
825825
}
826826
return rc;
827827
}
@@ -831,32 +831,11 @@
831831
*/
832832
void login_as_user(const char *zUser){
833833
char *zCap = ""; /* New capabilities */
834834
835835
/* Turn off all capabilities from prior logins */
836
- g.okSetup = 0;
837
- g.okAdmin = 0;
838
- g.okDelete = 0;
839
- g.okPassword = 0;
840
- g.okQuery = 0;
841
- g.okWrite = 0;
842
- g.okRead = 0;
843
- g.okHistory = 0;
844
- g.okClone = 0;
845
- g.okRdWiki = 0;
846
- g.okNewWiki = 0;
847
- g.okApndWiki = 0;
848
- g.okWrWiki = 0;
849
- g.okRdTkt = 0;
850
- g.okNewTkt = 0;
851
- g.okApndTkt = 0;
852
- g.okWrTkt = 0;
853
- g.okAttach = 0;
854
- g.okTktFmt = 0;
855
- g.okRdAddr = 0;
856
- g.okZip = 0;
857
- g.okPrivate = 0;
836
+ memset( &g.perm, 0, sizeof(g.perm) );
858837
859838
/* Set the global variables recording the userid and login. The
860839
** "nobody" user is a special case in that g.zLogin==0.
861840
*/
862841
g.userUid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUser);
@@ -892,11 +871,11 @@
892871
** the anonymous user has okHistory permission, then paint a mesage
893872
** to inform the user that much more information is available by
894873
** logging in as anonymous.
895874
*/
896875
void login_anonymous_available(void){
897
- if( !g.okHistory &&
876
+ if( !g.perm.History &&
898877
db_exists("SELECT 1 FROM user"
899878
" WHERE login='anonymous'"
900879
" AND cap LIKE '%%h%%'") ){
901880
const char *zUrl = PD("REQUEST_URI", "index");
902881
@ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
903882
--- src/login.c
+++ src/login.c
@@ -226,11 +226,11 @@
226 /* To logout, change the cookie value to an empty string */
227 const char *zCookieName = login_cookie_name();
228 cgi_set_cookie(zCookieName, "", login_cookie_path(), -86400);
229 redirect_to_g();
230 }
231 if( g.okPassword && zPasswd && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0 ){
232 /* The user requests a password change */
233 zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
234 if( db_int(1, "SELECT 0 FROM user"
235 " WHERE uid=%d AND (pw=%Q OR pw=%Q)",
236 g.userUid, zPasswd, zSha1Pw) ){
@@ -431,11 +431,11 @@
431 @ <p>To log off the system (and delete your login cookie)
432 @ press the following button:<br />
433 @ <input type="submit" name="out" value="Logout" /></p>
434 }
435 @ </form>
436 if( g.okPassword ){
437 @ <hr />
438 @ <p>To change your password, enter your old password and your
439 @ new password twice below then press the "Change Password"
440 @ button.</p>
441 @ <form action="login" method="post">
@@ -541,11 +541,11 @@
541
542 /*
543 ** This routine examines the login cookie to see if it exists and
544 ** and is valid. If the login cookie checks out, it then sets
545 ** global variables appropriately. Global variables set include
546 ** g.userUid and g.zLogin and of the g.okRead family of permission
547 ** booleans.
548 **
549 */
550 void login_check_credentials(void){
551 int uid = 0; /* User id */
@@ -725,40 +725,40 @@
725 */
726 void login_set_capabilities(const char *zCap, unsigned flags){
727 int i;
728 for(i=0; zCap[i]; i++){
729 switch( zCap[i] ){
730 case 's': g.okSetup = 1; /* Fall thru into Admin */
731 case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okZip =
732 g.okRdWiki = g.okWrWiki = g.okNewWiki =
733 g.okApndWiki = g.okHistory = g.okClone =
734 g.okNewTkt = g.okPassword = g.okRdAddr =
735 g.okTktFmt = g.okAttach = g.okApndTkt = 1;
736 /* Fall thru into Read/Write */
737 case 'i': g.okRead = g.okWrite = 1; break;
738 case 'o': g.okRead = 1; break;
739 case 'z': g.okZip = 1; break;
740
741 case 'd': g.okDelete = 1; break;
742 case 'h': g.okHistory = 1; break;
743 case 'g': g.okClone = 1; break;
744 case 'p': g.okPassword = 1; break;
745
746 case 'j': g.okRdWiki = 1; break;
747 case 'k': g.okWrWiki = g.okRdWiki = g.okApndWiki =1; break;
748 case 'm': g.okApndWiki = 1; break;
749 case 'f': g.okNewWiki = 1; break;
750
751 case 'e': g.okRdAddr = 1; break;
752 case 'r': g.okRdTkt = 1; break;
753 case 'n': g.okNewTkt = 1; break;
754 case 'w': g.okWrTkt = g.okRdTkt = g.okNewTkt =
755 g.okApndTkt = 1; break;
756 case 'c': g.okApndTkt = 1; break;
757 case 't': g.okTktFmt = 1; break;
758 case 'b': g.okAttach = 1; break;
759 case 'x': g.okPrivate = 1; break;
760
761 /* The "u" privileges is a little different. It recursively
762 ** inherits all privileges of the user named "reader" */
763 case 'u': {
764 if( (flags & LOGIN_IGNORE_U)==0 ){
@@ -792,36 +792,36 @@
792 int i;
793 int rc = 1;
794 if( nCap<0 ) nCap = strlen(zCap);
795 for(i=0; i<nCap && rc && zCap[i]; i++){
796 switch( zCap[i] ){
797 case 'a': rc = g.okAdmin; break;
798 case 'b': rc = g.okAttach; break;
799 case 'c': rc = g.okApndTkt; break;
800 case 'd': rc = g.okDelete; break;
801 case 'e': rc = g.okRdAddr; break;
802 case 'f': rc = g.okNewWiki; break;
803 case 'g': rc = g.okClone; break;
804 case 'h': rc = g.okHistory; break;
805 case 'i': rc = g.okWrite; break;
806 case 'j': rc = g.okRdWiki; break;
807 case 'k': rc = g.okWrWiki; break;
808 /* case 'l': */
809 case 'm': rc = g.okApndWiki; break;
810 case 'n': rc = g.okNewTkt; break;
811 case 'o': rc = g.okRead; break;
812 case 'p': rc = g.okPassword; break;
813 /* case 'q': */
814 case 'r': rc = g.okRdTkt; break;
815 case 's': rc = g.okSetup; break;
816 case 't': rc = g.okTktFmt; break;
817 /* case 'u': READER */
818 /* case 'v': DEVELOPER */
819 case 'w': rc = g.okWrTkt; break;
820 case 'x': rc = g.okPrivate; break;
821 /* case 'y': */
822 case 'z': rc = g.okZip; break;
823 default: rc = 0; break;
824 }
825 }
826 return rc;
827 }
@@ -831,32 +831,11 @@
831 */
832 void login_as_user(const char *zUser){
833 char *zCap = ""; /* New capabilities */
834
835 /* Turn off all capabilities from prior logins */
836 g.okSetup = 0;
837 g.okAdmin = 0;
838 g.okDelete = 0;
839 g.okPassword = 0;
840 g.okQuery = 0;
841 g.okWrite = 0;
842 g.okRead = 0;
843 g.okHistory = 0;
844 g.okClone = 0;
845 g.okRdWiki = 0;
846 g.okNewWiki = 0;
847 g.okApndWiki = 0;
848 g.okWrWiki = 0;
849 g.okRdTkt = 0;
850 g.okNewTkt = 0;
851 g.okApndTkt = 0;
852 g.okWrTkt = 0;
853 g.okAttach = 0;
854 g.okTktFmt = 0;
855 g.okRdAddr = 0;
856 g.okZip = 0;
857 g.okPrivate = 0;
858
859 /* Set the global variables recording the userid and login. The
860 ** "nobody" user is a special case in that g.zLogin==0.
861 */
862 g.userUid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUser);
@@ -892,11 +871,11 @@
892 ** the anonymous user has okHistory permission, then paint a mesage
893 ** to inform the user that much more information is available by
894 ** logging in as anonymous.
895 */
896 void login_anonymous_available(void){
897 if( !g.okHistory &&
898 db_exists("SELECT 1 FROM user"
899 " WHERE login='anonymous'"
900 " AND cap LIKE '%%h%%'") ){
901 const char *zUrl = PD("REQUEST_URI", "index");
902 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
903
--- src/login.c
+++ src/login.c
@@ -226,11 +226,11 @@
226 /* To logout, change the cookie value to an empty string */
227 const char *zCookieName = login_cookie_name();
228 cgi_set_cookie(zCookieName, "", login_cookie_path(), -86400);
229 redirect_to_g();
230 }
231 if( g.perm.Password && zPasswd && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0 ){
232 /* The user requests a password change */
233 zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
234 if( db_int(1, "SELECT 0 FROM user"
235 " WHERE uid=%d AND (pw=%Q OR pw=%Q)",
236 g.userUid, zPasswd, zSha1Pw) ){
@@ -431,11 +431,11 @@
431 @ <p>To log off the system (and delete your login cookie)
432 @ press the following button:<br />
433 @ <input type="submit" name="out" value="Logout" /></p>
434 }
435 @ </form>
436 if( g.perm.Password ){
437 @ <hr />
438 @ <p>To change your password, enter your old password and your
439 @ new password twice below then press the "Change Password"
440 @ button.</p>
441 @ <form action="login" method="post">
@@ -541,11 +541,11 @@
541
542 /*
543 ** This routine examines the login cookie to see if it exists and
544 ** and is valid. If the login cookie checks out, it then sets
545 ** global variables appropriately. Global variables set include
546 ** g.userUid and g.zLogin and of the g.perm.Read family of permission
547 ** booleans.
548 **
549 */
550 void login_check_credentials(void){
551 int uid = 0; /* User id */
@@ -725,40 +725,40 @@
725 */
726 void login_set_capabilities(const char *zCap, unsigned flags){
727 int i;
728 for(i=0; zCap[i]; i++){
729 switch( zCap[i] ){
730 case 's': g.perm.Setup = 1; /* Fall thru into Admin */
731 case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
732 g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
733 g.perm.ApndWiki = g.perm.History = g.perm.Clone =
734 g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
735 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
736 /* Fall thru into Read/Write */
737 case 'i': g.perm.Read = g.perm.Write = 1; break;
738 case 'o': g.perm.Read = 1; break;
739 case 'z': g.perm.Zip = 1; break;
740
741 case 'd': g.perm.Delete = 1; break;
742 case 'h': g.perm.History = 1; break;
743 case 'g': g.perm.Clone = 1; break;
744 case 'p': g.perm.Password = 1; break;
745
746 case 'j': g.perm.RdWiki = 1; break;
747 case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
748 case 'm': g.perm.ApndWiki = 1; break;
749 case 'f': g.perm.NewWiki = 1; break;
750
751 case 'e': g.perm.RdAddr = 1; break;
752 case 'r': g.perm.RdTkt = 1; break;
753 case 'n': g.perm.NewTkt = 1; break;
754 case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
755 g.perm.ApndTkt = 1; break;
756 case 'c': g.perm.ApndTkt = 1; break;
757 case 't': g.perm.TktFmt = 1; break;
758 case 'b': g.perm.Attach = 1; break;
759 case 'x': g.perm.Private = 1; break;
760
761 /* The "u" privileges is a little different. It recursively
762 ** inherits all privileges of the user named "reader" */
763 case 'u': {
764 if( (flags & LOGIN_IGNORE_U)==0 ){
@@ -792,36 +792,36 @@
792 int i;
793 int rc = 1;
794 if( nCap<0 ) nCap = strlen(zCap);
795 for(i=0; i<nCap && rc && zCap[i]; i++){
796 switch( zCap[i] ){
797 case 'a': rc = g.perm.Admin; break;
798 case 'b': rc = g.perm.Attach; break;
799 case 'c': rc = g.perm.ApndTkt; break;
800 case 'd': rc = g.perm.Delete; break;
801 case 'e': rc = g.perm.RdAddr; break;
802 case 'f': rc = g.perm.NewWiki; break;
803 case 'g': rc = g.perm.Clone; break;
804 case 'h': rc = g.perm.History; break;
805 case 'i': rc = g.perm.Write; break;
806 case 'j': rc = g.perm.RdWiki; break;
807 case 'k': rc = g.perm.WrWiki; break;
808 /* case 'l': */
809 case 'm': rc = g.perm.ApndWiki; break;
810 case 'n': rc = g.perm.NewTkt; break;
811 case 'o': rc = g.perm.Read; break;
812 case 'p': rc = g.perm.Password; break;
813 /* case 'q': */
814 case 'r': rc = g.perm.RdTkt; break;
815 case 's': rc = g.perm.Setup; break;
816 case 't': rc = g.perm.TktFmt; break;
817 /* case 'u': READER */
818 /* case 'v': DEVELOPER */
819 case 'w': rc = g.perm.WrTkt; break;
820 case 'x': rc = g.perm.Private; break;
821 /* case 'y': */
822 case 'z': rc = g.perm.Zip; break;
823 default: rc = 0; break;
824 }
825 }
826 return rc;
827 }
@@ -831,32 +831,11 @@
831 */
832 void login_as_user(const char *zUser){
833 char *zCap = ""; /* New capabilities */
834
835 /* Turn off all capabilities from prior logins */
836 memset( &g.perm, 0, sizeof(g.perm) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
837
838 /* Set the global variables recording the userid and login. The
839 ** "nobody" user is a special case in that g.zLogin==0.
840 */
841 g.userUid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUser);
@@ -892,11 +871,11 @@
871 ** the anonymous user has okHistory permission, then paint a mesage
872 ** to inform the user that much more information is available by
873 ** logging in as anonymous.
874 */
875 void login_anonymous_available(void){
876 if( !g.perm.History &&
877 db_exists("SELECT 1 FROM user"
878 " WHERE login='anonymous'"
879 " AND cap LIKE '%%h%%'") ){
880 const char *zUrl = PD("REQUEST_URI", "index");
881 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
882
+45 -23
--- src/main.c
+++ src/main.c
@@ -45,10 +45,38 @@
4545
/*
4646
** Maximum number of auxiliary parameters on reports
4747
*/
4848
#define MX_AUX 5
4949
50
+/*
51
+** Holds flags for fossil user permissions.
52
+*/
53
+struct FossilUserPerms {
54
+ char Setup; /* s: use Setup screens on web interface */
55
+ char Admin; /* a: administrative permission */
56
+ char Delete; /* d: delete wiki or tickets */
57
+ char Password; /* p: change password */
58
+ char Query; /* q: create new reports */
59
+ char Write; /* i: xfer inbound. checkin */
60
+ char Read; /* o: xfer outbound. checkout */
61
+ char History; /* h: access historical information. */
62
+ char Clone; /* g: clone */
63
+ char RdWiki; /* j: view wiki via web */
64
+ char NewWiki; /* f: create new wiki via web */
65
+ char ApndWiki; /* m: append to wiki via web */
66
+ char WrWiki; /* k: edit wiki via web */
67
+ char RdTkt; /* r: view tickets via web */
68
+ char NewTkt; /* n: create new tickets */
69
+ char ApndTkt; /* c: append to tickets via the web */
70
+ char WrTkt; /* w: make changes to tickets via web */
71
+ char Attach; /* b: add attachments */
72
+ char TktFmt; /* t: create new ticket report formats */
73
+ char RdAddr; /* e: read email addresses or other private data */
74
+ char Zip; /* z: download zipped artifact via /zip URL */
75
+ char Private; /* x: can send and receive private content */
76
+};
77
+
5078
/*
5179
** All global variables are in this structure.
5280
*/
5381
struct Global {
5482
int argc; char **argv; /* Command-line arguments to the program */
@@ -119,32 +147,11 @@
119147
int rcvid; /* The rcvid. 0 if not yet defined. */
120148
char *zIpAddr; /* The remote IP address */
121149
char *zNonce; /* The nonce used for login */
122150
123151
/* permissions used by the server */
124
- int okSetup; /* s: use Setup screens on web interface */
125
- int okAdmin; /* a: administrative permission */
126
- int okDelete; /* d: delete wiki or tickets */
127
- int okPassword; /* p: change password */
128
- int okQuery; /* q: create new reports */
129
- int okWrite; /* i: xfer inbound. checkin */
130
- int okRead; /* o: xfer outbound. checkout */
131
- int okHistory; /* h: access historical information. */
132
- int okClone; /* g: clone */
133
- int okRdWiki; /* j: view wiki via web */
134
- int okNewWiki; /* f: create new wiki via web */
135
- int okApndWiki; /* m: append to wiki via web */
136
- int okWrWiki; /* k: edit wiki via web */
137
- int okRdTkt; /* r: view tickets via web */
138
- int okNewTkt; /* n: create new tickets */
139
- int okApndTkt; /* c: append to tickets via the web */
140
- int okWrTkt; /* w: make changes to tickets via web */
141
- int okAttach; /* b: add attachments */
142
- int okTktFmt; /* t: create new ticket report formats */
143
- int okRdAddr; /* e: read email addresses or other private data */
144
- int okZip; /* z: download zipped artifact via /zip URL */
145
- int okPrivate; /* x: can send and receive private content */
152
+ struct FossilUserPerms perm;
146153
147154
/* For defense against Cross-site Request Forgery attacks */
148155
char zCsrfToken[12]; /* Value of the anti-CSRF token */
149156
int okCsrf; /* Anti-CSRF token is present and valid */
150157
@@ -646,10 +653,25 @@
646653
aCmd[nCmd++] = aCommand[i].zName;
647654
}
648655
multi_column_list(aCmd, nCmd);
649656
}
650657
658
+
659
+/*
660
+** COMMAND: test-list-webpage
661
+**
662
+** List all web pages
663
+*/
664
+void cmd_test_webpage_list(void){
665
+ int i, nCmd;
666
+ const char *aCmd[count(aWebpage)];
667
+ for(i=nCmd=0; i<count(aWebpage); i++){
668
+ aCmd[nCmd++] = aWebpage[i].zName;
669
+ }
670
+ multi_column_list(aCmd, nCmd);
671
+}
672
+
651673
652674
/*
653675
** COMMAND: version
654676
**
655677
** Usage: %fossil version
@@ -1015,11 +1037,11 @@
10151037
file_simplify_name(zAltRepo, -1);
10161038
}
10171039
db_close(1);
10181040
db_open_repository(zAltRepo);
10191041
login_as_user(zUser);
1020
- g.okPassword = 0;
1042
+ g.perm.Password = 0;
10211043
zPath += i;
10221044
nHost = g.zTop - g.zBaseURL;
10231045
g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
10241046
g.zTop = g.zBaseURL + nHost;
10251047
continue;
10261048
--- src/main.c
+++ src/main.c
@@ -45,10 +45,38 @@
45 /*
46 ** Maximum number of auxiliary parameters on reports
47 */
48 #define MX_AUX 5
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50 /*
51 ** All global variables are in this structure.
52 */
53 struct Global {
54 int argc; char **argv; /* Command-line arguments to the program */
@@ -119,32 +147,11 @@
119 int rcvid; /* The rcvid. 0 if not yet defined. */
120 char *zIpAddr; /* The remote IP address */
121 char *zNonce; /* The nonce used for login */
122
123 /* permissions used by the server */
124 int okSetup; /* s: use Setup screens on web interface */
125 int okAdmin; /* a: administrative permission */
126 int okDelete; /* d: delete wiki or tickets */
127 int okPassword; /* p: change password */
128 int okQuery; /* q: create new reports */
129 int okWrite; /* i: xfer inbound. checkin */
130 int okRead; /* o: xfer outbound. checkout */
131 int okHistory; /* h: access historical information. */
132 int okClone; /* g: clone */
133 int okRdWiki; /* j: view wiki via web */
134 int okNewWiki; /* f: create new wiki via web */
135 int okApndWiki; /* m: append to wiki via web */
136 int okWrWiki; /* k: edit wiki via web */
137 int okRdTkt; /* r: view tickets via web */
138 int okNewTkt; /* n: create new tickets */
139 int okApndTkt; /* c: append to tickets via the web */
140 int okWrTkt; /* w: make changes to tickets via web */
141 int okAttach; /* b: add attachments */
142 int okTktFmt; /* t: create new ticket report formats */
143 int okRdAddr; /* e: read email addresses or other private data */
144 int okZip; /* z: download zipped artifact via /zip URL */
145 int okPrivate; /* x: can send and receive private content */
146
147 /* For defense against Cross-site Request Forgery attacks */
148 char zCsrfToken[12]; /* Value of the anti-CSRF token */
149 int okCsrf; /* Anti-CSRF token is present and valid */
150
@@ -646,10 +653,25 @@
646 aCmd[nCmd++] = aCommand[i].zName;
647 }
648 multi_column_list(aCmd, nCmd);
649 }
650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
652 /*
653 ** COMMAND: version
654 **
655 ** Usage: %fossil version
@@ -1015,11 +1037,11 @@
1015 file_simplify_name(zAltRepo, -1);
1016 }
1017 db_close(1);
1018 db_open_repository(zAltRepo);
1019 login_as_user(zUser);
1020 g.okPassword = 0;
1021 zPath += i;
1022 nHost = g.zTop - g.zBaseURL;
1023 g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
1024 g.zTop = g.zBaseURL + nHost;
1025 continue;
1026
--- src/main.c
+++ src/main.c
@@ -45,10 +45,38 @@
45 /*
46 ** Maximum number of auxiliary parameters on reports
47 */
48 #define MX_AUX 5
49
50 /*
51 ** Holds flags for fossil user permissions.
52 */
53 struct FossilUserPerms {
54 char Setup; /* s: use Setup screens on web interface */
55 char Admin; /* a: administrative permission */
56 char Delete; /* d: delete wiki or tickets */
57 char Password; /* p: change password */
58 char Query; /* q: create new reports */
59 char Write; /* i: xfer inbound. checkin */
60 char Read; /* o: xfer outbound. checkout */
61 char History; /* h: access historical information. */
62 char Clone; /* g: clone */
63 char RdWiki; /* j: view wiki via web */
64 char NewWiki; /* f: create new wiki via web */
65 char ApndWiki; /* m: append to wiki via web */
66 char WrWiki; /* k: edit wiki via web */
67 char RdTkt; /* r: view tickets via web */
68 char NewTkt; /* n: create new tickets */
69 char ApndTkt; /* c: append to tickets via the web */
70 char WrTkt; /* w: make changes to tickets via web */
71 char Attach; /* b: add attachments */
72 char TktFmt; /* t: create new ticket report formats */
73 char RdAddr; /* e: read email addresses or other private data */
74 char Zip; /* z: download zipped artifact via /zip URL */
75 char Private; /* x: can send and receive private content */
76 };
77
78 /*
79 ** All global variables are in this structure.
80 */
81 struct Global {
82 int argc; char **argv; /* Command-line arguments to the program */
@@ -119,32 +147,11 @@
147 int rcvid; /* The rcvid. 0 if not yet defined. */
148 char *zIpAddr; /* The remote IP address */
149 char *zNonce; /* The nonce used for login */
150
151 /* permissions used by the server */
152 struct FossilUserPerms perm;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
154 /* For defense against Cross-site Request Forgery attacks */
155 char zCsrfToken[12]; /* Value of the anti-CSRF token */
156 int okCsrf; /* Anti-CSRF token is present and valid */
157
@@ -646,10 +653,25 @@
653 aCmd[nCmd++] = aCommand[i].zName;
654 }
655 multi_column_list(aCmd, nCmd);
656 }
657
658
659 /*
660 ** COMMAND: test-list-webpage
661 **
662 ** List all web pages
663 */
664 void cmd_test_webpage_list(void){
665 int i, nCmd;
666 const char *aCmd[count(aWebpage)];
667 for(i=nCmd=0; i<count(aWebpage); i++){
668 aCmd[nCmd++] = aWebpage[i].zName;
669 }
670 multi_column_list(aCmd, nCmd);
671 }
672
673
674 /*
675 ** COMMAND: version
676 **
677 ** Usage: %fossil version
@@ -1015,11 +1037,11 @@
1037 file_simplify_name(zAltRepo, -1);
1038 }
1039 db_close(1);
1040 db_open_repository(zAltRepo);
1041 login_as_user(zUser);
1042 g.perm.Password = 0;
1043 zPath += i;
1044 nHost = g.zTop - g.zBaseURL;
1045 g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
1046 g.zTop = g.zBaseURL + nHost;
1047 continue;
1048
+45 -23
--- src/main.c
+++ src/main.c
@@ -45,10 +45,38 @@
4545
/*
4646
** Maximum number of auxiliary parameters on reports
4747
*/
4848
#define MX_AUX 5
4949
50
+/*
51
+** Holds flags for fossil user permissions.
52
+*/
53
+struct FossilUserPerms {
54
+ char Setup; /* s: use Setup screens on web interface */
55
+ char Admin; /* a: administrative permission */
56
+ char Delete; /* d: delete wiki or tickets */
57
+ char Password; /* p: change password */
58
+ char Query; /* q: create new reports */
59
+ char Write; /* i: xfer inbound. checkin */
60
+ char Read; /* o: xfer outbound. checkout */
61
+ char History; /* h: access historical information. */
62
+ char Clone; /* g: clone */
63
+ char RdWiki; /* j: view wiki via web */
64
+ char NewWiki; /* f: create new wiki via web */
65
+ char ApndWiki; /* m: append to wiki via web */
66
+ char WrWiki; /* k: edit wiki via web */
67
+ char RdTkt; /* r: view tickets via web */
68
+ char NewTkt; /* n: create new tickets */
69
+ char ApndTkt; /* c: append to tickets via the web */
70
+ char WrTkt; /* w: make changes to tickets via web */
71
+ char Attach; /* b: add attachments */
72
+ char TktFmt; /* t: create new ticket report formats */
73
+ char RdAddr; /* e: read email addresses or other private data */
74
+ char Zip; /* z: download zipped artifact via /zip URL */
75
+ char Private; /* x: can send and receive private content */
76
+};
77
+
5078
/*
5179
** All global variables are in this structure.
5280
*/
5381
struct Global {
5482
int argc; char **argv; /* Command-line arguments to the program */
@@ -119,32 +147,11 @@
119147
int rcvid; /* The rcvid. 0 if not yet defined. */
120148
char *zIpAddr; /* The remote IP address */
121149
char *zNonce; /* The nonce used for login */
122150
123151
/* permissions used by the server */
124
- int okSetup; /* s: use Setup screens on web interface */
125
- int okAdmin; /* a: administrative permission */
126
- int okDelete; /* d: delete wiki or tickets */
127
- int okPassword; /* p: change password */
128
- int okQuery; /* q: create new reports */
129
- int okWrite; /* i: xfer inbound. checkin */
130
- int okRead; /* o: xfer outbound. checkout */
131
- int okHistory; /* h: access historical information. */
132
- int okClone; /* g: clone */
133
- int okRdWiki; /* j: view wiki via web */
134
- int okNewWiki; /* f: create new wiki via web */
135
- int okApndWiki; /* m: append to wiki via web */
136
- int okWrWiki; /* k: edit wiki via web */
137
- int okRdTkt; /* r: view tickets via web */
138
- int okNewTkt; /* n: create new tickets */
139
- int okApndTkt; /* c: append to tickets via the web */
140
- int okWrTkt; /* w: make changes to tickets via web */
141
- int okAttach; /* b: add attachments */
142
- int okTktFmt; /* t: create new ticket report formats */
143
- int okRdAddr; /* e: read email addresses or other private data */
144
- int okZip; /* z: download zipped artifact via /zip URL */
145
- int okPrivate; /* x: can send and receive private content */
152
+ struct FossilUserPerms perm;
146153
147154
/* For defense against Cross-site Request Forgery attacks */
148155
char zCsrfToken[12]; /* Value of the anti-CSRF token */
149156
int okCsrf; /* Anti-CSRF token is present and valid */
150157
@@ -646,10 +653,25 @@
646653
aCmd[nCmd++] = aCommand[i].zName;
647654
}
648655
multi_column_list(aCmd, nCmd);
649656
}
650657
658
+
659
+/*
660
+** COMMAND: test-list-webpage
661
+**
662
+** List all web pages
663
+*/
664
+void cmd_test_webpage_list(void){
665
+ int i, nCmd;
666
+ const char *aCmd[count(aWebpage)];
667
+ for(i=nCmd=0; i<count(aWebpage); i++){
668
+ aCmd[nCmd++] = aWebpage[i].zName;
669
+ }
670
+ multi_column_list(aCmd, nCmd);
671
+}
672
+
651673
652674
/*
653675
** COMMAND: version
654676
**
655677
** Usage: %fossil version
@@ -1015,11 +1037,11 @@
10151037
file_simplify_name(zAltRepo, -1);
10161038
}
10171039
db_close(1);
10181040
db_open_repository(zAltRepo);
10191041
login_as_user(zUser);
1020
- g.okPassword = 0;
1042
+ g.perm.Password = 0;
10211043
zPath += i;
10221044
nHost = g.zTop - g.zBaseURL;
10231045
g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
10241046
g.zTop = g.zBaseURL + nHost;
10251047
continue;
10261048
--- src/main.c
+++ src/main.c
@@ -45,10 +45,38 @@
45 /*
46 ** Maximum number of auxiliary parameters on reports
47 */
48 #define MX_AUX 5
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50 /*
51 ** All global variables are in this structure.
52 */
53 struct Global {
54 int argc; char **argv; /* Command-line arguments to the program */
@@ -119,32 +147,11 @@
119 int rcvid; /* The rcvid. 0 if not yet defined. */
120 char *zIpAddr; /* The remote IP address */
121 char *zNonce; /* The nonce used for login */
122
123 /* permissions used by the server */
124 int okSetup; /* s: use Setup screens on web interface */
125 int okAdmin; /* a: administrative permission */
126 int okDelete; /* d: delete wiki or tickets */
127 int okPassword; /* p: change password */
128 int okQuery; /* q: create new reports */
129 int okWrite; /* i: xfer inbound. checkin */
130 int okRead; /* o: xfer outbound. checkout */
131 int okHistory; /* h: access historical information. */
132 int okClone; /* g: clone */
133 int okRdWiki; /* j: view wiki via web */
134 int okNewWiki; /* f: create new wiki via web */
135 int okApndWiki; /* m: append to wiki via web */
136 int okWrWiki; /* k: edit wiki via web */
137 int okRdTkt; /* r: view tickets via web */
138 int okNewTkt; /* n: create new tickets */
139 int okApndTkt; /* c: append to tickets via the web */
140 int okWrTkt; /* w: make changes to tickets via web */
141 int okAttach; /* b: add attachments */
142 int okTktFmt; /* t: create new ticket report formats */
143 int okRdAddr; /* e: read email addresses or other private data */
144 int okZip; /* z: download zipped artifact via /zip URL */
145 int okPrivate; /* x: can send and receive private content */
146
147 /* For defense against Cross-site Request Forgery attacks */
148 char zCsrfToken[12]; /* Value of the anti-CSRF token */
149 int okCsrf; /* Anti-CSRF token is present and valid */
150
@@ -646,10 +653,25 @@
646 aCmd[nCmd++] = aCommand[i].zName;
647 }
648 multi_column_list(aCmd, nCmd);
649 }
650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
652 /*
653 ** COMMAND: version
654 **
655 ** Usage: %fossil version
@@ -1015,11 +1037,11 @@
1015 file_simplify_name(zAltRepo, -1);
1016 }
1017 db_close(1);
1018 db_open_repository(zAltRepo);
1019 login_as_user(zUser);
1020 g.okPassword = 0;
1021 zPath += i;
1022 nHost = g.zTop - g.zBaseURL;
1023 g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
1024 g.zTop = g.zBaseURL + nHost;
1025 continue;
1026
--- src/main.c
+++ src/main.c
@@ -45,10 +45,38 @@
45 /*
46 ** Maximum number of auxiliary parameters on reports
47 */
48 #define MX_AUX 5
49
50 /*
51 ** Holds flags for fossil user permissions.
52 */
53 struct FossilUserPerms {
54 char Setup; /* s: use Setup screens on web interface */
55 char Admin; /* a: administrative permission */
56 char Delete; /* d: delete wiki or tickets */
57 char Password; /* p: change password */
58 char Query; /* q: create new reports */
59 char Write; /* i: xfer inbound. checkin */
60 char Read; /* o: xfer outbound. checkout */
61 char History; /* h: access historical information. */
62 char Clone; /* g: clone */
63 char RdWiki; /* j: view wiki via web */
64 char NewWiki; /* f: create new wiki via web */
65 char ApndWiki; /* m: append to wiki via web */
66 char WrWiki; /* k: edit wiki via web */
67 char RdTkt; /* r: view tickets via web */
68 char NewTkt; /* n: create new tickets */
69 char ApndTkt; /* c: append to tickets via the web */
70 char WrTkt; /* w: make changes to tickets via web */
71 char Attach; /* b: add attachments */
72 char TktFmt; /* t: create new ticket report formats */
73 char RdAddr; /* e: read email addresses or other private data */
74 char Zip; /* z: download zipped artifact via /zip URL */
75 char Private; /* x: can send and receive private content */
76 };
77
78 /*
79 ** All global variables are in this structure.
80 */
81 struct Global {
82 int argc; char **argv; /* Command-line arguments to the program */
@@ -119,32 +147,11 @@
147 int rcvid; /* The rcvid. 0 if not yet defined. */
148 char *zIpAddr; /* The remote IP address */
149 char *zNonce; /* The nonce used for login */
150
151 /* permissions used by the server */
152 struct FossilUserPerms perm;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
154 /* For defense against Cross-site Request Forgery attacks */
155 char zCsrfToken[12]; /* Value of the anti-CSRF token */
156 int okCsrf; /* Anti-CSRF token is present and valid */
157
@@ -646,10 +653,25 @@
653 aCmd[nCmd++] = aCommand[i].zName;
654 }
655 multi_column_list(aCmd, nCmd);
656 }
657
658
659 /*
660 ** COMMAND: test-list-webpage
661 **
662 ** List all web pages
663 */
664 void cmd_test_webpage_list(void){
665 int i, nCmd;
666 const char *aCmd[count(aWebpage)];
667 for(i=nCmd=0; i<count(aWebpage); i++){
668 aCmd[nCmd++] = aWebpage[i].zName;
669 }
670 multi_column_list(aCmd, nCmd);
671 }
672
673
674 /*
675 ** COMMAND: version
676 **
677 ** Usage: %fossil version
@@ -1015,11 +1037,11 @@
1037 file_simplify_name(zAltRepo, -1);
1038 }
1039 db_close(1);
1040 db_open_repository(zAltRepo);
1041 login_as_user(zUser);
1042 g.perm.Password = 0;
1043 zPath += i;
1044 nHost = g.zTop - g.zBaseURL;
1045 g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
1046 g.zTop = g.zBaseURL + nHost;
1047 continue;
1048
+40 -28
--- src/merge.c
+++ src/merge.c
@@ -24,11 +24,11 @@
2424
2525
2626
/*
2727
** COMMAND: merge
2828
**
29
-** Usage: %fossil merge [--cherrypick] [--backout] VERSION
29
+** Usage: %fossil merge ?OPTIONS? VERSION
3030
**
3131
** The argument VERSION is a version that should be merged into the
3232
** current checkout. All changes from VERSION back to the nearest
3333
** common ancestor are merged. Except, if either of the --cherrypick or
3434
** --backout options are used only the changes associated with the
@@ -148,10 +148,19 @@
148148
vfile_check_signature(vid, 1, 0);
149149
db_begin_transaction();
150150
if( !nochangeFlag ) undo_begin();
151151
load_vfile_from_rid(mid);
152152
load_vfile_from_rid(pid);
153
+ if( debugFlag ){
154
+ char *z;
155
+ z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
156
+ fossil_print("P=%d %z\n", pid, z);
157
+ z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
158
+ fossil_print("M=%d %z\n", mid, z);
159
+ z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
160
+ fossil_print("V=%d %z\n", vid, z);
161
+ }
153162
154163
/*
155164
** The vfile.pathname field is used to match files against each other. The
156165
** FV table contains one row for each each unique filename in
157166
** in the current checkout, the pivot, and the version being merged.
@@ -187,19 +196,19 @@
187196
);
188197
189198
/*
190199
** Compute name changes from P->V
191200
*/
192
- find_filename_changes(vid, pid, &nChng, &aChng);
201
+ find_filename_changes(pid, vid, 0, &nChng, &aChng, debugFlag ? "P->V" : 0);
193202
if( nChng ){
194203
for(i=0; i<nChng; i++){
195204
char *z;
196
- z = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
205
+ z = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
197206
db_multi_exec(
198207
"UPDATE fv SET fnp=%Q, fnm=%Q"
199208
" WHERE fn=(SELECT name FROM filename WHERE fnid=%d)",
200
- z, z, aChng[i*2]
209
+ z, z, aChng[i*2+1]
201210
);
202211
free(z);
203212
}
204213
fossil_free(aChng);
205214
db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
@@ -217,11 +226,11 @@
217226
);
218227
219228
/*
220229
** Compute name changes from P->M
221230
*/
222
- find_filename_changes(pid, mid, &nChng, &aChng);
231
+ find_filename_changes(pid, mid, 0, &nChng, &aChng, debugFlag ? "P->M" : 0);
223232
if( nChng ){
224233
if( nChng>4 ) db_multi_exec("CREATE INDEX fv_fnp ON fv(fnp)");
225234
for(i=0; i<nChng; i++){
226235
db_multi_exec(
227236
"UPDATE fv SET fnm=(SELECT name FROM filename WHERE fnid=%d)"
@@ -250,26 +259,34 @@
250259
db_multi_exec(
251260
"UPDATE fv SET"
252261
" idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
253262
" ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
254263
" idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
255
- " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0)",
256
- pid, pid, mid, mid
264
+ " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0),"
265
+ " islinkv=coalesce((SELECT islink FROM vfile"
266
+ " WHERE vid=%d AND pathname=fnm),0),"
267
+ " islinkm=coalesce((SELECT islink FROM vfile"
268
+ " WHERE vid=%d AND pathname=fnm),0)",
269
+ pid, pid, mid, mid, vid, mid
257270
);
258271
259272
if( debugFlag ){
260273
db_prepare(&q,
261
- "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, isexe FROM fv"
274
+ "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, "
275
+ " isexe, islinkv, islinkm FROM fv"
262276
);
263277
while( db_step(&q)==SQLITE_ROW ){
264
- fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n",
278
+ fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d "
279
+ " islinkv=%d islinkm=%d\n",
265280
db_column_int(&q, 0),
266281
db_column_int(&q, 5),
267282
db_column_int(&q, 6),
268283
db_column_int(&q, 7),
269284
db_column_int(&q, 4),
270
- db_column_int(&q, 8));
285
+ db_column_int(&q, 8),
286
+ db_column_int(&q, 9),
287
+ db_column_int(&q, 10));
271288
fossil_print(" fn = [%s]\n", db_column_text(&q, 1));
272289
fossil_print(" fnp = [%s]\n", db_column_text(&q, 2));
273290
fossil_print(" fnm = [%s]\n", db_column_text(&q, 3));
274291
}
275292
db_finalize(&q);
@@ -303,12 +320,12 @@
303320
int idm = db_column_int(&q, 0);
304321
int rowid = db_column_int(&q, 1);
305322
int idv;
306323
const char *zName;
307324
db_multi_exec(
308
- "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,isexe,pathname)"
309
- " SELECT %d,3,0,rid,mrid,isexe,pathname FROM vfile WHERE id=%d",
325
+ "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,isexe,islink,pathname)"
326
+ " SELECT %d,3,0,rid,mrid,isexe,islink,pathname FROM vfile WHERE id=%d",
310327
vid, idm
311328
);
312329
idv = db_last_insert_rowid();
313330
db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid);
314331
zName = db_column_text(&q, 2);
@@ -317,41 +334,32 @@
317334
undo_save(zName);
318335
vfile_to_disk(0, idm, 0, 0);
319336
}
320337
}
321338
db_finalize(&q);
322
-
323
- /*
324
- ** Add islink information for files in V and M
325
- **
326
- */
327
- db_multi_exec(
328
- "UPDATE fv SET"
329
- " islinkv=coalesce((SELECT islink FROM vfile WHERE vid=%d AND pathname=fnm),0),"
330
- " islinkm=coalesce((SELECT islink FROM vfile WHERE vid=%d AND pathname=fnm),0)",
331
- vid, mid
332
- );
333339
334340
/*
335341
** Find files that have changed from P->M but not P->V.
336342
** Copy the M content over into V.
337343
*/
338344
db_prepare(&q,
339
- "SELECT idv, ridm, fn FROM fv"
345
+ "SELECT idv, ridm, fn, islinkm FROM fv"
340346
" WHERE idp>0 AND idv>0 AND idm>0"
341347
" AND ridm!=ridp AND ridv=ridp AND NOT chnged"
342348
);
343349
while( db_step(&q)==SQLITE_ROW ){
344350
int idv = db_column_int(&q, 0);
345351
int ridm = db_column_int(&q, 1);
346352
const char *zName = db_column_text(&q, 2);
353
+ int islinkm = db_column_int(&q, 3);
347354
/* Copy content from idm over into idv. Overwrite idv. */
348355
fossil_print("UPDATE %s\n", zName);
349356
if( !nochangeFlag ){
350357
undo_save(zName);
351358
db_multi_exec(
352
- "UPDATE vfile SET mtime=0, mrid=%d, chnged=2 WHERE id=%d", ridm, idv
359
+ "UPDATE vfile SET mtime=0, mrid=%d, chnged=2, islink=%d "
360
+ " WHERE id=%d", ridm, islinkm, idv
353361
);
354362
vfile_to_disk(0, idv, 0, 0);
355363
}
356364
}
357365
db_finalize(&q);
@@ -383,11 +391,11 @@
383391
fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n",
384392
zName, ridp, ridm, ridv);
385393
}else{
386394
fossil_print("MERGE %s\n", zName);
387395
}
388
- if( islinkv || islinkm /* || file_islink(zFullPath) */ ){
396
+ if( islinkv || islinkm /* || file_wd_islink(zFullPath) */ ){
389397
fossil_print("***** Cannot merge symlink %s\n", zName);
390398
nConflict++;
391399
}else{
392400
undo_save(zName);
393401
zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
@@ -400,11 +408,11 @@
400408
rc = merge_3way(&p, zFullPath, &m, &r);
401409
}
402410
if( rc>=0 ){
403411
if( !nochangeFlag ){
404412
blob_write_to_file(&r, zFullPath);
405
- file_setexe(zFullPath, isExe);
413
+ file_wd_setexe(zFullPath, isExe);
406414
}
407415
db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
408416
if( rc>0 ){
409417
fossil_print("***** %d merge conflicts in %s\n", rc, zName);
410418
nConflict++;
@@ -472,11 +480,15 @@
472480
" WHERE id=%d AND vid=%d", zNewName, idv, vid
473481
);
474482
if( !nochangeFlag ){
475483
char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
476484
char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
477
- file_copy(zFullOldPath, zFullNewPath);
485
+ if( file_wd_islink(zFullOldPath) ){
486
+ symlink_copy(zFullOldPath, zFullNewPath);
487
+ }else{
488
+ file_copy(zFullOldPath, zFullNewPath);
489
+ }
478490
file_delete(zFullOldPath);
479491
free(zFullNewPath);
480492
free(zFullOldPath);
481493
}
482494
}
483495
--- src/merge.c
+++ src/merge.c
@@ -24,11 +24,11 @@
24
25
26 /*
27 ** COMMAND: merge
28 **
29 ** Usage: %fossil merge [--cherrypick] [--backout] VERSION
30 **
31 ** The argument VERSION is a version that should be merged into the
32 ** current checkout. All changes from VERSION back to the nearest
33 ** common ancestor are merged. Except, if either of the --cherrypick or
34 ** --backout options are used only the changes associated with the
@@ -148,10 +148,19 @@
148 vfile_check_signature(vid, 1, 0);
149 db_begin_transaction();
150 if( !nochangeFlag ) undo_begin();
151 load_vfile_from_rid(mid);
152 load_vfile_from_rid(pid);
 
 
 
 
 
 
 
 
 
153
154 /*
155 ** The vfile.pathname field is used to match files against each other. The
156 ** FV table contains one row for each each unique filename in
157 ** in the current checkout, the pivot, and the version being merged.
@@ -187,19 +196,19 @@
187 );
188
189 /*
190 ** Compute name changes from P->V
191 */
192 find_filename_changes(vid, pid, &nChng, &aChng);
193 if( nChng ){
194 for(i=0; i<nChng; i++){
195 char *z;
196 z = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
197 db_multi_exec(
198 "UPDATE fv SET fnp=%Q, fnm=%Q"
199 " WHERE fn=(SELECT name FROM filename WHERE fnid=%d)",
200 z, z, aChng[i*2]
201 );
202 free(z);
203 }
204 fossil_free(aChng);
205 db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
@@ -217,11 +226,11 @@
217 );
218
219 /*
220 ** Compute name changes from P->M
221 */
222 find_filename_changes(pid, mid, &nChng, &aChng);
223 if( nChng ){
224 if( nChng>4 ) db_multi_exec("CREATE INDEX fv_fnp ON fv(fnp)");
225 for(i=0; i<nChng; i++){
226 db_multi_exec(
227 "UPDATE fv SET fnm=(SELECT name FROM filename WHERE fnid=%d)"
@@ -250,26 +259,34 @@
250 db_multi_exec(
251 "UPDATE fv SET"
252 " idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
253 " ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
254 " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
255 " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0)",
256 pid, pid, mid, mid
 
 
 
 
257 );
258
259 if( debugFlag ){
260 db_prepare(&q,
261 "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, isexe FROM fv"
 
262 );
263 while( db_step(&q)==SQLITE_ROW ){
264 fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n",
 
265 db_column_int(&q, 0),
266 db_column_int(&q, 5),
267 db_column_int(&q, 6),
268 db_column_int(&q, 7),
269 db_column_int(&q, 4),
270 db_column_int(&q, 8));
 
 
271 fossil_print(" fn = [%s]\n", db_column_text(&q, 1));
272 fossil_print(" fnp = [%s]\n", db_column_text(&q, 2));
273 fossil_print(" fnm = [%s]\n", db_column_text(&q, 3));
274 }
275 db_finalize(&q);
@@ -303,12 +320,12 @@
303 int idm = db_column_int(&q, 0);
304 int rowid = db_column_int(&q, 1);
305 int idv;
306 const char *zName;
307 db_multi_exec(
308 "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,isexe,pathname)"
309 " SELECT %d,3,0,rid,mrid,isexe,pathname FROM vfile WHERE id=%d",
310 vid, idm
311 );
312 idv = db_last_insert_rowid();
313 db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid);
314 zName = db_column_text(&q, 2);
@@ -317,41 +334,32 @@
317 undo_save(zName);
318 vfile_to_disk(0, idm, 0, 0);
319 }
320 }
321 db_finalize(&q);
322
323 /*
324 ** Add islink information for files in V and M
325 **
326 */
327 db_multi_exec(
328 "UPDATE fv SET"
329 " islinkv=coalesce((SELECT islink FROM vfile WHERE vid=%d AND pathname=fnm),0),"
330 " islinkm=coalesce((SELECT islink FROM vfile WHERE vid=%d AND pathname=fnm),0)",
331 vid, mid
332 );
333
334 /*
335 ** Find files that have changed from P->M but not P->V.
336 ** Copy the M content over into V.
337 */
338 db_prepare(&q,
339 "SELECT idv, ridm, fn FROM fv"
340 " WHERE idp>0 AND idv>0 AND idm>0"
341 " AND ridm!=ridp AND ridv=ridp AND NOT chnged"
342 );
343 while( db_step(&q)==SQLITE_ROW ){
344 int idv = db_column_int(&q, 0);
345 int ridm = db_column_int(&q, 1);
346 const char *zName = db_column_text(&q, 2);
 
347 /* Copy content from idm over into idv. Overwrite idv. */
348 fossil_print("UPDATE %s\n", zName);
349 if( !nochangeFlag ){
350 undo_save(zName);
351 db_multi_exec(
352 "UPDATE vfile SET mtime=0, mrid=%d, chnged=2 WHERE id=%d", ridm, idv
 
353 );
354 vfile_to_disk(0, idv, 0, 0);
355 }
356 }
357 db_finalize(&q);
@@ -383,11 +391,11 @@
383 fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n",
384 zName, ridp, ridm, ridv);
385 }else{
386 fossil_print("MERGE %s\n", zName);
387 }
388 if( islinkv || islinkm /* || file_islink(zFullPath) */ ){
389 fossil_print("***** Cannot merge symlink %s\n", zName);
390 nConflict++;
391 }else{
392 undo_save(zName);
393 zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
@@ -400,11 +408,11 @@
400 rc = merge_3way(&p, zFullPath, &m, &r);
401 }
402 if( rc>=0 ){
403 if( !nochangeFlag ){
404 blob_write_to_file(&r, zFullPath);
405 file_setexe(zFullPath, isExe);
406 }
407 db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
408 if( rc>0 ){
409 fossil_print("***** %d merge conflicts in %s\n", rc, zName);
410 nConflict++;
@@ -472,11 +480,15 @@
472 " WHERE id=%d AND vid=%d", zNewName, idv, vid
473 );
474 if( !nochangeFlag ){
475 char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
476 char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
477 file_copy(zFullOldPath, zFullNewPath);
 
 
 
 
478 file_delete(zFullOldPath);
479 free(zFullNewPath);
480 free(zFullOldPath);
481 }
482 }
483
--- src/merge.c
+++ src/merge.c
@@ -24,11 +24,11 @@
24
25
26 /*
27 ** COMMAND: merge
28 **
29 ** Usage: %fossil merge ?OPTIONS? VERSION
30 **
31 ** The argument VERSION is a version that should be merged into the
32 ** current checkout. All changes from VERSION back to the nearest
33 ** common ancestor are merged. Except, if either of the --cherrypick or
34 ** --backout options are used only the changes associated with the
@@ -148,10 +148,19 @@
148 vfile_check_signature(vid, 1, 0);
149 db_begin_transaction();
150 if( !nochangeFlag ) undo_begin();
151 load_vfile_from_rid(mid);
152 load_vfile_from_rid(pid);
153 if( debugFlag ){
154 char *z;
155 z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
156 fossil_print("P=%d %z\n", pid, z);
157 z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
158 fossil_print("M=%d %z\n", mid, z);
159 z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
160 fossil_print("V=%d %z\n", vid, z);
161 }
162
163 /*
164 ** The vfile.pathname field is used to match files against each other. The
165 ** FV table contains one row for each each unique filename in
166 ** in the current checkout, the pivot, and the version being merged.
@@ -187,19 +196,19 @@
196 );
197
198 /*
199 ** Compute name changes from P->V
200 */
201 find_filename_changes(pid, vid, 0, &nChng, &aChng, debugFlag ? "P->V" : 0);
202 if( nChng ){
203 for(i=0; i<nChng; i++){
204 char *z;
205 z = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
206 db_multi_exec(
207 "UPDATE fv SET fnp=%Q, fnm=%Q"
208 " WHERE fn=(SELECT name FROM filename WHERE fnid=%d)",
209 z, z, aChng[i*2+1]
210 );
211 free(z);
212 }
213 fossil_free(aChng);
214 db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
@@ -217,11 +226,11 @@
226 );
227
228 /*
229 ** Compute name changes from P->M
230 */
231 find_filename_changes(pid, mid, 0, &nChng, &aChng, debugFlag ? "P->M" : 0);
232 if( nChng ){
233 if( nChng>4 ) db_multi_exec("CREATE INDEX fv_fnp ON fv(fnp)");
234 for(i=0; i<nChng; i++){
235 db_multi_exec(
236 "UPDATE fv SET fnm=(SELECT name FROM filename WHERE fnid=%d)"
@@ -250,26 +259,34 @@
259 db_multi_exec(
260 "UPDATE fv SET"
261 " idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
262 " ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
263 " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
264 " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0),"
265 " islinkv=coalesce((SELECT islink FROM vfile"
266 " WHERE vid=%d AND pathname=fnm),0),"
267 " islinkm=coalesce((SELECT islink FROM vfile"
268 " WHERE vid=%d AND pathname=fnm),0)",
269 pid, pid, mid, mid, vid, mid
270 );
271
272 if( debugFlag ){
273 db_prepare(&q,
274 "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, "
275 " isexe, islinkv, islinkm FROM fv"
276 );
277 while( db_step(&q)==SQLITE_ROW ){
278 fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d "
279 " islinkv=%d islinkm=%d\n",
280 db_column_int(&q, 0),
281 db_column_int(&q, 5),
282 db_column_int(&q, 6),
283 db_column_int(&q, 7),
284 db_column_int(&q, 4),
285 db_column_int(&q, 8),
286 db_column_int(&q, 9),
287 db_column_int(&q, 10));
288 fossil_print(" fn = [%s]\n", db_column_text(&q, 1));
289 fossil_print(" fnp = [%s]\n", db_column_text(&q, 2));
290 fossil_print(" fnm = [%s]\n", db_column_text(&q, 3));
291 }
292 db_finalize(&q);
@@ -303,12 +320,12 @@
320 int idm = db_column_int(&q, 0);
321 int rowid = db_column_int(&q, 1);
322 int idv;
323 const char *zName;
324 db_multi_exec(
325 "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,isexe,islink,pathname)"
326 " SELECT %d,3,0,rid,mrid,isexe,islink,pathname FROM vfile WHERE id=%d",
327 vid, idm
328 );
329 idv = db_last_insert_rowid();
330 db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid);
331 zName = db_column_text(&q, 2);
@@ -317,41 +334,32 @@
334 undo_save(zName);
335 vfile_to_disk(0, idm, 0, 0);
336 }
337 }
338 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
339
340 /*
341 ** Find files that have changed from P->M but not P->V.
342 ** Copy the M content over into V.
343 */
344 db_prepare(&q,
345 "SELECT idv, ridm, fn, islinkm FROM fv"
346 " WHERE idp>0 AND idv>0 AND idm>0"
347 " AND ridm!=ridp AND ridv=ridp AND NOT chnged"
348 );
349 while( db_step(&q)==SQLITE_ROW ){
350 int idv = db_column_int(&q, 0);
351 int ridm = db_column_int(&q, 1);
352 const char *zName = db_column_text(&q, 2);
353 int islinkm = db_column_int(&q, 3);
354 /* Copy content from idm over into idv. Overwrite idv. */
355 fossil_print("UPDATE %s\n", zName);
356 if( !nochangeFlag ){
357 undo_save(zName);
358 db_multi_exec(
359 "UPDATE vfile SET mtime=0, mrid=%d, chnged=2, islink=%d "
360 " WHERE id=%d", ridm, islinkm, idv
361 );
362 vfile_to_disk(0, idv, 0, 0);
363 }
364 }
365 db_finalize(&q);
@@ -383,11 +391,11 @@
391 fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n",
392 zName, ridp, ridm, ridv);
393 }else{
394 fossil_print("MERGE %s\n", zName);
395 }
396 if( islinkv || islinkm /* || file_wd_islink(zFullPath) */ ){
397 fossil_print("***** Cannot merge symlink %s\n", zName);
398 nConflict++;
399 }else{
400 undo_save(zName);
401 zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
@@ -400,11 +408,11 @@
408 rc = merge_3way(&p, zFullPath, &m, &r);
409 }
410 if( rc>=0 ){
411 if( !nochangeFlag ){
412 blob_write_to_file(&r, zFullPath);
413 file_wd_setexe(zFullPath, isExe);
414 }
415 db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
416 if( rc>0 ){
417 fossil_print("***** %d merge conflicts in %s\n", rc, zName);
418 nConflict++;
@@ -472,11 +480,15 @@
480 " WHERE id=%d AND vid=%d", zNewName, idv, vid
481 );
482 if( !nochangeFlag ){
483 char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
484 char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
485 if( file_wd_islink(zFullOldPath) ){
486 symlink_copy(zFullOldPath, zFullNewPath);
487 }else{
488 file_copy(zFullOldPath, zFullNewPath);
489 }
490 file_delete(zFullOldPath);
491 free(zFullNewPath);
492 free(zFullOldPath);
493 }
494 }
495
+1 -1
--- src/merge3.c
+++ src/merge3.c
@@ -422,11 +422,11 @@
422422
azSubst[4] = "%merge"; azSubst[5] = zOther;
423423
azSubst[6] = "%output"; azSubst[7] = zOut;
424424
zCmd = string_subst(zGMerge, 8, azSubst);
425425
printf("%s\n", zCmd); fflush(stdout);
426426
fossil_system(zCmd);
427
- if( file_size(zOut)>=0 ){
427
+ if( file_wd_size(zOut)>=0 ){
428428
blob_read_from_file(pOut, zOut);
429429
file_delete(zPivot);
430430
file_delete(zOrig);
431431
file_delete(zOther);
432432
file_delete(zOut);
433433
--- src/merge3.c
+++ src/merge3.c
@@ -422,11 +422,11 @@
422 azSubst[4] = "%merge"; azSubst[5] = zOther;
423 azSubst[6] = "%output"; azSubst[7] = zOut;
424 zCmd = string_subst(zGMerge, 8, azSubst);
425 printf("%s\n", zCmd); fflush(stdout);
426 fossil_system(zCmd);
427 if( file_size(zOut)>=0 ){
428 blob_read_from_file(pOut, zOut);
429 file_delete(zPivot);
430 file_delete(zOrig);
431 file_delete(zOther);
432 file_delete(zOut);
433
--- src/merge3.c
+++ src/merge3.c
@@ -422,11 +422,11 @@
422 azSubst[4] = "%merge"; azSubst[5] = zOther;
423 azSubst[6] = "%output"; azSubst[7] = zOut;
424 zCmd = string_subst(zGMerge, 8, azSubst);
425 printf("%s\n", zCmd); fflush(stdout);
426 fossil_system(zCmd);
427 if( file_wd_size(zOut)>=0 ){
428 blob_read_from_file(pOut, zOut);
429 file_delete(zPivot);
430 file_delete(zOrig);
431 file_delete(zOther);
432 file_delete(zOut);
433
+94 -43
--- src/path.c
+++ src/path.c
@@ -89,14 +89,11 @@
8989
p = path.pAll;
9090
path.pAll = p->pAll;
9191
fossil_free(p);
9292
}
9393
bag_clear(&path.seen);
94
- path.pCurrent = 0;
95
- path.pAll = 0;
96
- path.pEnd = 0;
97
- path.nStep = 0;
94
+ memset(&path, 0, sizeof(&path));
9895
}
9996
10097
/*
10198
** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
10299
*/
@@ -119,11 +116,16 @@
119116
** Elements of the path can be traversed by following the PathNode.u.pTo
120117
** pointer chain.
121118
**
122119
** Return NULL if no path is found.
123120
*/
124
-PathNode *path_shortest(int iFrom, int iTo, int directOnly){
121
+PathNode *path_shortest(
122
+ int iFrom, /* Path starts here */
123
+ int iTo, /* Path ends here */
124
+ int directOnly, /* No merge links if true */
125
+ int oneWayOnly /* Parent->child only if true */
126
+){
125127
Stmt s;
126128
PathNode *pPrev;
127129
PathNode *p;
128130
129131
path_reset();
@@ -130,11 +132,15 @@
130132
path.pStart = path_new_node(iFrom, 0, 0);
131133
if( iTo==iFrom ){
132134
path.pEnd = path.pStart;
133135
return path.pStart;
134136
}
135
- if( directOnly ){
137
+ if( oneWayOnly ){
138
+ db_prepare(&s,
139
+ "SELECT cid, 1 FROM plink WHERE pid=:pid "
140
+ );
141
+ }else if( directOnly ){
136142
db_prepare(&s,
137143
"SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
138144
"UNION ALL "
139145
"SELECT pid, 0 FROM plink WHERE cid=:pid AND isprim"
140146
);
@@ -196,17 +202,19 @@
196202
int iFrom;
197203
int iTo;
198204
PathNode *p;
199205
int n;
200206
int directOnly;
207
+ int oneWay;
201208
202209
db_find_and_open_repository(0,0);
203210
directOnly = find_option("no-merge",0,0)!=0;
211
+ oneWay = find_option("one-way",0,0)!=0;
204212
if( g.argc!=4 ) usage("VERSION1 VERSION2");
205213
iFrom = name_to_rid(g.argv[2]);
206214
iTo = name_to_rid(g.argv[3]);
207
- p = path_shortest(iFrom, iTo, directOnly);
215
+ p = path_shortest(iFrom, iTo, directOnly, oneWay);
208216
if( p==0 ){
209217
fossil_fatal("no path from %s to %s", g.argv[1], g.argv[2]);
210218
}
211219
for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
212220
char *z;
@@ -213,11 +221,11 @@
213221
z = db_text(0,
214222
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
215223
" FROM blob, event"
216224
" WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
217225
p->rid, p->rid);
218
- fossil_print("%4d: %s", n, z);
226
+ fossil_print("%4d: %5d %s", n, p->rid, z);
219227
fossil_free(z);
220228
if( p->u.pTo ){
221229
fossil_print(" is a %s of\n",
222230
p->u.pTo->fromIsParent ? "parent" : "child");
223231
}else{
@@ -313,11 +321,11 @@
313321
z = db_text(0,
314322
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
315323
" FROM blob, event"
316324
" WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
317325
p->rid, p->rid);
318
- fossil_print("%4d: %s", n, z);
326
+ fossil_print("%4d: %5d %s", n, p->rid, z);
319327
fossil_free(z);
320328
if( p->rid==iFrom ) fossil_print(" VERSION1");
321329
if( p->rid==iTo ) fossil_print(" VERSION2");
322330
if( p->rid==iPivot ) fossil_print(" PIVOT");
323331
fossil_print("\n");
@@ -340,25 +348,29 @@
340348
** Compute all file name changes that occur going from checkin iFrom
341349
** to checkin iTo.
342350
**
343351
** The number of name changes is written into *pnChng. For each name
344352
** change, two integers are allocated for *piChng. The first is the
345
-** filename.fnid for the original name and the second is for new name.
353
+** filename.fnid for the original name as seen in check-in iFrom and
354
+** the second is for new name as it is used in check-in iTo.
355
+**
346356
** Space to hold *piChng is obtained from fossil_malloc() and should
347357
** be released by the caller.
348358
**
349
-** This routine really has nothing to do with pathion. It is located
359
+** This routine really has nothing to do with path. It is located
350360
** in this path.c module in order to leverage some of the path
351361
** infrastructure.
352362
*/
353363
void find_filename_changes(
354
- int iFrom,
355
- int iTo,
356
- int *pnChng,
357
- int **aiChng
364
+ int iFrom, /* Ancestor check-in */
365
+ int iTo, /* Recent check-in */
366
+ int revOk, /* Ok to move backwards (child->parent) if true */
367
+ int *pnChng, /* Number of name changes along the path */
368
+ int **aiChng, /* Name changes */
369
+ const char *zDebug /* Generate trace output if no NULL */
358370
){
359
- PathNode *p; /* For looping over path from iFrom to iTo */
371
+ PathNode *p; /* For looping over path from iFrom to iTo */
360372
NameChange *pAll = 0; /* List of all name changes seen so far */
361373
NameChange *pChng; /* For looping through the name change list */
362374
int nChng = 0; /* Number of files whose names have changed */
363375
int *aChng; /* Two integers per name change */
364376
int i; /* Loop counter */
@@ -366,58 +378,87 @@
366378
367379
*pnChng = 0;
368380
*aiChng = 0;
369381
if( iFrom==iTo ) return;
370382
path_reset();
371
- p = path_shortest(iFrom, iTo, 1);
383
+ p = path_shortest(iFrom, iTo, 1, revOk==0);
372384
if( p==0 ) return;
373385
path_reverse_path();
374386
db_prepare(&q1,
375
- "SELECT pfnid, fnid FROM mlink WHERE mid=:mid AND pfnid>0"
387
+ "SELECT pfnid, fnid FROM mlink"
388
+ " WHERE mid=:mid AND (pfnid>0 OR fid==0)"
389
+ " ORDER BY pfnid"
376390
);
377391
for(p=path.pStart; p; p=p->u.pTo){
378392
int fnid, pfnid;
379393
if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
380394
/* Skip nodes where the parent is not on the path */
381395
continue;
382396
}
383397
db_bind_int(&q1, ":mid", p->rid);
384398
while( db_step(&q1)==SQLITE_ROW ){
385
- if( p->fromIsParent ){
386
- fnid = db_column_int(&q1, 1);
387
- pfnid = db_column_int(&q1, 0);
388
- }else{
389
- fnid = db_column_int(&q1, 0);
390
- pfnid = db_column_int(&q1, 1);
399
+ fnid = db_column_int(&q1, 1);
400
+ pfnid = db_column_int(&q1, 0);
401
+ if( pfnid==0 ){
402
+ pfnid = fnid;
403
+ fnid = 0;
404
+ }
405
+ if( !p->fromIsParent ){
406
+ int t = fnid;
407
+ fnid = pfnid;
408
+ pfnid = t;
409
+ }
410
+ if( zDebug ){
411
+ fossil_print("%s at %d%s %.10z: %d[%z] -> %d[%z]\n",
412
+ zDebug, p->rid, p->fromIsParent ? ">" : "<",
413
+ db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid),
414
+ pfnid,
415
+ db_text(0, "SELECT name FROM filename WHERE fnid=%d", pfnid),
416
+ fnid,
417
+ db_text(0, "SELECT name FROM filename WHERE fnid=%d", fnid));
391418
}
392419
for(pChng=pAll; pChng; pChng=pChng->pNext){
393420
if( pChng->curName==pfnid ){
394421
pChng->newName = fnid;
395422
break;
396423
}
397424
}
398
- if( pChng==0 ){
425
+ if( pChng==0 && fnid>0 ){
399426
pChng = fossil_malloc( sizeof(*pChng) );
400427
pChng->pNext = pAll;
401428
pAll = pChng;
402429
pChng->origName = pfnid;
403430
pChng->curName = pfnid;
404431
pChng->newName = fnid;
405432
nChng++;
406433
}
407434
}
408
- for(pChng=pAll; pChng; pChng=pChng->pNext) pChng->curName = pChng->newName;
435
+ for(pChng=pAll; pChng; pChng=pChng->pNext){
436
+ pChng->curName = pChng->newName;
437
+ }
409438
db_reset(&q1);
410439
}
411440
db_finalize(&q1);
412441
if( nChng ){
413
- *pnChng = nChng;
414442
aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
415
- for(pChng=pAll, i=0; pChng; pChng=pChng->pNext, i+=2){
443
+ for(pChng=pAll, i=0; pChng; pChng=pChng->pNext){
444
+ if( pChng->newName==0 ) continue;
445
+ if( pChng->origName==0 ) continue;
446
+ if( pChng->newName==pChng->origName ) continue;
416447
aChng[i] = pChng->origName;
417448
aChng[i+1] = pChng->newName;
449
+ if( zDebug ){
450
+ fossil_print("%s summary %d[%z] -> %d[%z]\n",
451
+ zDebug,
452
+ aChng[i],
453
+ db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i]),
454
+ aChng[i+1],
455
+ db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i+1]));
456
+ }
457
+ i += 2;
418458
}
459
+ *pnChng = i/2;
419460
while( pAll ){
420461
pChng = pAll;
421462
pAll = pAll->pNext;
422463
fossil_free(pChng);
423464
}
@@ -425,32 +466,42 @@
425466
}
426467
427468
/*
428469
** COMMAND: test-name-changes
429470
**
430
-** Usage: %fossil test-name-changes VERSION1 VERSION2
471
+** Usage: %fossil test-name-changes [--debug] VERSION1 VERSION2
431472
**
432473
** Show all filename changes that occur going from VERSION1 to VERSION2
433474
*/
434475
void test_name_change(void){
435476
int iFrom;
436477
int iTo;
437478
int *aChng;
438479
int nChng;
439480
int i;
481
+ const char *zDebug = 0;
482
+ int revOk = 0;
440483
441484
db_find_and_open_repository(0,0);
442
- if( g.argc!=4 ) usage("VERSION1 VERSION2");
443
- iFrom = name_to_rid(g.argv[2]);
444
- iTo = name_to_rid(g.argv[3]);
445
- find_filename_changes(iFrom, iTo, &nChng, &aChng);
446
- for(i=0; i<nChng; i++){
447
- char *zFrom, *zTo;
448
-
449
- zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
450
- zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
451
- fossil_print("[%s] -> [%s]\n", zFrom, zTo);
452
- fossil_free(zFrom);
453
- fossil_free(zTo);
454
- }
455
- fossil_free(aChng);
485
+ zDebug = find_option("debug",0,0)!=0 ? "debug" : 0;
486
+ revOk = find_option("bidirectional",0,0)!=0;
487
+ if( g.argc<4 ) usage("VERSION1 VERSION2");
488
+ while( g.argc>=4 ){
489
+ iFrom = name_to_rid(g.argv[2]);
490
+ iTo = name_to_rid(g.argv[3]);
491
+ find_filename_changes(iFrom, iTo, revOk, &nChng, &aChng, zDebug);
492
+ fossil_print("------ Changes for (%d) %s -> (%d) %s\n",
493
+ iFrom, g.argv[2], iTo, g.argv[3]);
494
+ for(i=0; i<nChng; i++){
495
+ char *zFrom, *zTo;
496
+
497
+ zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
498
+ zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
499
+ fossil_print("[%s] -> [%s]\n", zFrom, zTo);
500
+ fossil_free(zFrom);
501
+ fossil_free(zTo);
502
+ }
503
+ fossil_free(aChng);
504
+ g.argv += 2;
505
+ g.argc -= 2;
506
+ }
456507
}
457508
--- src/path.c
+++ src/path.c
@@ -89,14 +89,11 @@
89 p = path.pAll;
90 path.pAll = p->pAll;
91 fossil_free(p);
92 }
93 bag_clear(&path.seen);
94 path.pCurrent = 0;
95 path.pAll = 0;
96 path.pEnd = 0;
97 path.nStep = 0;
98 }
99
100 /*
101 ** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
102 */
@@ -119,11 +116,16 @@
119 ** Elements of the path can be traversed by following the PathNode.u.pTo
120 ** pointer chain.
121 **
122 ** Return NULL if no path is found.
123 */
124 PathNode *path_shortest(int iFrom, int iTo, int directOnly){
 
 
 
 
 
125 Stmt s;
126 PathNode *pPrev;
127 PathNode *p;
128
129 path_reset();
@@ -130,11 +132,15 @@
130 path.pStart = path_new_node(iFrom, 0, 0);
131 if( iTo==iFrom ){
132 path.pEnd = path.pStart;
133 return path.pStart;
134 }
135 if( directOnly ){
 
 
 
 
136 db_prepare(&s,
137 "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
138 "UNION ALL "
139 "SELECT pid, 0 FROM plink WHERE cid=:pid AND isprim"
140 );
@@ -196,17 +202,19 @@
196 int iFrom;
197 int iTo;
198 PathNode *p;
199 int n;
200 int directOnly;
 
201
202 db_find_and_open_repository(0,0);
203 directOnly = find_option("no-merge",0,0)!=0;
 
204 if( g.argc!=4 ) usage("VERSION1 VERSION2");
205 iFrom = name_to_rid(g.argv[2]);
206 iTo = name_to_rid(g.argv[3]);
207 p = path_shortest(iFrom, iTo, directOnly);
208 if( p==0 ){
209 fossil_fatal("no path from %s to %s", g.argv[1], g.argv[2]);
210 }
211 for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
212 char *z;
@@ -213,11 +221,11 @@
213 z = db_text(0,
214 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
215 " FROM blob, event"
216 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
217 p->rid, p->rid);
218 fossil_print("%4d: %s", n, z);
219 fossil_free(z);
220 if( p->u.pTo ){
221 fossil_print(" is a %s of\n",
222 p->u.pTo->fromIsParent ? "parent" : "child");
223 }else{
@@ -313,11 +321,11 @@
313 z = db_text(0,
314 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
315 " FROM blob, event"
316 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
317 p->rid, p->rid);
318 fossil_print("%4d: %s", n, z);
319 fossil_free(z);
320 if( p->rid==iFrom ) fossil_print(" VERSION1");
321 if( p->rid==iTo ) fossil_print(" VERSION2");
322 if( p->rid==iPivot ) fossil_print(" PIVOT");
323 fossil_print("\n");
@@ -340,25 +348,29 @@
340 ** Compute all file name changes that occur going from checkin iFrom
341 ** to checkin iTo.
342 **
343 ** The number of name changes is written into *pnChng. For each name
344 ** change, two integers are allocated for *piChng. The first is the
345 ** filename.fnid for the original name and the second is for new name.
 
 
346 ** Space to hold *piChng is obtained from fossil_malloc() and should
347 ** be released by the caller.
348 **
349 ** This routine really has nothing to do with pathion. It is located
350 ** in this path.c module in order to leverage some of the path
351 ** infrastructure.
352 */
353 void find_filename_changes(
354 int iFrom,
355 int iTo,
356 int *pnChng,
357 int **aiChng
 
 
358 ){
359 PathNode *p; /* For looping over path from iFrom to iTo */
360 NameChange *pAll = 0; /* List of all name changes seen so far */
361 NameChange *pChng; /* For looping through the name change list */
362 int nChng = 0; /* Number of files whose names have changed */
363 int *aChng; /* Two integers per name change */
364 int i; /* Loop counter */
@@ -366,58 +378,87 @@
366
367 *pnChng = 0;
368 *aiChng = 0;
369 if( iFrom==iTo ) return;
370 path_reset();
371 p = path_shortest(iFrom, iTo, 1);
372 if( p==0 ) return;
373 path_reverse_path();
374 db_prepare(&q1,
375 "SELECT pfnid, fnid FROM mlink WHERE mid=:mid AND pfnid>0"
 
 
376 );
377 for(p=path.pStart; p; p=p->u.pTo){
378 int fnid, pfnid;
379 if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
380 /* Skip nodes where the parent is not on the path */
381 continue;
382 }
383 db_bind_int(&q1, ":mid", p->rid);
384 while( db_step(&q1)==SQLITE_ROW ){
385 if( p->fromIsParent ){
386 fnid = db_column_int(&q1, 1);
387 pfnid = db_column_int(&q1, 0);
388 }else{
389 fnid = db_column_int(&q1, 0);
390 pfnid = db_column_int(&q1, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
391 }
392 for(pChng=pAll; pChng; pChng=pChng->pNext){
393 if( pChng->curName==pfnid ){
394 pChng->newName = fnid;
395 break;
396 }
397 }
398 if( pChng==0 ){
399 pChng = fossil_malloc( sizeof(*pChng) );
400 pChng->pNext = pAll;
401 pAll = pChng;
402 pChng->origName = pfnid;
403 pChng->curName = pfnid;
404 pChng->newName = fnid;
405 nChng++;
406 }
407 }
408 for(pChng=pAll; pChng; pChng=pChng->pNext) pChng->curName = pChng->newName;
 
 
409 db_reset(&q1);
410 }
411 db_finalize(&q1);
412 if( nChng ){
413 *pnChng = nChng;
414 aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
415 for(pChng=pAll, i=0; pChng; pChng=pChng->pNext, i+=2){
 
 
 
416 aChng[i] = pChng->origName;
417 aChng[i+1] = pChng->newName;
 
 
 
 
 
 
 
 
 
418 }
 
419 while( pAll ){
420 pChng = pAll;
421 pAll = pAll->pNext;
422 fossil_free(pChng);
423 }
@@ -425,32 +466,42 @@
425 }
426
427 /*
428 ** COMMAND: test-name-changes
429 **
430 ** Usage: %fossil test-name-changes VERSION1 VERSION2
431 **
432 ** Show all filename changes that occur going from VERSION1 to VERSION2
433 */
434 void test_name_change(void){
435 int iFrom;
436 int iTo;
437 int *aChng;
438 int nChng;
439 int i;
 
 
440
441 db_find_and_open_repository(0,0);
442 if( g.argc!=4 ) usage("VERSION1 VERSION2");
443 iFrom = name_to_rid(g.argv[2]);
444 iTo = name_to_rid(g.argv[3]);
445 find_filename_changes(iFrom, iTo, &nChng, &aChng);
446 for(i=0; i<nChng; i++){
447 char *zFrom, *zTo;
448
449 zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
450 zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
451 fossil_print("[%s] -> [%s]\n", zFrom, zTo);
452 fossil_free(zFrom);
453 fossil_free(zTo);
454 }
455 fossil_free(aChng);
 
 
 
 
 
 
 
 
456 }
457
--- src/path.c
+++ src/path.c
@@ -89,14 +89,11 @@
89 p = path.pAll;
90 path.pAll = p->pAll;
91 fossil_free(p);
92 }
93 bag_clear(&path.seen);
94 memset(&path, 0, sizeof(&path));
 
 
 
95 }
96
97 /*
98 ** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
99 */
@@ -119,11 +116,16 @@
116 ** Elements of the path can be traversed by following the PathNode.u.pTo
117 ** pointer chain.
118 **
119 ** Return NULL if no path is found.
120 */
121 PathNode *path_shortest(
122 int iFrom, /* Path starts here */
123 int iTo, /* Path ends here */
124 int directOnly, /* No merge links if true */
125 int oneWayOnly /* Parent->child only if true */
126 ){
127 Stmt s;
128 PathNode *pPrev;
129 PathNode *p;
130
131 path_reset();
@@ -130,11 +132,15 @@
132 path.pStart = path_new_node(iFrom, 0, 0);
133 if( iTo==iFrom ){
134 path.pEnd = path.pStart;
135 return path.pStart;
136 }
137 if( oneWayOnly ){
138 db_prepare(&s,
139 "SELECT cid, 1 FROM plink WHERE pid=:pid "
140 );
141 }else if( directOnly ){
142 db_prepare(&s,
143 "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
144 "UNION ALL "
145 "SELECT pid, 0 FROM plink WHERE cid=:pid AND isprim"
146 );
@@ -196,17 +202,19 @@
202 int iFrom;
203 int iTo;
204 PathNode *p;
205 int n;
206 int directOnly;
207 int oneWay;
208
209 db_find_and_open_repository(0,0);
210 directOnly = find_option("no-merge",0,0)!=0;
211 oneWay = find_option("one-way",0,0)!=0;
212 if( g.argc!=4 ) usage("VERSION1 VERSION2");
213 iFrom = name_to_rid(g.argv[2]);
214 iTo = name_to_rid(g.argv[3]);
215 p = path_shortest(iFrom, iTo, directOnly, oneWay);
216 if( p==0 ){
217 fossil_fatal("no path from %s to %s", g.argv[1], g.argv[2]);
218 }
219 for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
220 char *z;
@@ -213,11 +221,11 @@
221 z = db_text(0,
222 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
223 " FROM blob, event"
224 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
225 p->rid, p->rid);
226 fossil_print("%4d: %5d %s", n, p->rid, z);
227 fossil_free(z);
228 if( p->u.pTo ){
229 fossil_print(" is a %s of\n",
230 p->u.pTo->fromIsParent ? "parent" : "child");
231 }else{
@@ -313,11 +321,11 @@
321 z = db_text(0,
322 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
323 " FROM blob, event"
324 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
325 p->rid, p->rid);
326 fossil_print("%4d: %5d %s", n, p->rid, z);
327 fossil_free(z);
328 if( p->rid==iFrom ) fossil_print(" VERSION1");
329 if( p->rid==iTo ) fossil_print(" VERSION2");
330 if( p->rid==iPivot ) fossil_print(" PIVOT");
331 fossil_print("\n");
@@ -340,25 +348,29 @@
348 ** Compute all file name changes that occur going from checkin iFrom
349 ** to checkin iTo.
350 **
351 ** The number of name changes is written into *pnChng. For each name
352 ** change, two integers are allocated for *piChng. The first is the
353 ** filename.fnid for the original name as seen in check-in iFrom and
354 ** the second is for new name as it is used in check-in iTo.
355 **
356 ** Space to hold *piChng is obtained from fossil_malloc() and should
357 ** be released by the caller.
358 **
359 ** This routine really has nothing to do with path. It is located
360 ** in this path.c module in order to leverage some of the path
361 ** infrastructure.
362 */
363 void find_filename_changes(
364 int iFrom, /* Ancestor check-in */
365 int iTo, /* Recent check-in */
366 int revOk, /* Ok to move backwards (child->parent) if true */
367 int *pnChng, /* Number of name changes along the path */
368 int **aiChng, /* Name changes */
369 const char *zDebug /* Generate trace output if no NULL */
370 ){
371 PathNode *p; /* For looping over path from iFrom to iTo */
372 NameChange *pAll = 0; /* List of all name changes seen so far */
373 NameChange *pChng; /* For looping through the name change list */
374 int nChng = 0; /* Number of files whose names have changed */
375 int *aChng; /* Two integers per name change */
376 int i; /* Loop counter */
@@ -366,58 +378,87 @@
378
379 *pnChng = 0;
380 *aiChng = 0;
381 if( iFrom==iTo ) return;
382 path_reset();
383 p = path_shortest(iFrom, iTo, 1, revOk==0);
384 if( p==0 ) return;
385 path_reverse_path();
386 db_prepare(&q1,
387 "SELECT pfnid, fnid FROM mlink"
388 " WHERE mid=:mid AND (pfnid>0 OR fid==0)"
389 " ORDER BY pfnid"
390 );
391 for(p=path.pStart; p; p=p->u.pTo){
392 int fnid, pfnid;
393 if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
394 /* Skip nodes where the parent is not on the path */
395 continue;
396 }
397 db_bind_int(&q1, ":mid", p->rid);
398 while( db_step(&q1)==SQLITE_ROW ){
399 fnid = db_column_int(&q1, 1);
400 pfnid = db_column_int(&q1, 0);
401 if( pfnid==0 ){
402 pfnid = fnid;
403 fnid = 0;
404 }
405 if( !p->fromIsParent ){
406 int t = fnid;
407 fnid = pfnid;
408 pfnid = t;
409 }
410 if( zDebug ){
411 fossil_print("%s at %d%s %.10z: %d[%z] -> %d[%z]\n",
412 zDebug, p->rid, p->fromIsParent ? ">" : "<",
413 db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid),
414 pfnid,
415 db_text(0, "SELECT name FROM filename WHERE fnid=%d", pfnid),
416 fnid,
417 db_text(0, "SELECT name FROM filename WHERE fnid=%d", fnid));
418 }
419 for(pChng=pAll; pChng; pChng=pChng->pNext){
420 if( pChng->curName==pfnid ){
421 pChng->newName = fnid;
422 break;
423 }
424 }
425 if( pChng==0 && fnid>0 ){
426 pChng = fossil_malloc( sizeof(*pChng) );
427 pChng->pNext = pAll;
428 pAll = pChng;
429 pChng->origName = pfnid;
430 pChng->curName = pfnid;
431 pChng->newName = fnid;
432 nChng++;
433 }
434 }
435 for(pChng=pAll; pChng; pChng=pChng->pNext){
436 pChng->curName = pChng->newName;
437 }
438 db_reset(&q1);
439 }
440 db_finalize(&q1);
441 if( nChng ){
 
442 aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
443 for(pChng=pAll, i=0; pChng; pChng=pChng->pNext){
444 if( pChng->newName==0 ) continue;
445 if( pChng->origName==0 ) continue;
446 if( pChng->newName==pChng->origName ) continue;
447 aChng[i] = pChng->origName;
448 aChng[i+1] = pChng->newName;
449 if( zDebug ){
450 fossil_print("%s summary %d[%z] -> %d[%z]\n",
451 zDebug,
452 aChng[i],
453 db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i]),
454 aChng[i+1],
455 db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i+1]));
456 }
457 i += 2;
458 }
459 *pnChng = i/2;
460 while( pAll ){
461 pChng = pAll;
462 pAll = pAll->pNext;
463 fossil_free(pChng);
464 }
@@ -425,32 +466,42 @@
466 }
467
468 /*
469 ** COMMAND: test-name-changes
470 **
471 ** Usage: %fossil test-name-changes [--debug] VERSION1 VERSION2
472 **
473 ** Show all filename changes that occur going from VERSION1 to VERSION2
474 */
475 void test_name_change(void){
476 int iFrom;
477 int iTo;
478 int *aChng;
479 int nChng;
480 int i;
481 const char *zDebug = 0;
482 int revOk = 0;
483
484 db_find_and_open_repository(0,0);
485 zDebug = find_option("debug",0,0)!=0 ? "debug" : 0;
486 revOk = find_option("bidirectional",0,0)!=0;
487 if( g.argc<4 ) usage("VERSION1 VERSION2");
488 while( g.argc>=4 ){
489 iFrom = name_to_rid(g.argv[2]);
490 iTo = name_to_rid(g.argv[3]);
491 find_filename_changes(iFrom, iTo, revOk, &nChng, &aChng, zDebug);
492 fossil_print("------ Changes for (%d) %s -> (%d) %s\n",
493 iFrom, g.argv[2], iTo, g.argv[3]);
494 for(i=0; i<nChng; i++){
495 char *zFrom, *zTo;
496
497 zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
498 zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
499 fossil_print("[%s] -> [%s]\n", zFrom, zTo);
500 fossil_free(zFrom);
501 fossil_free(zTo);
502 }
503 fossil_free(aChng);
504 g.argv += 2;
505 g.argc -= 2;
506 }
507 }
508
+25 -14
--- src/rebuild.c
+++ src/rebuild.c
@@ -338,11 +338,11 @@
338338
int incrSize;
339339
340340
bag_init(&bagDone);
341341
ttyOutput = doOut;
342342
processCnt = 0;
343
- if (!g.fQuiet) {
343
+ if (ttyOutput && !g.fQuiet) {
344344
percent_complete(0);
345345
}
346346
rebuild_update_schema();
347347
for(;;){
348348
zTable = db_text(0,
@@ -410,16 +410,16 @@
410410
}
411411
}
412412
db_finalize(&s);
413413
manifest_crosslink_end();
414414
rebuild_tag_trunk();
415
- if( !g.fQuiet && totalSize>0 ){
415
+ if( ttyOutput && !g.fQuiet && totalSize>0 ){
416416
processCnt += incrSize;
417417
percent_complete((processCnt*1000)/totalSize);
418418
}
419419
if( doClustering ) create_cluster();
420
- if( !g.fQuiet && totalSize>0 ){
420
+ if( ttyOutput && !g.fQuiet && totalSize>0 ){
421421
processCnt += incrSize;
422422
percent_complete((processCnt*1000)/totalSize);
423423
}
424424
if(!g.fQuiet && ttyOutput ){
425425
fossil_print("\n");
@@ -485,26 +485,27 @@
485485
}
486486
487487
/*
488488
** COMMAND: rebuild
489489
**
490
-** Usage: %fossil rebuild ?REPOSITORY?
490
+** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS?
491491
**
492492
** Reconstruct the named repository database from the core
493493
** records. Run this command after updating the fossil
494494
** executable in a way that changes the database schema.
495495
**
496496
** Options:
497
-**
498
-** --noverify Skip the verification of changes to the BLOB table
497
+** --cluster Compute clusters for unclustered artifacts
498
+** --compress Strive to make the database as small as possible
499499
** --force Force the rebuild to complete even if errors are seen
500
-** --randomize Scan artifacts in a random order
501
-** --cluster Compute clusters for unclustered artifacts
500
+** --noverify Skip the verification of changes to the BLOB table
502501
** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
502
+** --randomize Scan artifacts in a random order
503
+** --vacuum Run VACUUM on the database after rebuilding
503504
** --wal Set Write-Ahead-Log journalling mode on the database
504
-** --compress Strive to make the database as small as possible
505
-** --vacuum Run VACUUM on the database after rebuilding
505
+**
506
+** See also: deconstruct, reconstruct
506507
*/
507508
void rebuild_database(void){
508509
int forceFlag;
509510
int randomizeFlag;
510511
int errCnt;
@@ -693,11 +694,11 @@
693694
}
694695
}
695696
696697
/*
697698
** COMMAND: scrub
698
-** %fossil scrub [--verily] [--force] [--private] [REPOSITORY]
699
+** %fossil scrub ?OPTIONS? ?REPOSITORY?
699700
**
700701
** The command removes sensitive information (such as passwords) from a
701702
** repository so that the respository can be sent to an untrusted reader.
702703
**
703704
** By default, only passwords are removed. However, if the --verily option
@@ -709,10 +710,15 @@
709710
** This command permanently deletes the scrubbed information. The effects
710711
** of this command are irreversible. Use with caution.
711712
**
712713
** The user is prompted to confirm the scrub unless the --force option
713714
** is used.
715
+**
716
+** Options:
717
+** --force do not prompt for confirmation
718
+** --private only private branches are removed from the repository
719
+** --verily scrub real thoroughly (see above)
714720
*/
715721
void scrub_cmd(void){
716722
int bVerily = find_option("verily",0,0)!=0;
717723
int bForce = find_option("force", "f", 0)!=0;
718724
int privateOnly = find_option("private",0,0)!=0;
@@ -829,10 +835,11 @@
829835
** This command studies the artifacts (files) in DIRECTORY and
830836
** reconstructs the fossil record from them. It places the new
831837
** fossil repository in FILENAME. Subdirectories are read, files
832838
** with leading '.' in the filename are ignored.
833839
**
840
+** See also: deconstruct, rebuild
834841
*/
835842
void reconstruct_cmd(void) {
836843
char *zPassword;
837844
if( g.argc!=4 ){
838845
usage("FILENAME DIRECTORY");
@@ -884,20 +891,24 @@
884891
/*
885892
** COMMAND: deconstruct
886893
**
887894
** Usage %fossil deconstruct ?OPTIONS? DESTINATION
888895
**
889
-** Options:
890
-** -R|--repository REPOSITORY
891
-** -L|--prefixlength N
892896
**
893897
** This command exports all artifacts of a given repository and
894898
** writes all artifacts to the file system. The DESTINATION directory
895899
** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
896900
** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
897901
** If -L|--prefixlength is given, the length (default 2) of the directory
898902
** prefix can be set to 0,1,..,9 characters.
903
+**
904
+** Options:
905
+** -R|--repository REPOSITORY deconstruct given REPOSITORY
906
+** -L|--prefixlength N set the length of the names of the DESTINATION
907
+** subdirectories to N
908
+**
909
+** See also: rebuild, reconstruct
899910
*/
900911
void deconstruct_cmd(void){
901912
const char *zDestDir;
902913
const char *zPrefixOpt;
903914
Stmt s;
904915
--- src/rebuild.c
+++ src/rebuild.c
@@ -338,11 +338,11 @@
338 int incrSize;
339
340 bag_init(&bagDone);
341 ttyOutput = doOut;
342 processCnt = 0;
343 if (!g.fQuiet) {
344 percent_complete(0);
345 }
346 rebuild_update_schema();
347 for(;;){
348 zTable = db_text(0,
@@ -410,16 +410,16 @@
410 }
411 }
412 db_finalize(&s);
413 manifest_crosslink_end();
414 rebuild_tag_trunk();
415 if( !g.fQuiet && totalSize>0 ){
416 processCnt += incrSize;
417 percent_complete((processCnt*1000)/totalSize);
418 }
419 if( doClustering ) create_cluster();
420 if( !g.fQuiet && totalSize>0 ){
421 processCnt += incrSize;
422 percent_complete((processCnt*1000)/totalSize);
423 }
424 if(!g.fQuiet && ttyOutput ){
425 fossil_print("\n");
@@ -485,26 +485,27 @@
485 }
486
487 /*
488 ** COMMAND: rebuild
489 **
490 ** Usage: %fossil rebuild ?REPOSITORY?
491 **
492 ** Reconstruct the named repository database from the core
493 ** records. Run this command after updating the fossil
494 ** executable in a way that changes the database schema.
495 **
496 ** Options:
497 **
498 ** --noverify Skip the verification of changes to the BLOB table
499 ** --force Force the rebuild to complete even if errors are seen
500 ** --randomize Scan artifacts in a random order
501 ** --cluster Compute clusters for unclustered artifacts
502 ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
 
 
503 ** --wal Set Write-Ahead-Log journalling mode on the database
504 ** --compress Strive to make the database as small as possible
505 ** --vacuum Run VACUUM on the database after rebuilding
506 */
507 void rebuild_database(void){
508 int forceFlag;
509 int randomizeFlag;
510 int errCnt;
@@ -693,11 +694,11 @@
693 }
694 }
695
696 /*
697 ** COMMAND: scrub
698 ** %fossil scrub [--verily] [--force] [--private] [REPOSITORY]
699 **
700 ** The command removes sensitive information (such as passwords) from a
701 ** repository so that the respository can be sent to an untrusted reader.
702 **
703 ** By default, only passwords are removed. However, if the --verily option
@@ -709,10 +710,15 @@
709 ** This command permanently deletes the scrubbed information. The effects
710 ** of this command are irreversible. Use with caution.
711 **
712 ** The user is prompted to confirm the scrub unless the --force option
713 ** is used.
 
 
 
 
 
714 */
715 void scrub_cmd(void){
716 int bVerily = find_option("verily",0,0)!=0;
717 int bForce = find_option("force", "f", 0)!=0;
718 int privateOnly = find_option("private",0,0)!=0;
@@ -829,10 +835,11 @@
829 ** This command studies the artifacts (files) in DIRECTORY and
830 ** reconstructs the fossil record from them. It places the new
831 ** fossil repository in FILENAME. Subdirectories are read, files
832 ** with leading '.' in the filename are ignored.
833 **
 
834 */
835 void reconstruct_cmd(void) {
836 char *zPassword;
837 if( g.argc!=4 ){
838 usage("FILENAME DIRECTORY");
@@ -884,20 +891,24 @@
884 /*
885 ** COMMAND: deconstruct
886 **
887 ** Usage %fossil deconstruct ?OPTIONS? DESTINATION
888 **
889 ** Options:
890 ** -R|--repository REPOSITORY
891 ** -L|--prefixlength N
892 **
893 ** This command exports all artifacts of a given repository and
894 ** writes all artifacts to the file system. The DESTINATION directory
895 ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
896 ** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
897 ** If -L|--prefixlength is given, the length (default 2) of the directory
898 ** prefix can be set to 0,1,..,9 characters.
 
 
 
 
 
 
 
899 */
900 void deconstruct_cmd(void){
901 const char *zDestDir;
902 const char *zPrefixOpt;
903 Stmt s;
904
--- src/rebuild.c
+++ src/rebuild.c
@@ -338,11 +338,11 @@
338 int incrSize;
339
340 bag_init(&bagDone);
341 ttyOutput = doOut;
342 processCnt = 0;
343 if (ttyOutput && !g.fQuiet) {
344 percent_complete(0);
345 }
346 rebuild_update_schema();
347 for(;;){
348 zTable = db_text(0,
@@ -410,16 +410,16 @@
410 }
411 }
412 db_finalize(&s);
413 manifest_crosslink_end();
414 rebuild_tag_trunk();
415 if( ttyOutput && !g.fQuiet && totalSize>0 ){
416 processCnt += incrSize;
417 percent_complete((processCnt*1000)/totalSize);
418 }
419 if( doClustering ) create_cluster();
420 if( ttyOutput && !g.fQuiet && totalSize>0 ){
421 processCnt += incrSize;
422 percent_complete((processCnt*1000)/totalSize);
423 }
424 if(!g.fQuiet && ttyOutput ){
425 fossil_print("\n");
@@ -485,26 +485,27 @@
485 }
486
487 /*
488 ** COMMAND: rebuild
489 **
490 ** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS?
491 **
492 ** Reconstruct the named repository database from the core
493 ** records. Run this command after updating the fossil
494 ** executable in a way that changes the database schema.
495 **
496 ** Options:
497 ** --cluster Compute clusters for unclustered artifacts
498 ** --compress Strive to make the database as small as possible
499 ** --force Force the rebuild to complete even if errors are seen
500 ** --noverify Skip the verification of changes to the BLOB table
 
501 ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
502 ** --randomize Scan artifacts in a random order
503 ** --vacuum Run VACUUM on the database after rebuilding
504 ** --wal Set Write-Ahead-Log journalling mode on the database
505 **
506 ** See also: deconstruct, reconstruct
507 */
508 void rebuild_database(void){
509 int forceFlag;
510 int randomizeFlag;
511 int errCnt;
@@ -693,11 +694,11 @@
694 }
695 }
696
697 /*
698 ** COMMAND: scrub
699 ** %fossil scrub ?OPTIONS? ?REPOSITORY?
700 **
701 ** The command removes sensitive information (such as passwords) from a
702 ** repository so that the respository can be sent to an untrusted reader.
703 **
704 ** By default, only passwords are removed. However, if the --verily option
@@ -709,10 +710,15 @@
710 ** This command permanently deletes the scrubbed information. The effects
711 ** of this command are irreversible. Use with caution.
712 **
713 ** The user is prompted to confirm the scrub unless the --force option
714 ** is used.
715 **
716 ** Options:
717 ** --force do not prompt for confirmation
718 ** --private only private branches are removed from the repository
719 ** --verily scrub real thoroughly (see above)
720 */
721 void scrub_cmd(void){
722 int bVerily = find_option("verily",0,0)!=0;
723 int bForce = find_option("force", "f", 0)!=0;
724 int privateOnly = find_option("private",0,0)!=0;
@@ -829,10 +835,11 @@
835 ** This command studies the artifacts (files) in DIRECTORY and
836 ** reconstructs the fossil record from them. It places the new
837 ** fossil repository in FILENAME. Subdirectories are read, files
838 ** with leading '.' in the filename are ignored.
839 **
840 ** See also: deconstruct, rebuild
841 */
842 void reconstruct_cmd(void) {
843 char *zPassword;
844 if( g.argc!=4 ){
845 usage("FILENAME DIRECTORY");
@@ -884,20 +891,24 @@
891 /*
892 ** COMMAND: deconstruct
893 **
894 ** Usage %fossil deconstruct ?OPTIONS? DESTINATION
895 **
 
 
 
896 **
897 ** This command exports all artifacts of a given repository and
898 ** writes all artifacts to the file system. The DESTINATION directory
899 ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
900 ** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
901 ** If -L|--prefixlength is given, the length (default 2) of the directory
902 ** prefix can be set to 0,1,..,9 characters.
903 **
904 ** Options:
905 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
906 ** -L|--prefixlength N set the length of the names of the DESTINATION
907 ** subdirectories to N
908 **
909 ** See also: rebuild, reconstruct
910 */
911 void deconstruct_cmd(void){
912 const char *zDestDir;
913 const char *zPrefixOpt;
914 Stmt s;
915
+23 -23
--- src/report.c
+++ src/report.c
@@ -34,11 +34,11 @@
3434
Stmt q;
3535
int rn = 0;
3636
int cnt = 0;
3737
3838
login_check_credentials();
39
- if( !g.okRdTkt && !g.okNewTkt ){ login_needed(); return; }
39
+ if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(); return; }
4040
style_header("Ticket Main Menu");
4141
if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
4242
zScript = ticket_reportlist_code();
4343
if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
4444
@@ -47,11 +47,11 @@
4747
4848
db_prepare(&q, "SELECT rn, title, owner FROM reportfmt ORDER BY title");
4949
while( db_step(&q)==SQLITE_ROW ){
5050
const char *zTitle = db_column_text(&q, 1);
5151
const char *zOwner = db_column_text(&q, 2);
52
- if( zTitle[0] =='_' && !g.okTktFmt ){
52
+ if( zTitle[0] =='_' && !g.perm.TktFmt ){
5353
continue;
5454
}
5555
rn = db_column_int(&q, 0);
5656
cnt++;
5757
blob_appendf(&ril, "<li>");
@@ -59,22 +59,22 @@
5959
blob_appendf(&ril, "%s", zTitle);
6060
} else {
6161
blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle);
6262
}
6363
blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
64
- if( g.okWrite && zOwner && zOwner[0] ){
64
+ if( g.perm.Write && zOwner && zOwner[0] ){
6565
blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
6666
}
67
- if( g.okTktFmt ){
67
+ if( g.perm.TktFmt ){
6868
blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&amp;copy=1\" rel=\"nofollow\">copy</a>] ", rn);
6969
}
70
- if( g.okAdmin
71
- || (g.okWrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
70
+ if( g.perm.Admin
71
+ || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
7272
){
7373
blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] ", rn);
7474
}
75
- if( g.okTktFmt ){
75
+ if( g.perm.TktFmt ){
7676
blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn);
7777
}
7878
blob_appendf(&ril, "</li>\n");
7979
}
8080
@@ -184,11 +184,11 @@
184184
if( fossil_stricmp(zArg1, azAllowed[i])==0 ) break;
185185
}
186186
if( i>=sizeof(azAllowed)/sizeof(azAllowed[0]) ){
187187
*(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1);
188188
rc = SQLITE_DENY;
189
- }else if( !g.okRdAddr && strncmp(zArg2, "private_", 8)==0 ){
189
+ }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){
190190
rc = SQLITE_IGNORE;
191191
}
192192
break;
193193
}
194194
default: {
@@ -275,11 +275,11 @@
275275
const char *zOwner;
276276
const char *zClrKey;
277277
Stmt q;
278278
279279
login_check_credentials();
280
- if( !g.okTktFmt ){
280
+ if( !g.perm.TktFmt ){
281281
login_needed();
282282
return;
283283
}
284284
rn = atoi(PD("rn","0"));
285285
db_prepare(&q, "SELECT title, sqlcode, owner, cols "
@@ -323,11 +323,11 @@
323323
const char *zClrKey;
324324
char *zSQL;
325325
char *zErr = 0;
326326
327327
login_check_credentials();
328
- if( !g.okTktFmt ){
328
+ if( !g.perm.TktFmt ){
329329
login_needed();
330330
return;
331331
}
332332
/*view_add_functions(0);*/
333333
rn = atoi(PD("rn","0"));
@@ -430,11 +430,11 @@
430430
@ <input type="text" name="t" value="%h(zTitle)" size="60" /></p>
431431
@ <p>Enter a complete SQL query statement against the "TICKET" table:<br />
432432
@ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea>
433433
@ </p>
434434
login_insert_csrf_secret();
435
- if( g.okAdmin ){
435
+ if( g.perm.Admin ){
436436
@ <p>Report owner:
437437
@ <input type="text" name="w" size="20" value="%h(zOwner)" />
438438
@ </p>
439439
} else {
440440
@ <input type="hidden" name="w" value="%h(zOwner)" />
@@ -443,11 +443,11 @@
443443
@ color key is displayed.) Each line contains the text for a single
444444
@ entry in the key. The first token of each line is the background
445445
@ color for that line.<br />
446446
@ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
447447
@ </p>
448
- if( !g.okAdmin && fossil_strcmp(zOwner,g.zLogin)!=0 ){
448
+ if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){
449449
@ <p>This report format is owned by %h(zOwner). You are not allowed
450450
@ to change it.</p>
451451
@ </form>
452452
report_format_hints();
453453
style_footer();
@@ -659,11 +659,11 @@
659659
for(i=0; i<nArg; i++){
660660
if( azName[i][0]=='b' && fossil_strcmp(azName[i],"bgcolor")==0 ){
661661
pState->iBg = i;
662662
continue;
663663
}
664
- if( g.okWrite && azName[i][0]=='#' ){
664
+ if( g.perm.Write && azName[i][0]=='#' ){
665665
pState->nCol++;
666666
}
667667
if( !pState->isMultirow ){
668668
if( azName[i][0]=='_' ){
669669
pState->isMultirow = 1;
@@ -680,11 +680,11 @@
680680
zTid = 0;
681681
for(i=0; i<nArg; i++){
682682
char *zName = azName[i];
683683
if( i==pState->iBg ) continue;
684684
if( pState->iNewRow>=0 && i>=pState->iNewRow ){
685
- if( g.okWrite && zTid ){
685
+ if( g.perm.Write && zTid ){
686686
@ <th>&nbsp;</th>
687687
zTid = 0;
688688
}
689689
if( zName[0]=='_' ) zName++;
690690
@ </tr><tr><th colspan=%d(pState->nCol)>%h(zName)</th>
@@ -693,11 +693,11 @@
693693
zTid = zName;
694694
}
695695
@ <th>%h(zName)</th>
696696
}
697697
}
698
- if( g.okWrite && zTid ){
698
+ if( g.perm.Write && zTid ){
699699
@ <th>&nbsp;</th>
700700
}
701701
@ </tr>
702702
}
703703
if( azArg==0 ){
@@ -726,11 +726,11 @@
726726
char *zData;
727727
if( i==pState->iBg ) continue;
728728
zData = azArg[i];
729729
if( zData==0 ) zData = "";
730730
if( pState->iNewRow>=0 && i>=pState->iNewRow ){
731
- if( zTid && g.okWrite ){
731
+ if( zTid && g.perm.Write ){
732732
@ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
733733
zTid = 0;
734734
}
735735
if( zData[0] ){
736736
Blob content;
@@ -739,11 +739,11 @@
739739
wiki_convert(&content, 0, 0);
740740
blob_reset(&content);
741741
}
742742
}else if( azName[i][0]=='#' ){
743743
zTid = zData;
744
- if( g.okHistory ){
744
+ if( g.perm.History ){
745745
@ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td>
746746
}else{
747747
@ <td valign="top">%h(zData)</td>
748748
}
749749
}else if( zData[0]==0 ){
@@ -752,11 +752,11 @@
752752
@ <td valign="top">
753753
@ %h(zData)
754754
@ </td>
755755
}
756756
}
757
- if( zTid && g.okWrite ){
757
+ if( zTid && g.perm.Write ){
758758
@ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
759759
}
760760
@ </tr>
761761
return 0;
762762
}
@@ -915,11 +915,11 @@
915915
Stmt q;
916916
char *zErr1 = 0;
917917
char *zErr2 = 0;
918918
919919
login_check_credentials();
920
- if( !g.okRdTkt ){ login_needed(); return; }
920
+ if( !g.perm.RdTkt ){ login_needed(); return; }
921921
rn = atoi(PD("rn","0"));
922922
if( rn==0 ){
923923
cgi_redirect("reportlist");
924924
return;
925925
}
@@ -957,18 +957,18 @@
957957
struct GenerateHTML sState;
958958
959959
db_multi_exec("PRAGMA empty_result_callbacks=ON");
960960
style_submenu_element("Raw", "Raw",
961961
"rptview?tablist=1&amp;%h", PD("QUERY_STRING",""));
962
- if( g.okAdmin
963
- || (g.okTktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
962
+ if( g.perm.Admin
963
+ || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
964964
style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
965965
}
966
- if( g.okTktFmt ){
966
+ if( g.perm.TktFmt ){
967967
style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
968968
}
969
- if( g.okNewTkt ){
969
+ if( g.perm.NewTkt ){
970970
style_submenu_element("New Ticket", "Create a new ticket",
971971
"%s/tktnew", g.zTop);
972972
}
973973
style_header(zTitle);
974974
output_color_key(zClrKey, 1,
975975
--- src/report.c
+++ src/report.c
@@ -34,11 +34,11 @@
34 Stmt q;
35 int rn = 0;
36 int cnt = 0;
37
38 login_check_credentials();
39 if( !g.okRdTkt && !g.okNewTkt ){ login_needed(); return; }
40 style_header("Ticket Main Menu");
41 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
42 zScript = ticket_reportlist_code();
43 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
44
@@ -47,11 +47,11 @@
47
48 db_prepare(&q, "SELECT rn, title, owner FROM reportfmt ORDER BY title");
49 while( db_step(&q)==SQLITE_ROW ){
50 const char *zTitle = db_column_text(&q, 1);
51 const char *zOwner = db_column_text(&q, 2);
52 if( zTitle[0] =='_' && !g.okTktFmt ){
53 continue;
54 }
55 rn = db_column_int(&q, 0);
56 cnt++;
57 blob_appendf(&ril, "<li>");
@@ -59,22 +59,22 @@
59 blob_appendf(&ril, "%s", zTitle);
60 } else {
61 blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle);
62 }
63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
64 if( g.okWrite && zOwner && zOwner[0] ){
65 blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
66 }
67 if( g.okTktFmt ){
68 blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&amp;copy=1\" rel=\"nofollow\">copy</a>] ", rn);
69 }
70 if( g.okAdmin
71 || (g.okWrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
72 ){
73 blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] ", rn);
74 }
75 if( g.okTktFmt ){
76 blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn);
77 }
78 blob_appendf(&ril, "</li>\n");
79 }
80
@@ -184,11 +184,11 @@
184 if( fossil_stricmp(zArg1, azAllowed[i])==0 ) break;
185 }
186 if( i>=sizeof(azAllowed)/sizeof(azAllowed[0]) ){
187 *(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1);
188 rc = SQLITE_DENY;
189 }else if( !g.okRdAddr && strncmp(zArg2, "private_", 8)==0 ){
190 rc = SQLITE_IGNORE;
191 }
192 break;
193 }
194 default: {
@@ -275,11 +275,11 @@
275 const char *zOwner;
276 const char *zClrKey;
277 Stmt q;
278
279 login_check_credentials();
280 if( !g.okTktFmt ){
281 login_needed();
282 return;
283 }
284 rn = atoi(PD("rn","0"));
285 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
@@ -323,11 +323,11 @@
323 const char *zClrKey;
324 char *zSQL;
325 char *zErr = 0;
326
327 login_check_credentials();
328 if( !g.okTktFmt ){
329 login_needed();
330 return;
331 }
332 /*view_add_functions(0);*/
333 rn = atoi(PD("rn","0"));
@@ -430,11 +430,11 @@
430 @ <input type="text" name="t" value="%h(zTitle)" size="60" /></p>
431 @ <p>Enter a complete SQL query statement against the "TICKET" table:<br />
432 @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea>
433 @ </p>
434 login_insert_csrf_secret();
435 if( g.okAdmin ){
436 @ <p>Report owner:
437 @ <input type="text" name="w" size="20" value="%h(zOwner)" />
438 @ </p>
439 } else {
440 @ <input type="hidden" name="w" value="%h(zOwner)" />
@@ -443,11 +443,11 @@
443 @ color key is displayed.) Each line contains the text for a single
444 @ entry in the key. The first token of each line is the background
445 @ color for that line.<br />
446 @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
447 @ </p>
448 if( !g.okAdmin && fossil_strcmp(zOwner,g.zLogin)!=0 ){
449 @ <p>This report format is owned by %h(zOwner). You are not allowed
450 @ to change it.</p>
451 @ </form>
452 report_format_hints();
453 style_footer();
@@ -659,11 +659,11 @@
659 for(i=0; i<nArg; i++){
660 if( azName[i][0]=='b' && fossil_strcmp(azName[i],"bgcolor")==0 ){
661 pState->iBg = i;
662 continue;
663 }
664 if( g.okWrite && azName[i][0]=='#' ){
665 pState->nCol++;
666 }
667 if( !pState->isMultirow ){
668 if( azName[i][0]=='_' ){
669 pState->isMultirow = 1;
@@ -680,11 +680,11 @@
680 zTid = 0;
681 for(i=0; i<nArg; i++){
682 char *zName = azName[i];
683 if( i==pState->iBg ) continue;
684 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
685 if( g.okWrite && zTid ){
686 @ <th>&nbsp;</th>
687 zTid = 0;
688 }
689 if( zName[0]=='_' ) zName++;
690 @ </tr><tr><th colspan=%d(pState->nCol)>%h(zName)</th>
@@ -693,11 +693,11 @@
693 zTid = zName;
694 }
695 @ <th>%h(zName)</th>
696 }
697 }
698 if( g.okWrite && zTid ){
699 @ <th>&nbsp;</th>
700 }
701 @ </tr>
702 }
703 if( azArg==0 ){
@@ -726,11 +726,11 @@
726 char *zData;
727 if( i==pState->iBg ) continue;
728 zData = azArg[i];
729 if( zData==0 ) zData = "";
730 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
731 if( zTid && g.okWrite ){
732 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
733 zTid = 0;
734 }
735 if( zData[0] ){
736 Blob content;
@@ -739,11 +739,11 @@
739 wiki_convert(&content, 0, 0);
740 blob_reset(&content);
741 }
742 }else if( azName[i][0]=='#' ){
743 zTid = zData;
744 if( g.okHistory ){
745 @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td>
746 }else{
747 @ <td valign="top">%h(zData)</td>
748 }
749 }else if( zData[0]==0 ){
@@ -752,11 +752,11 @@
752 @ <td valign="top">
753 @ %h(zData)
754 @ </td>
755 }
756 }
757 if( zTid && g.okWrite ){
758 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
759 }
760 @ </tr>
761 return 0;
762 }
@@ -915,11 +915,11 @@
915 Stmt q;
916 char *zErr1 = 0;
917 char *zErr2 = 0;
918
919 login_check_credentials();
920 if( !g.okRdTkt ){ login_needed(); return; }
921 rn = atoi(PD("rn","0"));
922 if( rn==0 ){
923 cgi_redirect("reportlist");
924 return;
925 }
@@ -957,18 +957,18 @@
957 struct GenerateHTML sState;
958
959 db_multi_exec("PRAGMA empty_result_callbacks=ON");
960 style_submenu_element("Raw", "Raw",
961 "rptview?tablist=1&amp;%h", PD("QUERY_STRING",""));
962 if( g.okAdmin
963 || (g.okTktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
964 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
965 }
966 if( g.okTktFmt ){
967 style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
968 }
969 if( g.okNewTkt ){
970 style_submenu_element("New Ticket", "Create a new ticket",
971 "%s/tktnew", g.zTop);
972 }
973 style_header(zTitle);
974 output_color_key(zClrKey, 1,
975
--- src/report.c
+++ src/report.c
@@ -34,11 +34,11 @@
34 Stmt q;
35 int rn = 0;
36 int cnt = 0;
37
38 login_check_credentials();
39 if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(); return; }
40 style_header("Ticket Main Menu");
41 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
42 zScript = ticket_reportlist_code();
43 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
44
@@ -47,11 +47,11 @@
47
48 db_prepare(&q, "SELECT rn, title, owner FROM reportfmt ORDER BY title");
49 while( db_step(&q)==SQLITE_ROW ){
50 const char *zTitle = db_column_text(&q, 1);
51 const char *zOwner = db_column_text(&q, 2);
52 if( zTitle[0] =='_' && !g.perm.TktFmt ){
53 continue;
54 }
55 rn = db_column_int(&q, 0);
56 cnt++;
57 blob_appendf(&ril, "<li>");
@@ -59,22 +59,22 @@
59 blob_appendf(&ril, "%s", zTitle);
60 } else {
61 blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle);
62 }
63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
64 if( g.perm.Write && zOwner && zOwner[0] ){
65 blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
66 }
67 if( g.perm.TktFmt ){
68 blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&amp;copy=1\" rel=\"nofollow\">copy</a>] ", rn);
69 }
70 if( g.perm.Admin
71 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
72 ){
73 blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] ", rn);
74 }
75 if( g.perm.TktFmt ){
76 blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn);
77 }
78 blob_appendf(&ril, "</li>\n");
79 }
80
@@ -184,11 +184,11 @@
184 if( fossil_stricmp(zArg1, azAllowed[i])==0 ) break;
185 }
186 if( i>=sizeof(azAllowed)/sizeof(azAllowed[0]) ){
187 *(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1);
188 rc = SQLITE_DENY;
189 }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){
190 rc = SQLITE_IGNORE;
191 }
192 break;
193 }
194 default: {
@@ -275,11 +275,11 @@
275 const char *zOwner;
276 const char *zClrKey;
277 Stmt q;
278
279 login_check_credentials();
280 if( !g.perm.TktFmt ){
281 login_needed();
282 return;
283 }
284 rn = atoi(PD("rn","0"));
285 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
@@ -323,11 +323,11 @@
323 const char *zClrKey;
324 char *zSQL;
325 char *zErr = 0;
326
327 login_check_credentials();
328 if( !g.perm.TktFmt ){
329 login_needed();
330 return;
331 }
332 /*view_add_functions(0);*/
333 rn = atoi(PD("rn","0"));
@@ -430,11 +430,11 @@
430 @ <input type="text" name="t" value="%h(zTitle)" size="60" /></p>
431 @ <p>Enter a complete SQL query statement against the "TICKET" table:<br />
432 @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea>
433 @ </p>
434 login_insert_csrf_secret();
435 if( g.perm.Admin ){
436 @ <p>Report owner:
437 @ <input type="text" name="w" size="20" value="%h(zOwner)" />
438 @ </p>
439 } else {
440 @ <input type="hidden" name="w" value="%h(zOwner)" />
@@ -443,11 +443,11 @@
443 @ color key is displayed.) Each line contains the text for a single
444 @ entry in the key. The first token of each line is the background
445 @ color for that line.<br />
446 @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
447 @ </p>
448 if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){
449 @ <p>This report format is owned by %h(zOwner). You are not allowed
450 @ to change it.</p>
451 @ </form>
452 report_format_hints();
453 style_footer();
@@ -659,11 +659,11 @@
659 for(i=0; i<nArg; i++){
660 if( azName[i][0]=='b' && fossil_strcmp(azName[i],"bgcolor")==0 ){
661 pState->iBg = i;
662 continue;
663 }
664 if( g.perm.Write && azName[i][0]=='#' ){
665 pState->nCol++;
666 }
667 if( !pState->isMultirow ){
668 if( azName[i][0]=='_' ){
669 pState->isMultirow = 1;
@@ -680,11 +680,11 @@
680 zTid = 0;
681 for(i=0; i<nArg; i++){
682 char *zName = azName[i];
683 if( i==pState->iBg ) continue;
684 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
685 if( g.perm.Write && zTid ){
686 @ <th>&nbsp;</th>
687 zTid = 0;
688 }
689 if( zName[0]=='_' ) zName++;
690 @ </tr><tr><th colspan=%d(pState->nCol)>%h(zName)</th>
@@ -693,11 +693,11 @@
693 zTid = zName;
694 }
695 @ <th>%h(zName)</th>
696 }
697 }
698 if( g.perm.Write && zTid ){
699 @ <th>&nbsp;</th>
700 }
701 @ </tr>
702 }
703 if( azArg==0 ){
@@ -726,11 +726,11 @@
726 char *zData;
727 if( i==pState->iBg ) continue;
728 zData = azArg[i];
729 if( zData==0 ) zData = "";
730 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
731 if( zTid && g.perm.Write ){
732 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
733 zTid = 0;
734 }
735 if( zData[0] ){
736 Blob content;
@@ -739,11 +739,11 @@
739 wiki_convert(&content, 0, 0);
740 blob_reset(&content);
741 }
742 }else if( azName[i][0]=='#' ){
743 zTid = zData;
744 if( g.perm.History ){
745 @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td>
746 }else{
747 @ <td valign="top">%h(zData)</td>
748 }
749 }else if( zData[0]==0 ){
@@ -752,11 +752,11 @@
752 @ <td valign="top">
753 @ %h(zData)
754 @ </td>
755 }
756 }
757 if( zTid && g.perm.Write ){
758 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
759 }
760 @ </tr>
761 return 0;
762 }
@@ -915,11 +915,11 @@
915 Stmt q;
916 char *zErr1 = 0;
917 char *zErr2 = 0;
918
919 login_check_credentials();
920 if( !g.perm.RdTkt ){ login_needed(); return; }
921 rn = atoi(PD("rn","0"));
922 if( rn==0 ){
923 cgi_redirect("reportlist");
924 return;
925 }
@@ -957,18 +957,18 @@
957 struct GenerateHTML sState;
958
959 db_multi_exec("PRAGMA empty_result_callbacks=ON");
960 style_submenu_element("Raw", "Raw",
961 "rptview?tablist=1&amp;%h", PD("QUERY_STRING",""));
962 if( g.perm.Admin
963 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
964 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
965 }
966 if( g.perm.TktFmt ){
967 style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
968 }
969 if( g.perm.NewTkt ){
970 style_submenu_element("New Ticket", "Create a new ticket",
971 "%s/tktnew", g.zTop);
972 }
973 style_header(zTitle);
974 output_color_key(zClrKey, 1,
975
+13 -13
--- src/rss.c
+++ src/rss.c
@@ -44,39 +44,39 @@
4444
@ FROM event, blob
4545
@ WHERE blob.rid=event.objid
4646
;
4747
4848
login_check_credentials();
49
- if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){
49
+ if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
5050
return;
5151
}
5252
5353
blob_zero(&bSQL);
5454
blob_append( &bSQL, zSQL1, -1 );
5555
5656
if( zType[0]!='a' ){
57
- if( zType[0]=='c' && !g.okRead ) zType = "x";
58
- if( zType[0]=='w' && !g.okRdWiki ) zType = "x";
59
- if( zType[0]=='t' && !g.okRdTkt ) zType = "x";
57
+ if( zType[0]=='c' && !g.perm.Read ) zType = "x";
58
+ if( zType[0]=='w' && !g.perm.RdWiki ) zType = "x";
59
+ if( zType[0]=='t' && !g.perm.RdTkt ) zType = "x";
6060
blob_appendf(&bSQL, " AND event.type=%Q", zType);
6161
}else{
62
- if( !g.okRead ){
63
- if( g.okRdTkt && g.okRdWiki ){
62
+ if( !g.perm.Read ){
63
+ if( g.perm.RdTkt && g.perm.RdWiki ){
6464
blob_append(&bSQL, " AND event.type!='ci'", -1);
65
- }else if( g.okRdTkt ){
65
+ }else if( g.perm.RdTkt ){
6666
blob_append(&bSQL, " AND event.type=='t'", -1);
6767
}else{
6868
blob_append(&bSQL, " AND event.type=='w'", -1);
6969
}
70
- }else if( !g.okRdWiki ){
71
- if( g.okRdTkt ){
70
+ }else if( !g.perm.RdWiki ){
71
+ if( g.perm.RdTkt ){
7272
blob_append(&bSQL, " AND event.type!='w'", -1);
7373
}else{
7474
blob_append(&bSQL, " AND event.type=='ci'", -1);
7575
}
76
- }else if( !g.okRdTkt ){
77
- assert( !g.okRdTkt &&& g.okRead && g.okRdWiki );
76
+ }else if( !g.perm.RdTkt ){
77
+ assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki );
7878
blob_append(&bSQL, " AND event.type!='t'", -1);
7979
}
8080
}
8181
8282
blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
@@ -94,11 +94,11 @@
9494
}
9595
9696
zPubDate = cgi_rfc822_datestamp(time(NULL));
9797
9898
@ <?xml version="1.0"?>
99
- @ <rss version="2.0">
99
+ @ <rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
100100
@ <channel>
101101
@ <title>%h(zProjectName)</title>
102102
@ <link>%s(g.zBaseURL)</link>
103103
@ <description>%h(zProjectDescr)</description>
104104
@ <pubDate>%s(zPubDate)</pubDate>
@@ -130,11 +130,11 @@
130130
@ <item>
131131
@ <title>%s(zPrefix)%h(zCom)</title>
132132
@ <link>%s(g.zBaseURL)/info/%s(zId)</link>
133133
@ <description>%s(zPrefix)%h(zCom)</description>
134134
@ <pubDate>%s(zDate)</pubDate>
135
- @ <author>%h(zAuthor)</author>
135
+ @ <dc:creator>%h(zAuthor)</dc:creator>
136136
@ <guid>%s(g.zBaseURL)/info/%s(zId)</guid>
137137
@ </item>
138138
free(zDate);
139139
nLine++;
140140
}
141141
--- src/rss.c
+++ src/rss.c
@@ -44,39 +44,39 @@
44 @ FROM event, blob
45 @ WHERE blob.rid=event.objid
46 ;
47
48 login_check_credentials();
49 if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){
50 return;
51 }
52
53 blob_zero(&bSQL);
54 blob_append( &bSQL, zSQL1, -1 );
55
56 if( zType[0]!='a' ){
57 if( zType[0]=='c' && !g.okRead ) zType = "x";
58 if( zType[0]=='w' && !g.okRdWiki ) zType = "x";
59 if( zType[0]=='t' && !g.okRdTkt ) zType = "x";
60 blob_appendf(&bSQL, " AND event.type=%Q", zType);
61 }else{
62 if( !g.okRead ){
63 if( g.okRdTkt && g.okRdWiki ){
64 blob_append(&bSQL, " AND event.type!='ci'", -1);
65 }else if( g.okRdTkt ){
66 blob_append(&bSQL, " AND event.type=='t'", -1);
67 }else{
68 blob_append(&bSQL, " AND event.type=='w'", -1);
69 }
70 }else if( !g.okRdWiki ){
71 if( g.okRdTkt ){
72 blob_append(&bSQL, " AND event.type!='w'", -1);
73 }else{
74 blob_append(&bSQL, " AND event.type=='ci'", -1);
75 }
76 }else if( !g.okRdTkt ){
77 assert( !g.okRdTkt &&& g.okRead && g.okRdWiki );
78 blob_append(&bSQL, " AND event.type!='t'", -1);
79 }
80 }
81
82 blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
@@ -94,11 +94,11 @@
94 }
95
96 zPubDate = cgi_rfc822_datestamp(time(NULL));
97
98 @ <?xml version="1.0"?>
99 @ <rss version="2.0">
100 @ <channel>
101 @ <title>%h(zProjectName)</title>
102 @ <link>%s(g.zBaseURL)</link>
103 @ <description>%h(zProjectDescr)</description>
104 @ <pubDate>%s(zPubDate)</pubDate>
@@ -130,11 +130,11 @@
130 @ <item>
131 @ <title>%s(zPrefix)%h(zCom)</title>
132 @ <link>%s(g.zBaseURL)/info/%s(zId)</link>
133 @ <description>%s(zPrefix)%h(zCom)</description>
134 @ <pubDate>%s(zDate)</pubDate>
135 @ <author>%h(zAuthor)</author>
136 @ <guid>%s(g.zBaseURL)/info/%s(zId)</guid>
137 @ </item>
138 free(zDate);
139 nLine++;
140 }
141
--- src/rss.c
+++ src/rss.c
@@ -44,39 +44,39 @@
44 @ FROM event, blob
45 @ WHERE blob.rid=event.objid
46 ;
47
48 login_check_credentials();
49 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
50 return;
51 }
52
53 blob_zero(&bSQL);
54 blob_append( &bSQL, zSQL1, -1 );
55
56 if( zType[0]!='a' ){
57 if( zType[0]=='c' && !g.perm.Read ) zType = "x";
58 if( zType[0]=='w' && !g.perm.RdWiki ) zType = "x";
59 if( zType[0]=='t' && !g.perm.RdTkt ) zType = "x";
60 blob_appendf(&bSQL, " AND event.type=%Q", zType);
61 }else{
62 if( !g.perm.Read ){
63 if( g.perm.RdTkt && g.perm.RdWiki ){
64 blob_append(&bSQL, " AND event.type!='ci'", -1);
65 }else if( g.perm.RdTkt ){
66 blob_append(&bSQL, " AND event.type=='t'", -1);
67 }else{
68 blob_append(&bSQL, " AND event.type=='w'", -1);
69 }
70 }else if( !g.perm.RdWiki ){
71 if( g.perm.RdTkt ){
72 blob_append(&bSQL, " AND event.type!='w'", -1);
73 }else{
74 blob_append(&bSQL, " AND event.type=='ci'", -1);
75 }
76 }else if( !g.perm.RdTkt ){
77 assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki );
78 blob_append(&bSQL, " AND event.type!='t'", -1);
79 }
80 }
81
82 blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
@@ -94,11 +94,11 @@
94 }
95
96 zPubDate = cgi_rfc822_datestamp(time(NULL));
97
98 @ <?xml version="1.0"?>
99 @ <rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
100 @ <channel>
101 @ <title>%h(zProjectName)</title>
102 @ <link>%s(g.zBaseURL)</link>
103 @ <description>%h(zProjectDescr)</description>
104 @ <pubDate>%s(zPubDate)</pubDate>
@@ -130,11 +130,11 @@
130 @ <item>
131 @ <title>%s(zPrefix)%h(zCom)</title>
132 @ <link>%s(g.zBaseURL)/info/%s(zId)</link>
133 @ <description>%s(zPrefix)%h(zCom)</description>
134 @ <pubDate>%s(zDate)</pubDate>
135 @ <dc:creator>%h(zAuthor)</dc:creator>
136 @ <guid>%s(g.zBaseURL)/info/%s(zId)</guid>
137 @ </item>
138 free(zDate);
139 nLine++;
140 }
141
+25 -17
--- src/setup.c
+++ src/setup.c
@@ -52,11 +52,11 @@
5252
/*
5353
** WEBPAGE: /setup
5454
*/
5555
void setup_page(void){
5656
login_check_credentials();
57
- if( !g.okSetup ){
57
+ if( !g.perm.Setup ){
5858
login_needed();
5959
}
6060
6161
style_header("Server Administration");
6262
@ <table border="0" cellspacing="7">
@@ -106,11 +106,11 @@
106106
*/
107107
void setup_ulist(void){
108108
Stmt s;
109109
110110
login_check_credentials();
111
- if( !g.okAdmin ){
111
+ if( !g.perm.Admin ){
112112
login_needed();
113113
return;
114114
}
115115
116116
style_submenu_element("Add", "Add User", "setup_uedit");
@@ -127,15 +127,15 @@
127127
db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
128128
while( db_step(&s)==SQLITE_ROW ){
129129
const char *zCap = db_column_text(&s, 2);
130130
@ <tr>
131131
@ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;">
132
- if( g.okAdmin && (zCap[0]!='s' || g.okSetup) ){
132
+ if( g.perm.Admin && (zCap[0]!='s' || g.perm.Setup) ){
133133
@ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
134134
}
135135
@ %h(db_column_text(&s,1))
136
- if( g.okAdmin ){
136
+ if( g.perm.Admin ){
137137
@ </a>
138138
}
139139
@ </td>
140140
@ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td>
141141
@ <td class="usetupListCon" style="text-align: left;">%s(db_column_text(&s,3))</td>
@@ -259,18 +259,18 @@
259259
/* user doing the editing is ADMIN. Disallow editing */
260260
261261
/* Must have ADMIN privleges to access this page
262262
*/
263263
login_check_credentials();
264
- if( !g.okAdmin ){ login_needed(); return; }
264
+ if( !g.perm.Admin ){ login_needed(); return; }
265265
266266
/* Check to see if an ADMIN user is trying to edit a SETUP account.
267267
** Don't allow that.
268268
*/
269269
zId = PD("id", "0");
270270
uid = atoi(zId);
271
- if( zId && !g.okSetup && uid>0 ){
271
+ if( zId && !g.perm.Setup && uid>0 ){
272272
char *zOldCaps;
273273
zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
274274
higherUser = zOldCaps && strchr(zOldCaps,'s');
275275
}
276276
@@ -296,11 +296,11 @@
296296
int ak = P("ak")!=0;
297297
int an = P("an")!=0;
298298
int ao = P("ao")!=0;
299299
int ap = P("ap")!=0;
300300
int ar = P("ar")!=0;
301
- int as = g.okSetup && P("as")!=0;
301
+ int as = g.perm.Setup && P("as")!=0;
302302
int aw = P("aw")!=0;
303303
int ac = P("ac")!=0;
304304
int af = P("af")!=0;
305305
int am = P("am")!=0;
306306
int ah = P("ah")!=0;
@@ -335,10 +335,18 @@
335335
if( az ){ zCap[i++] = 'z'; }
336336
337337
zCap[i] = 0;
338338
zPw = P("pw");
339339
zLogin = P("login");
340
+ if( strlen(zLogin)==0 ){
341
+ style_header("User Creation Error");
342
+ @ <span class="loginError">Empty login not allowed.</span>
343
+ @
344
+ @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
345
+ style_footer();
346
+ return;
347
+ }
340348
if( isValidPwString(zPw) ){
341349
zPw = sha1_shared_secret(zPw, zLogin, 0);
342350
}else{
343351
zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid);
344352
}
@@ -505,11 +513,11 @@
505513
@ </tr>
506514
@ <tr>
507515
@ <td class="usetupEditLabel">Capabilities:</td>
508516
@ <td>
509517
#define B(x) inherit[x]
510
- if( g.okSetup ){
518
+ if( g.perm.Setup ){
511519
@ <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br />
512520
}
513521
@ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br />
514522
@ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
515523
@ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
@@ -808,11 +816,11 @@
808816
/*
809817
** WEBPAGE: setup_access
810818
*/
811819
void setup_access(void){
812820
login_check_credentials();
813
- if( !g.okSetup ){
821
+ if( !g.perm.Setup ){
814822
login_needed();
815823
}
816824
817825
style_header("Access Control Settings");
818826
db_begin_transaction();
@@ -910,11 +918,11 @@
910918
const char *zLogin = PD("login", "");
911919
const char *zPw = PD("pw", "");
912920
const char *zNewName = PD("newname", "New Login Group");
913921
914922
login_check_credentials();
915
- if( !g.okSetup ){
923
+ if( !g.perm.Setup ){
916924
login_needed();
917925
}
918926
file_canonical_name(g.zRepositoryName, &fullName);
919927
zSelfRepo = mprintf(blob_str(&fullName));
920928
blob_reset(&fullName);
@@ -996,11 +1004,11 @@
9961004
/*
9971005
** WEBPAGE: setup_timeline
9981006
*/
9991007
void setup_timeline(void){
10001008
login_check_credentials();
1001
- if( !g.okSetup ){
1009
+ if( !g.perm.Setup ){
10021010
login_needed();
10031011
}
10041012
10051013
style_header("Timeline Display Preferences");
10061014
db_begin_transaction();
@@ -1045,11 +1053,11 @@
10451053
*/
10461054
void setup_settings(void){
10471055
struct stControlSettings const *pSet;
10481056
10491057
login_check_credentials();
1050
- if( !g.okSetup ){
1058
+ if( !g.perm.Setup ){
10511059
login_needed();
10521060
}
10531061
10541062
style_header("Settings");
10551063
db_open_local();
@@ -1099,11 +1107,11 @@
10991107
/*
11001108
** WEBPAGE: setup_config
11011109
*/
11021110
void setup_config(void){
11031111
login_check_credentials();
1104
- if( !g.okSetup ){
1112
+ if( !g.perm.Setup ){
11051113
login_needed();
11061114
}
11071115
11081116
style_header("WWW Configuration");
11091117
db_begin_transaction();
@@ -1163,11 +1171,11 @@
11631171
/*
11641172
** WEBPAGE: setup_editcss
11651173
*/
11661174
void setup_editcss(void){
11671175
login_check_credentials();
1168
- if( !g.okSetup ){
1176
+ if( !g.perm.Setup ){
11691177
login_needed();
11701178
}
11711179
db_begin_transaction();
11721180
if( P("clear")!=0 ){
11731181
db_multi_exec("DELETE FROM config WHERE name='css'");
@@ -1207,11 +1215,11 @@
12071215
/*
12081216
** WEBPAGE: setup_header
12091217
*/
12101218
void setup_header(void){
12111219
login_check_credentials();
1212
- if( !g.okSetup ){
1220
+ if( !g.perm.Setup ){
12131221
login_needed();
12141222
}
12151223
db_begin_transaction();
12161224
if( P("clear")!=0 ){
12171225
db_multi_exec("DELETE FROM config WHERE name='header'");
@@ -1245,11 +1253,11 @@
12451253
/*
12461254
** WEBPAGE: setup_footer
12471255
*/
12481256
void setup_footer(void){
12491257
login_check_credentials();
1250
- if( !g.okSetup ){
1258
+ if( !g.perm.Setup ){
12511259
login_needed();
12521260
}
12531261
db_begin_transaction();
12541262
if( P("clear")!=0 ){
12551263
db_multi_exec("DELETE FROM config WHERE name='footer'");
@@ -1288,11 +1296,11 @@
12881296
int szImg = atoi(PD("im:bytes","0"));
12891297
if( szImg>0 ){
12901298
zMime = PD("im:mimetype","image/gif");
12911299
}
12921300
login_check_credentials();
1293
- if( !g.okSetup ){
1301
+ if( !g.perm.Setup ){
12941302
login_needed();
12951303
}
12961304
db_begin_transaction();
12971305
if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
12981306
Blob img;
12991307
--- src/setup.c
+++ src/setup.c
@@ -52,11 +52,11 @@
52 /*
53 ** WEBPAGE: /setup
54 */
55 void setup_page(void){
56 login_check_credentials();
57 if( !g.okSetup ){
58 login_needed();
59 }
60
61 style_header("Server Administration");
62 @ <table border="0" cellspacing="7">
@@ -106,11 +106,11 @@
106 */
107 void setup_ulist(void){
108 Stmt s;
109
110 login_check_credentials();
111 if( !g.okAdmin ){
112 login_needed();
113 return;
114 }
115
116 style_submenu_element("Add", "Add User", "setup_uedit");
@@ -127,15 +127,15 @@
127 db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
128 while( db_step(&s)==SQLITE_ROW ){
129 const char *zCap = db_column_text(&s, 2);
130 @ <tr>
131 @ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;">
132 if( g.okAdmin && (zCap[0]!='s' || g.okSetup) ){
133 @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
134 }
135 @ %h(db_column_text(&s,1))
136 if( g.okAdmin ){
137 @ </a>
138 }
139 @ </td>
140 @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td>
141 @ <td class="usetupListCon" style="text-align: left;">%s(db_column_text(&s,3))</td>
@@ -259,18 +259,18 @@
259 /* user doing the editing is ADMIN. Disallow editing */
260
261 /* Must have ADMIN privleges to access this page
262 */
263 login_check_credentials();
264 if( !g.okAdmin ){ login_needed(); return; }
265
266 /* Check to see if an ADMIN user is trying to edit a SETUP account.
267 ** Don't allow that.
268 */
269 zId = PD("id", "0");
270 uid = atoi(zId);
271 if( zId && !g.okSetup && uid>0 ){
272 char *zOldCaps;
273 zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
274 higherUser = zOldCaps && strchr(zOldCaps,'s');
275 }
276
@@ -296,11 +296,11 @@
296 int ak = P("ak")!=0;
297 int an = P("an")!=0;
298 int ao = P("ao")!=0;
299 int ap = P("ap")!=0;
300 int ar = P("ar")!=0;
301 int as = g.okSetup && P("as")!=0;
302 int aw = P("aw")!=0;
303 int ac = P("ac")!=0;
304 int af = P("af")!=0;
305 int am = P("am")!=0;
306 int ah = P("ah")!=0;
@@ -335,10 +335,18 @@
335 if( az ){ zCap[i++] = 'z'; }
336
337 zCap[i] = 0;
338 zPw = P("pw");
339 zLogin = P("login");
 
 
 
 
 
 
 
 
340 if( isValidPwString(zPw) ){
341 zPw = sha1_shared_secret(zPw, zLogin, 0);
342 }else{
343 zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid);
344 }
@@ -505,11 +513,11 @@
505 @ </tr>
506 @ <tr>
507 @ <td class="usetupEditLabel">Capabilities:</td>
508 @ <td>
509 #define B(x) inherit[x]
510 if( g.okSetup ){
511 @ <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br />
512 }
513 @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br />
514 @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
515 @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
@@ -808,11 +816,11 @@
808 /*
809 ** WEBPAGE: setup_access
810 */
811 void setup_access(void){
812 login_check_credentials();
813 if( !g.okSetup ){
814 login_needed();
815 }
816
817 style_header("Access Control Settings");
818 db_begin_transaction();
@@ -910,11 +918,11 @@
910 const char *zLogin = PD("login", "");
911 const char *zPw = PD("pw", "");
912 const char *zNewName = PD("newname", "New Login Group");
913
914 login_check_credentials();
915 if( !g.okSetup ){
916 login_needed();
917 }
918 file_canonical_name(g.zRepositoryName, &fullName);
919 zSelfRepo = mprintf(blob_str(&fullName));
920 blob_reset(&fullName);
@@ -996,11 +1004,11 @@
996 /*
997 ** WEBPAGE: setup_timeline
998 */
999 void setup_timeline(void){
1000 login_check_credentials();
1001 if( !g.okSetup ){
1002 login_needed();
1003 }
1004
1005 style_header("Timeline Display Preferences");
1006 db_begin_transaction();
@@ -1045,11 +1053,11 @@
1045 */
1046 void setup_settings(void){
1047 struct stControlSettings const *pSet;
1048
1049 login_check_credentials();
1050 if( !g.okSetup ){
1051 login_needed();
1052 }
1053
1054 style_header("Settings");
1055 db_open_local();
@@ -1099,11 +1107,11 @@
1099 /*
1100 ** WEBPAGE: setup_config
1101 */
1102 void setup_config(void){
1103 login_check_credentials();
1104 if( !g.okSetup ){
1105 login_needed();
1106 }
1107
1108 style_header("WWW Configuration");
1109 db_begin_transaction();
@@ -1163,11 +1171,11 @@
1163 /*
1164 ** WEBPAGE: setup_editcss
1165 */
1166 void setup_editcss(void){
1167 login_check_credentials();
1168 if( !g.okSetup ){
1169 login_needed();
1170 }
1171 db_begin_transaction();
1172 if( P("clear")!=0 ){
1173 db_multi_exec("DELETE FROM config WHERE name='css'");
@@ -1207,11 +1215,11 @@
1207 /*
1208 ** WEBPAGE: setup_header
1209 */
1210 void setup_header(void){
1211 login_check_credentials();
1212 if( !g.okSetup ){
1213 login_needed();
1214 }
1215 db_begin_transaction();
1216 if( P("clear")!=0 ){
1217 db_multi_exec("DELETE FROM config WHERE name='header'");
@@ -1245,11 +1253,11 @@
1245 /*
1246 ** WEBPAGE: setup_footer
1247 */
1248 void setup_footer(void){
1249 login_check_credentials();
1250 if( !g.okSetup ){
1251 login_needed();
1252 }
1253 db_begin_transaction();
1254 if( P("clear")!=0 ){
1255 db_multi_exec("DELETE FROM config WHERE name='footer'");
@@ -1288,11 +1296,11 @@
1288 int szImg = atoi(PD("im:bytes","0"));
1289 if( szImg>0 ){
1290 zMime = PD("im:mimetype","image/gif");
1291 }
1292 login_check_credentials();
1293 if( !g.okSetup ){
1294 login_needed();
1295 }
1296 db_begin_transaction();
1297 if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
1298 Blob img;
1299
--- src/setup.c
+++ src/setup.c
@@ -52,11 +52,11 @@
52 /*
53 ** WEBPAGE: /setup
54 */
55 void setup_page(void){
56 login_check_credentials();
57 if( !g.perm.Setup ){
58 login_needed();
59 }
60
61 style_header("Server Administration");
62 @ <table border="0" cellspacing="7">
@@ -106,11 +106,11 @@
106 */
107 void setup_ulist(void){
108 Stmt s;
109
110 login_check_credentials();
111 if( !g.perm.Admin ){
112 login_needed();
113 return;
114 }
115
116 style_submenu_element("Add", "Add User", "setup_uedit");
@@ -127,15 +127,15 @@
127 db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
128 while( db_step(&s)==SQLITE_ROW ){
129 const char *zCap = db_column_text(&s, 2);
130 @ <tr>
131 @ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;">
132 if( g.perm.Admin && (zCap[0]!='s' || g.perm.Setup) ){
133 @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
134 }
135 @ %h(db_column_text(&s,1))
136 if( g.perm.Admin ){
137 @ </a>
138 }
139 @ </td>
140 @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td>
141 @ <td class="usetupListCon" style="text-align: left;">%s(db_column_text(&s,3))</td>
@@ -259,18 +259,18 @@
259 /* user doing the editing is ADMIN. Disallow editing */
260
261 /* Must have ADMIN privleges to access this page
262 */
263 login_check_credentials();
264 if( !g.perm.Admin ){ login_needed(); return; }
265
266 /* Check to see if an ADMIN user is trying to edit a SETUP account.
267 ** Don't allow that.
268 */
269 zId = PD("id", "0");
270 uid = atoi(zId);
271 if( zId && !g.perm.Setup && uid>0 ){
272 char *zOldCaps;
273 zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
274 higherUser = zOldCaps && strchr(zOldCaps,'s');
275 }
276
@@ -296,11 +296,11 @@
296 int ak = P("ak")!=0;
297 int an = P("an")!=0;
298 int ao = P("ao")!=0;
299 int ap = P("ap")!=0;
300 int ar = P("ar")!=0;
301 int as = g.perm.Setup && P("as")!=0;
302 int aw = P("aw")!=0;
303 int ac = P("ac")!=0;
304 int af = P("af")!=0;
305 int am = P("am")!=0;
306 int ah = P("ah")!=0;
@@ -335,10 +335,18 @@
335 if( az ){ zCap[i++] = 'z'; }
336
337 zCap[i] = 0;
338 zPw = P("pw");
339 zLogin = P("login");
340 if( strlen(zLogin)==0 ){
341 style_header("User Creation Error");
342 @ <span class="loginError">Empty login not allowed.</span>
343 @
344 @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
345 style_footer();
346 return;
347 }
348 if( isValidPwString(zPw) ){
349 zPw = sha1_shared_secret(zPw, zLogin, 0);
350 }else{
351 zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid);
352 }
@@ -505,11 +513,11 @@
513 @ </tr>
514 @ <tr>
515 @ <td class="usetupEditLabel">Capabilities:</td>
516 @ <td>
517 #define B(x) inherit[x]
518 if( g.perm.Setup ){
519 @ <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br />
520 }
521 @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br />
522 @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
523 @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
@@ -808,11 +816,11 @@
816 /*
817 ** WEBPAGE: setup_access
818 */
819 void setup_access(void){
820 login_check_credentials();
821 if( !g.perm.Setup ){
822 login_needed();
823 }
824
825 style_header("Access Control Settings");
826 db_begin_transaction();
@@ -910,11 +918,11 @@
918 const char *zLogin = PD("login", "");
919 const char *zPw = PD("pw", "");
920 const char *zNewName = PD("newname", "New Login Group");
921
922 login_check_credentials();
923 if( !g.perm.Setup ){
924 login_needed();
925 }
926 file_canonical_name(g.zRepositoryName, &fullName);
927 zSelfRepo = mprintf(blob_str(&fullName));
928 blob_reset(&fullName);
@@ -996,11 +1004,11 @@
1004 /*
1005 ** WEBPAGE: setup_timeline
1006 */
1007 void setup_timeline(void){
1008 login_check_credentials();
1009 if( !g.perm.Setup ){
1010 login_needed();
1011 }
1012
1013 style_header("Timeline Display Preferences");
1014 db_begin_transaction();
@@ -1045,11 +1053,11 @@
1053 */
1054 void setup_settings(void){
1055 struct stControlSettings const *pSet;
1056
1057 login_check_credentials();
1058 if( !g.perm.Setup ){
1059 login_needed();
1060 }
1061
1062 style_header("Settings");
1063 db_open_local();
@@ -1099,11 +1107,11 @@
1107 /*
1108 ** WEBPAGE: setup_config
1109 */
1110 void setup_config(void){
1111 login_check_credentials();
1112 if( !g.perm.Setup ){
1113 login_needed();
1114 }
1115
1116 style_header("WWW Configuration");
1117 db_begin_transaction();
@@ -1163,11 +1171,11 @@
1171 /*
1172 ** WEBPAGE: setup_editcss
1173 */
1174 void setup_editcss(void){
1175 login_check_credentials();
1176 if( !g.perm.Setup ){
1177 login_needed();
1178 }
1179 db_begin_transaction();
1180 if( P("clear")!=0 ){
1181 db_multi_exec("DELETE FROM config WHERE name='css'");
@@ -1207,11 +1215,11 @@
1215 /*
1216 ** WEBPAGE: setup_header
1217 */
1218 void setup_header(void){
1219 login_check_credentials();
1220 if( !g.perm.Setup ){
1221 login_needed();
1222 }
1223 db_begin_transaction();
1224 if( P("clear")!=0 ){
1225 db_multi_exec("DELETE FROM config WHERE name='header'");
@@ -1245,11 +1253,11 @@
1253 /*
1254 ** WEBPAGE: setup_footer
1255 */
1256 void setup_footer(void){
1257 login_check_credentials();
1258 if( !g.perm.Setup ){
1259 login_needed();
1260 }
1261 db_begin_transaction();
1262 if( P("clear")!=0 ){
1263 db_multi_exec("DELETE FROM config WHERE name='footer'");
@@ -1288,11 +1296,11 @@
1296 int szImg = atoi(PD("im:bytes","0"));
1297 if( szImg>0 ){
1298 zMime = PD("im:mimetype","image/gif");
1299 }
1300 login_check_credentials();
1301 if( !g.perm.Setup ){
1302 login_needed();
1303 }
1304 db_begin_transaction();
1305 if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
1306 Blob img;
1307
+1 -1
--- src/sha1.c
+++ src/sha1.c
@@ -281,11 +281,11 @@
281281
FILE *in;
282282
SHA1Context ctx;
283283
unsigned char zResult[20];
284284
char zBuf[10240];
285285
286
- if( file_islink(zFilename) ){
286
+ if( file_wd_islink(zFilename) ){
287287
/* Instead of file content, return sha1 of link destination path */
288288
Blob destinationPath;
289289
int rc;
290290
291291
blob_read_link(&destinationPath, zFilename);
292292
--- src/sha1.c
+++ src/sha1.c
@@ -281,11 +281,11 @@
281 FILE *in;
282 SHA1Context ctx;
283 unsigned char zResult[20];
284 char zBuf[10240];
285
286 if( file_islink(zFilename) ){
287 /* Instead of file content, return sha1 of link destination path */
288 Blob destinationPath;
289 int rc;
290
291 blob_read_link(&destinationPath, zFilename);
292
--- src/sha1.c
+++ src/sha1.c
@@ -281,11 +281,11 @@
281 FILE *in;
282 SHA1Context ctx;
283 unsigned char zResult[20];
284 char zBuf[10240];
285
286 if( file_wd_islink(zFilename) ){
287 /* Instead of file content, return sha1 of link destination path */
288 Blob destinationPath;
289 int rc;
290
291 blob_read_link(&destinationPath, zFilename);
292
+3 -3
--- src/shun.c
+++ src/shun.c
@@ -44,11 +44,11 @@
4444
const char *zUuid = P("uuid");
4545
int nUuid;
4646
char zCanonical[UUID_SIZE+1];
4747
4848
login_check_credentials();
49
- if( !g.okAdmin ){
49
+ if( !g.perm.Admin ){
5050
login_needed();
5151
}
5252
if( P("rebuild") ){
5353
db_close(1);
5454
db_open_repository(g.zRepositoryName);
@@ -219,11 +219,11 @@
219219
int ofst = atoi(PD("ofst","0"));
220220
int cnt;
221221
Stmt q;
222222
223223
login_check_credentials();
224
- if( !g.okAdmin ){
224
+ if( !g.perm.Admin ){
225225
login_needed();
226226
}
227227
style_header("Content Sources");
228228
if( ofst>0 ){
229229
style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
@@ -282,11 +282,11 @@
282282
void rcvfrom_page(void){
283283
int rcvid = atoi(PD("rcvid","0"));
284284
Stmt q;
285285
286286
login_check_credentials();
287
- if( !g.okAdmin ){
287
+ if( !g.perm.Admin ){
288288
login_needed();
289289
}
290290
style_header("Content Source %d", rcvid);
291291
db_prepare(&q,
292292
"SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
293293
--- src/shun.c
+++ src/shun.c
@@ -44,11 +44,11 @@
44 const char *zUuid = P("uuid");
45 int nUuid;
46 char zCanonical[UUID_SIZE+1];
47
48 login_check_credentials();
49 if( !g.okAdmin ){
50 login_needed();
51 }
52 if( P("rebuild") ){
53 db_close(1);
54 db_open_repository(g.zRepositoryName);
@@ -219,11 +219,11 @@
219 int ofst = atoi(PD("ofst","0"));
220 int cnt;
221 Stmt q;
222
223 login_check_credentials();
224 if( !g.okAdmin ){
225 login_needed();
226 }
227 style_header("Content Sources");
228 if( ofst>0 ){
229 style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
@@ -282,11 +282,11 @@
282 void rcvfrom_page(void){
283 int rcvid = atoi(PD("rcvid","0"));
284 Stmt q;
285
286 login_check_credentials();
287 if( !g.okAdmin ){
288 login_needed();
289 }
290 style_header("Content Source %d", rcvid);
291 db_prepare(&q,
292 "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
293
--- src/shun.c
+++ src/shun.c
@@ -44,11 +44,11 @@
44 const char *zUuid = P("uuid");
45 int nUuid;
46 char zCanonical[UUID_SIZE+1];
47
48 login_check_credentials();
49 if( !g.perm.Admin ){
50 login_needed();
51 }
52 if( P("rebuild") ){
53 db_close(1);
54 db_open_repository(g.zRepositoryName);
@@ -219,11 +219,11 @@
219 int ofst = atoi(PD("ofst","0"));
220 int cnt;
221 Stmt q;
222
223 login_check_credentials();
224 if( !g.perm.Admin ){
225 login_needed();
226 }
227 style_header("Content Sources");
228 if( ofst>0 ){
229 style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
@@ -282,11 +282,11 @@
282 void rcvfrom_page(void){
283 int rcvid = atoi(PD("rcvid","0"));
284 Stmt q;
285
286 login_check_credentials();
287 if( !g.perm.Admin ){
288 login_needed();
289 }
290 style_header("Content Source %d", rcvid);
291 db_prepare(&q,
292 "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
293
+1 -1
--- src/skins.c
+++ src/skins.c
@@ -1025,11 +1025,11 @@
10251025
const char *zCurrent; /* Current skin */
10261026
int i; /* Loop counter */
10271027
Stmt q;
10281028
10291029
login_check_credentials();
1030
- if( !g.okSetup ){
1030
+ if( !g.perm.Setup ){
10311031
login_needed();
10321032
}
10331033
db_begin_transaction();
10341034
10351035
/* Process requests to delete a user-defined skin */
10361036
--- src/skins.c
+++ src/skins.c
@@ -1025,11 +1025,11 @@
1025 const char *zCurrent; /* Current skin */
1026 int i; /* Loop counter */
1027 Stmt q;
1028
1029 login_check_credentials();
1030 if( !g.okSetup ){
1031 login_needed();
1032 }
1033 db_begin_transaction();
1034
1035 /* Process requests to delete a user-defined skin */
1036
--- src/skins.c
+++ src/skins.c
@@ -1025,11 +1025,11 @@
1025 const char *zCurrent; /* Current skin */
1026 int i; /* Loop counter */
1027 Stmt q;
1028
1029 login_check_credentials();
1030 if( !g.perm.Setup ){
1031 login_needed();
1032 }
1033 db_begin_transaction();
1034
1035 /* Process requests to delete a user-defined skin */
1036
+1861 -1534
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -656,11 +656,11 @@
656656
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657657
** [sqlite_version()] and [sqlite_source_id()].
658658
*/
659659
#define SQLITE_VERSION "3.7.8"
660660
#define SQLITE_VERSION_NUMBER 3007008
661
-#define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
661
+#define SQLITE_SOURCE_ID "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"
662662
663663
/*
664664
** CAPI3REF: Run-Time Library Version Numbers
665665
** KEYWORDS: sqlite3_version, sqlite3_sourceid
666666
**
@@ -7632,18 +7632,10 @@
76327632
*/
76337633
#ifndef SQLITE_TEMP_STORE
76347634
# define SQLITE_TEMP_STORE 1
76357635
#endif
76367636
7637
-/*
7638
-** If all temporary storage is in-memory, then omit the external merge-sort
7639
-** logic since it is superfluous.
7640
-*/
7641
-#if SQLITE_TEMP_STORE==3 && !defined(SQLITE_OMIT_MERGE_SORT)
7642
-# define SQLITE_OMIT_MERGE_SORT
7643
-#endif
7644
-
76457637
/*
76467638
** GCC does not define the offsetof() macro so we'll have to do it
76477639
** ourselves.
76487640
*/
76497641
#ifndef offsetof
@@ -7982,11 +7974,10 @@
79827974
#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
79837975
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
79847976
#define BTREE_MEMORY 4 /* This is an in-memory DB */
79857977
#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
79867978
#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
7987
-#define BTREE_SORTER 32 /* Used as accumulator in external merge sort */
79887979
79897980
SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
79907981
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
79917982
SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
79927983
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
@@ -8383,106 +8374,109 @@
83838374
#define OP_Jump 25
83848375
#define OP_And 69 /* same as TK_AND */
83858376
#define OP_Or 68 /* same as TK_OR */
83868377
#define OP_Not 19 /* same as TK_NOT */
83878378
#define OP_BitNot 93 /* same as TK_BITNOT */
8388
-#define OP_If 26
8389
-#define OP_IfNot 27
8379
+#define OP_Once 26
8380
+#define OP_If 27
8381
+#define OP_IfNot 28
83908382
#define OP_IsNull 73 /* same as TK_ISNULL */
83918383
#define OP_NotNull 74 /* same as TK_NOTNULL */
8392
-#define OP_Column 28
8393
-#define OP_Affinity 29
8394
-#define OP_MakeRecord 30
8395
-#define OP_Count 31
8396
-#define OP_Savepoint 32
8397
-#define OP_AutoCommit 33
8398
-#define OP_Transaction 34
8399
-#define OP_ReadCookie 35
8400
-#define OP_SetCookie 36
8401
-#define OP_VerifyCookie 37
8402
-#define OP_OpenRead 38
8403
-#define OP_OpenWrite 39
8404
-#define OP_OpenSorter 40
8384
+#define OP_Column 29
8385
+#define OP_Affinity 30
8386
+#define OP_MakeRecord 31
8387
+#define OP_Count 32
8388
+#define OP_Savepoint 33
8389
+#define OP_AutoCommit 34
8390
+#define OP_Transaction 35
8391
+#define OP_ReadCookie 36
8392
+#define OP_SetCookie 37
8393
+#define OP_VerifyCookie 38
8394
+#define OP_OpenRead 39
8395
+#define OP_OpenWrite 40
84058396
#define OP_OpenAutoindex 41
84068397
#define OP_OpenEphemeral 42
8407
-#define OP_OpenPseudo 43
8408
-#define OP_Close 44
8409
-#define OP_SeekLt 45
8410
-#define OP_SeekLe 46
8411
-#define OP_SeekGe 47
8412
-#define OP_SeekGt 48
8413
-#define OP_Seek 49
8414
-#define OP_NotFound 50
8415
-#define OP_Found 51
8416
-#define OP_IsUnique 52
8417
-#define OP_NotExists 53
8418
-#define OP_Sequence 54
8419
-#define OP_NewRowid 55
8420
-#define OP_Insert 56
8421
-#define OP_InsertInt 57
8422
-#define OP_Delete 58
8423
-#define OP_ResetCount 59
8424
-#define OP_RowKey 60
8425
-#define OP_RowData 61
8426
-#define OP_Rowid 62
8427
-#define OP_NullRow 63
8428
-#define OP_Last 64
8429
-#define OP_Sort 65
8430
-#define OP_Rewind 66
8431
-#define OP_Prev 67
8432
-#define OP_Next 70
8433
-#define OP_IdxInsert 71
8434
-#define OP_IdxDelete 72
8435
-#define OP_IdxRowid 81
8436
-#define OP_IdxLT 92
8437
-#define OP_IdxGE 95
8438
-#define OP_Destroy 96
8439
-#define OP_Clear 97
8440
-#define OP_CreateIndex 98
8441
-#define OP_CreateTable 99
8442
-#define OP_ParseSchema 100
8443
-#define OP_LoadAnalysis 101
8444
-#define OP_DropTable 102
8445
-#define OP_DropIndex 103
8446
-#define OP_DropTrigger 104
8447
-#define OP_IntegrityCk 105
8448
-#define OP_RowSetAdd 106
8449
-#define OP_RowSetRead 107
8450
-#define OP_RowSetTest 108
8451
-#define OP_Program 109
8452
-#define OP_Param 110
8453
-#define OP_FkCounter 111
8454
-#define OP_FkIfZero 112
8455
-#define OP_MemMax 113
8456
-#define OP_IfPos 114
8457
-#define OP_IfNeg 115
8458
-#define OP_IfZero 116
8459
-#define OP_AggStep 117
8460
-#define OP_AggFinal 118
8461
-#define OP_Checkpoint 119
8462
-#define OP_JournalMode 120
8463
-#define OP_Vacuum 121
8464
-#define OP_IncrVacuum 122
8465
-#define OP_Expire 123
8466
-#define OP_TableLock 124
8467
-#define OP_VBegin 125
8468
-#define OP_VCreate 126
8469
-#define OP_VDestroy 127
8470
-#define OP_VOpen 128
8471
-#define OP_VFilter 129
8472
-#define OP_VColumn 131
8473
-#define OP_VNext 132
8474
-#define OP_VRename 133
8475
-#define OP_VUpdate 134
8476
-#define OP_Pagecount 135
8477
-#define OP_MaxPgcnt 136
8478
-#define OP_Trace 137
8479
-#define OP_Noop 138
8480
-#define OP_Explain 139
8481
-
8482
-/* The following opcode values are never used */
8483
-#define OP_NotUsed_140 140
8398
+#define OP_SorterOpen 43
8399
+#define OP_OpenPseudo 44
8400
+#define OP_Close 45
8401
+#define OP_SeekLt 46
8402
+#define OP_SeekLe 47
8403
+#define OP_SeekGe 48
8404
+#define OP_SeekGt 49
8405
+#define OP_Seek 50
8406
+#define OP_NotFound 51
8407
+#define OP_Found 52
8408
+#define OP_IsUnique 53
8409
+#define OP_NotExists 54
8410
+#define OP_Sequence 55
8411
+#define OP_NewRowid 56
8412
+#define OP_Insert 57
8413
+#define OP_InsertInt 58
8414
+#define OP_Delete 59
8415
+#define OP_ResetCount 60
8416
+#define OP_SorterCompare 61
8417
+#define OP_SorterData 62
8418
+#define OP_RowKey 63
8419
+#define OP_RowData 64
8420
+#define OP_Rowid 65
8421
+#define OP_NullRow 66
8422
+#define OP_Last 67
8423
+#define OP_SorterSort 70
8424
+#define OP_Sort 71
8425
+#define OP_Rewind 72
8426
+#define OP_SorterNext 81
8427
+#define OP_Prev 92
8428
+#define OP_Next 95
8429
+#define OP_SorterInsert 96
8430
+#define OP_IdxInsert 97
8431
+#define OP_IdxDelete 98
8432
+#define OP_IdxRowid 99
8433
+#define OP_IdxLT 100
8434
+#define OP_IdxGE 101
8435
+#define OP_Destroy 102
8436
+#define OP_Clear 103
8437
+#define OP_CreateIndex 104
8438
+#define OP_CreateTable 105
8439
+#define OP_ParseSchema 106
8440
+#define OP_LoadAnalysis 107
8441
+#define OP_DropTable 108
8442
+#define OP_DropIndex 109
8443
+#define OP_DropTrigger 110
8444
+#define OP_IntegrityCk 111
8445
+#define OP_RowSetAdd 112
8446
+#define OP_RowSetRead 113
8447
+#define OP_RowSetTest 114
8448
+#define OP_Program 115
8449
+#define OP_Param 116
8450
+#define OP_FkCounter 117
8451
+#define OP_FkIfZero 118
8452
+#define OP_MemMax 119
8453
+#define OP_IfPos 120
8454
+#define OP_IfNeg 121
8455
+#define OP_IfZero 122
8456
+#define OP_AggStep 123
8457
+#define OP_AggFinal 124
8458
+#define OP_Checkpoint 125
8459
+#define OP_JournalMode 126
8460
+#define OP_Vacuum 127
8461
+#define OP_IncrVacuum 128
8462
+#define OP_Expire 129
8463
+#define OP_TableLock 131
8464
+#define OP_VBegin 132
8465
+#define OP_VCreate 133
8466
+#define OP_VDestroy 134
8467
+#define OP_VOpen 135
8468
+#define OP_VFilter 136
8469
+#define OP_VColumn 137
8470
+#define OP_VNext 138
8471
+#define OP_VRename 139
8472
+#define OP_VUpdate 140
8473
+#define OP_Pagecount 146
8474
+#define OP_MaxPgcnt 147
8475
+#define OP_Trace 148
8476
+#define OP_Noop 149
8477
+#define OP_Explain 150
84848478
84858479
84868480
/* Properties such as "out2" or "jump" that are specified in
84878481
** comments following the "case" for each opcode in the vdbe.c
84888482
** are encoded into bitvectors as follows:
@@ -8496,26 +8490,26 @@
84968490
#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
84978491
#define OPFLG_INITIALIZER {\
84988492
/* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
84998493
/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
85008494
/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
8501
-/* 24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
8502
-/* 32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
8503
-/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,\
8504
-/* 48 */ 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02,\
8505
-/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,\
8506
-/* 64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x01, 0x08,\
8507
-/* 72 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8508
-/* 80 */ 0x15, 0x02, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
8495
+/* 24 */ 0x00, 0x01, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
8496
+/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
8497
+/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
8498
+/* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
8499
+/* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
8500
+/* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
8501
+/* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8502
+/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
85098503
/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
8510
-/* 96 */ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\
8511
-/* 104 */ 0x00, 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00,\
8512
-/* 112 */ 0x01, 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
8513
-/* 120 */ 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\
8514
-/* 128 */ 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x02,\
8515
-/* 136 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
8516
-/* 144 */ 0x04, 0x04,}
8504
+/* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
8505
+/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
8506
+/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
8507
+/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\
8508
+/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
8509
+/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
8510
+/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}
85178511
85188512
/************** End of opcodes.h *********************************************/
85198513
/************** Continuing where we left off in vdbe.h ***********************/
85208514
85218515
/*
@@ -8534,11 +8528,11 @@
85348528
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
85358529
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
85368530
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
85378531
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
85388532
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
8539
-SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
8533
+SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
85408534
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
85418535
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
85428536
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
85438537
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
85448538
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
@@ -8566,13 +8560,13 @@
85668560
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
85678561
#ifndef SQLITE_OMIT_TRACE
85688562
SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
85698563
#endif
85708564
8571
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int);
8572
-SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
8565
+SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
85738566
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
8567
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
85748568
85758569
#ifndef SQLITE_OMIT_TRIGGER
85768570
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
85778571
#endif
85788572
@@ -8653,11 +8647,10 @@
86538647
** NOTE: These values must match the corresponding BTREE_ values in btree.h.
86548648
*/
86558649
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
86568650
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
86578651
#define PAGER_MEMORY 0x0004 /* In-memory database */
8658
-#define PAGER_SORTER 0x0020 /* Accumulator in external merge sort */
86598652
86608653
/*
86618654
** Valid values for the second argument to sqlite3PagerLockingMode().
86628655
*/
86638656
#define PAGER_LOCKINGMODE_QUERY -1
@@ -8749,13 +8742,10 @@
87498742
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
87508743
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
87518744
SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
87528745
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
87538746
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
8754
-#ifndef SQLITE_OMIT_MERGE_SORT
8755
-SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager*);
8756
-#endif
87578747
87588748
/* Functions used to truncate the database file. */
87598749
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
87608750
87618751
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
@@ -10186,10 +10176,11 @@
1018610176
u8 directMode; /* Direct rendering mode means take data directly
1018710177
** from source tables rather than from accumulators */
1018810178
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
1018910179
** than the source table */
1019010180
int sortingIdx; /* Cursor number of the sorting index */
10181
+ int sortingIdxPTab; /* Cursor number of pseudo-table */
1019110182
ExprList *pGroupBy; /* The group by clause */
1019210183
int nSortingColumn; /* Number of columns in the sorting index */
1019310184
struct AggInfo_col { /* For each column used in source tables */
1019410185
Table *pTab; /* Source table */
1019510186
int iTable; /* Cursor number of the source table */
@@ -10495,11 +10486,12 @@
1049510486
char *zDatabase; /* Name of database holding this table */
1049610487
char *zName; /* Name of the table */
1049710488
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
1049810489
Table *pTab; /* An SQL table corresponding to zName */
1049910490
Select *pSelect; /* A SELECT statement used in place of a table name */
10500
- u8 isPopulated; /* Temporary table associated with SELECT is populated */
10491
+ int addrFillSub; /* Address of subroutine to manifest a subquery */
10492
+ int regReturn; /* Register holding return address of addrFillSub */
1050110493
u8 jointype; /* Type of join between this able and the previous */
1050210494
u8 notIndexed; /* True if there is a NOT INDEXED clause */
1050310495
u8 isCorrelated; /* True if sub-query is correlated */
1050410496
#ifndef SQLITE_OMIT_EXPLAIN
1050510497
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
@@ -10718,10 +10710,11 @@
1071810710
#define SF_Resolved 0x0002 /* Identifiers have been resolved */
1071910711
#define SF_Aggregate 0x0004 /* Contains aggregate functions */
1072010712
#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
1072110713
#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
1072210714
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
10715
+#define SF_UseSorter 0x0040 /* Sort using a sorter */
1072310716
1072410717
1072510718
/*
1072610719
** The results of a select can be distributed in several ways. The
1072710720
** "SRT" prefix means "SELECT Result Type".
@@ -12044,11 +12037,11 @@
1204412037
SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
1204512038
1, /* bCoreMutex */
1204612039
SQLITE_THREADSAFE==1, /* bFullMutex */
1204712040
SQLITE_USE_URI, /* bOpenUri */
1204812041
0x7ffffffe, /* mxStrlen */
12049
- 100, /* szLookaside */
12042
+ 128, /* szLookaside */
1205012043
500, /* nLookaside */
1205112044
{0,0,0,0,0,0,0,0}, /* m */
1205212045
{0,0,0,0,0,0,0,0,0}, /* mutex */
1205312046
{0,0,0,0,0,0,0,0,0,0,0}, /* pcache */
1205412047
(void*)0, /* pHeap */
@@ -12267,10 +12260,13 @@
1226712260
"INT64_TYPE",
1226812261
#endif
1226912262
#ifdef SQLITE_LOCK_TRACE
1227012263
"LOCK_TRACE",
1227112264
#endif
12265
+#ifdef SQLITE_MAX_SCHEMA_RETRY
12266
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
12267
+#endif
1227212268
#ifdef SQLITE_MEMDEBUG
1227312269
"MEMDEBUG",
1227412270
#endif
1227512271
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
1227612272
"MIXED_ENDIAN_64BIT_FLOAT",
@@ -12601,16 +12597,17 @@
1260112597
Bool nullRow; /* True if pointing to a row with no data */
1260212598
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
1260312599
Bool isTable; /* True if a table requiring integer keys */
1260412600
Bool isIndex; /* True if an index containing keys only - no data */
1260512601
Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
12602
+ Bool isSorter; /* True if a new-style sorter */
1260612603
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
1260712604
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
1260812605
i64 seqCount; /* Sequence counter */
1260912606
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
1261012607
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
12611
- VdbeSorter *pSorter; /* Sorter object for OP_OpenSorter cursors */
12608
+ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
1261212609
1261312610
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
1261412611
** OP_IsUnique opcode on this cursor. */
1261512612
int seekResult;
1261612613
@@ -12944,17 +12941,19 @@
1294412941
# define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
1294512942
# define sqlite3VdbeSorterClose(Y,Z)
1294612943
# define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
1294712944
# define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
1294812945
# define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
12946
+# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
1294912947
#else
1295012948
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
12951
-SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, int);
1295212949
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
1295312950
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
12954
-SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
1295512951
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
12952
+SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
12953
+SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, Mem *);
12954
+SQLITE_PRIVATE int sqlite3VdbeSorterCompare(VdbeCursor *, Mem *, int *);
1295612955
#endif
1295712956
1295812957
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
1295912958
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
1296012959
SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
@@ -14537,11 +14536,11 @@
1453714536
int flags,
1453814537
int *pOutFlags
1453914538
){
1454014539
int rc = SQLITE_NOMEM;
1454114540
sqlite3_file *pFile;
14542
- pFile = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile);
14541
+ pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
1454314542
if( pFile ){
1454414543
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
1454514544
if( rc!=SQLITE_OK ){
1454614545
sqlite3_free(pFile);
1454714546
}else{
@@ -22100,66 +22099,66 @@
2210022099
/* 21 */ "MustBeInt",
2210122100
/* 22 */ "RealAffinity",
2210222101
/* 23 */ "Permutation",
2210322102
/* 24 */ "Compare",
2210422103
/* 25 */ "Jump",
22105
- /* 26 */ "If",
22106
- /* 27 */ "IfNot",
22107
- /* 28 */ "Column",
22108
- /* 29 */ "Affinity",
22109
- /* 30 */ "MakeRecord",
22110
- /* 31 */ "Count",
22111
- /* 32 */ "Savepoint",
22112
- /* 33 */ "AutoCommit",
22113
- /* 34 */ "Transaction",
22114
- /* 35 */ "ReadCookie",
22115
- /* 36 */ "SetCookie",
22116
- /* 37 */ "VerifyCookie",
22117
- /* 38 */ "OpenRead",
22118
- /* 39 */ "OpenWrite",
22119
- /* 40 */ "OpenSorter",
22104
+ /* 26 */ "Once",
22105
+ /* 27 */ "If",
22106
+ /* 28 */ "IfNot",
22107
+ /* 29 */ "Column",
22108
+ /* 30 */ "Affinity",
22109
+ /* 31 */ "MakeRecord",
22110
+ /* 32 */ "Count",
22111
+ /* 33 */ "Savepoint",
22112
+ /* 34 */ "AutoCommit",
22113
+ /* 35 */ "Transaction",
22114
+ /* 36 */ "ReadCookie",
22115
+ /* 37 */ "SetCookie",
22116
+ /* 38 */ "VerifyCookie",
22117
+ /* 39 */ "OpenRead",
22118
+ /* 40 */ "OpenWrite",
2212022119
/* 41 */ "OpenAutoindex",
2212122120
/* 42 */ "OpenEphemeral",
22122
- /* 43 */ "OpenPseudo",
22123
- /* 44 */ "Close",
22124
- /* 45 */ "SeekLt",
22125
- /* 46 */ "SeekLe",
22126
- /* 47 */ "SeekGe",
22127
- /* 48 */ "SeekGt",
22128
- /* 49 */ "Seek",
22129
- /* 50 */ "NotFound",
22130
- /* 51 */ "Found",
22131
- /* 52 */ "IsUnique",
22132
- /* 53 */ "NotExists",
22133
- /* 54 */ "Sequence",
22134
- /* 55 */ "NewRowid",
22135
- /* 56 */ "Insert",
22136
- /* 57 */ "InsertInt",
22137
- /* 58 */ "Delete",
22138
- /* 59 */ "ResetCount",
22139
- /* 60 */ "RowKey",
22140
- /* 61 */ "RowData",
22141
- /* 62 */ "Rowid",
22142
- /* 63 */ "NullRow",
22143
- /* 64 */ "Last",
22144
- /* 65 */ "Sort",
22145
- /* 66 */ "Rewind",
22146
- /* 67 */ "Prev",
22121
+ /* 43 */ "SorterOpen",
22122
+ /* 44 */ "OpenPseudo",
22123
+ /* 45 */ "Close",
22124
+ /* 46 */ "SeekLt",
22125
+ /* 47 */ "SeekLe",
22126
+ /* 48 */ "SeekGe",
22127
+ /* 49 */ "SeekGt",
22128
+ /* 50 */ "Seek",
22129
+ /* 51 */ "NotFound",
22130
+ /* 52 */ "Found",
22131
+ /* 53 */ "IsUnique",
22132
+ /* 54 */ "NotExists",
22133
+ /* 55 */ "Sequence",
22134
+ /* 56 */ "NewRowid",
22135
+ /* 57 */ "Insert",
22136
+ /* 58 */ "InsertInt",
22137
+ /* 59 */ "Delete",
22138
+ /* 60 */ "ResetCount",
22139
+ /* 61 */ "SorterCompare",
22140
+ /* 62 */ "SorterData",
22141
+ /* 63 */ "RowKey",
22142
+ /* 64 */ "RowData",
22143
+ /* 65 */ "Rowid",
22144
+ /* 66 */ "NullRow",
22145
+ /* 67 */ "Last",
2214722146
/* 68 */ "Or",
2214822147
/* 69 */ "And",
22149
- /* 70 */ "Next",
22150
- /* 71 */ "IdxInsert",
22151
- /* 72 */ "IdxDelete",
22148
+ /* 70 */ "SorterSort",
22149
+ /* 71 */ "Sort",
22150
+ /* 72 */ "Rewind",
2215222151
/* 73 */ "IsNull",
2215322152
/* 74 */ "NotNull",
2215422153
/* 75 */ "Ne",
2215522154
/* 76 */ "Eq",
2215622155
/* 77 */ "Gt",
2215722156
/* 78 */ "Le",
2215822157
/* 79 */ "Lt",
2215922158
/* 80 */ "Ge",
22160
- /* 81 */ "IdxRowid",
22159
+ /* 81 */ "SorterNext",
2216122160
/* 82 */ "BitAnd",
2216222161
/* 83 */ "BitOr",
2216322162
/* 84 */ "ShiftLeft",
2216422163
/* 85 */ "ShiftRight",
2216522164
/* 86 */ "Add",
@@ -22166,64 +22165,69 @@
2216622165
/* 87 */ "Subtract",
2216722166
/* 88 */ "Multiply",
2216822167
/* 89 */ "Divide",
2216922168
/* 90 */ "Remainder",
2217022169
/* 91 */ "Concat",
22171
- /* 92 */ "IdxLT",
22170
+ /* 92 */ "Prev",
2217222171
/* 93 */ "BitNot",
2217322172
/* 94 */ "String8",
22174
- /* 95 */ "IdxGE",
22175
- /* 96 */ "Destroy",
22176
- /* 97 */ "Clear",
22177
- /* 98 */ "CreateIndex",
22178
- /* 99 */ "CreateTable",
22179
- /* 100 */ "ParseSchema",
22180
- /* 101 */ "LoadAnalysis",
22181
- /* 102 */ "DropTable",
22182
- /* 103 */ "DropIndex",
22183
- /* 104 */ "DropTrigger",
22184
- /* 105 */ "IntegrityCk",
22185
- /* 106 */ "RowSetAdd",
22186
- /* 107 */ "RowSetRead",
22187
- /* 108 */ "RowSetTest",
22188
- /* 109 */ "Program",
22189
- /* 110 */ "Param",
22190
- /* 111 */ "FkCounter",
22191
- /* 112 */ "FkIfZero",
22192
- /* 113 */ "MemMax",
22193
- /* 114 */ "IfPos",
22194
- /* 115 */ "IfNeg",
22195
- /* 116 */ "IfZero",
22196
- /* 117 */ "AggStep",
22197
- /* 118 */ "AggFinal",
22198
- /* 119 */ "Checkpoint",
22199
- /* 120 */ "JournalMode",
22200
- /* 121 */ "Vacuum",
22201
- /* 122 */ "IncrVacuum",
22202
- /* 123 */ "Expire",
22203
- /* 124 */ "TableLock",
22204
- /* 125 */ "VBegin",
22205
- /* 126 */ "VCreate",
22206
- /* 127 */ "VDestroy",
22207
- /* 128 */ "VOpen",
22208
- /* 129 */ "VFilter",
22173
+ /* 95 */ "Next",
22174
+ /* 96 */ "SorterInsert",
22175
+ /* 97 */ "IdxInsert",
22176
+ /* 98 */ "IdxDelete",
22177
+ /* 99 */ "IdxRowid",
22178
+ /* 100 */ "IdxLT",
22179
+ /* 101 */ "IdxGE",
22180
+ /* 102 */ "Destroy",
22181
+ /* 103 */ "Clear",
22182
+ /* 104 */ "CreateIndex",
22183
+ /* 105 */ "CreateTable",
22184
+ /* 106 */ "ParseSchema",
22185
+ /* 107 */ "LoadAnalysis",
22186
+ /* 108 */ "DropTable",
22187
+ /* 109 */ "DropIndex",
22188
+ /* 110 */ "DropTrigger",
22189
+ /* 111 */ "IntegrityCk",
22190
+ /* 112 */ "RowSetAdd",
22191
+ /* 113 */ "RowSetRead",
22192
+ /* 114 */ "RowSetTest",
22193
+ /* 115 */ "Program",
22194
+ /* 116 */ "Param",
22195
+ /* 117 */ "FkCounter",
22196
+ /* 118 */ "FkIfZero",
22197
+ /* 119 */ "MemMax",
22198
+ /* 120 */ "IfPos",
22199
+ /* 121 */ "IfNeg",
22200
+ /* 122 */ "IfZero",
22201
+ /* 123 */ "AggStep",
22202
+ /* 124 */ "AggFinal",
22203
+ /* 125 */ "Checkpoint",
22204
+ /* 126 */ "JournalMode",
22205
+ /* 127 */ "Vacuum",
22206
+ /* 128 */ "IncrVacuum",
22207
+ /* 129 */ "Expire",
2220922208
/* 130 */ "Real",
22210
- /* 131 */ "VColumn",
22211
- /* 132 */ "VNext",
22212
- /* 133 */ "VRename",
22213
- /* 134 */ "VUpdate",
22214
- /* 135 */ "Pagecount",
22215
- /* 136 */ "MaxPgcnt",
22216
- /* 137 */ "Trace",
22217
- /* 138 */ "Noop",
22218
- /* 139 */ "Explain",
22219
- /* 140 */ "NotUsed_140",
22209
+ /* 131 */ "TableLock",
22210
+ /* 132 */ "VBegin",
22211
+ /* 133 */ "VCreate",
22212
+ /* 134 */ "VDestroy",
22213
+ /* 135 */ "VOpen",
22214
+ /* 136 */ "VFilter",
22215
+ /* 137 */ "VColumn",
22216
+ /* 138 */ "VNext",
22217
+ /* 139 */ "VRename",
22218
+ /* 140 */ "VUpdate",
2222022219
/* 141 */ "ToText",
2222122220
/* 142 */ "ToBlob",
2222222221
/* 143 */ "ToNumeric",
2222322222
/* 144 */ "ToInt",
2222422223
/* 145 */ "ToReal",
22224
+ /* 146 */ "Pagecount",
22225
+ /* 147 */ "MaxPgcnt",
22226
+ /* 148 */ "Trace",
22227
+ /* 149 */ "Noop",
22228
+ /* 150 */ "Explain",
2222522229
};
2222622230
return azName[i];
2222722231
}
2222822232
#endif
2222922233
@@ -22314,11 +22318,11 @@
2231422318
*/
2231522319
#ifdef MEMORY_DEBUG
2231622320
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
2231722321
#endif
2231822322
22319
-#ifdef SQLITE_DEBUG
22323
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
2232022324
# ifndef SQLITE_DEBUG_OS_TRACE
2232122325
# define SQLITE_DEBUG_OS_TRACE 0
2232222326
# endif
2232322327
int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
2232422328
# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -24656,11 +24660,11 @@
2465624660
*/
2465724661
#ifdef MEMORY_DEBUG
2465824662
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
2465924663
#endif
2466024664
24661
-#ifdef SQLITE_DEBUG
24665
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
2466224666
# ifndef SQLITE_DEBUG_OS_TRACE
2466324667
# define SQLITE_DEBUG_OS_TRACE 0
2466424668
# endif
2466524669
int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
2466624670
# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -27716,15 +27720,15 @@
2771627720
SQLITE_API int sqlite3_fullsync_count = 0;
2771727721
#endif
2771827722
2771927723
/*
2772027724
** We do not trust systems to provide a working fdatasync(). Some do.
27721
-** Others do no. To be safe, we will stick with the (slower) fsync().
27722
-** If you know that your system does support fdatasync() correctly,
27725
+** Others do no. To be safe, we will stick with the (slightly slower)
27726
+** fsync(). If you know that your system does support fdatasync() correctly,
2772327727
** then simply compile with -Dfdatasync=fdatasync
2772427728
*/
27725
-#if !defined(fdatasync) && !defined(__linux__)
27729
+#if !defined(fdatasync)
2772627730
# define fdatasync fsync
2772727731
#endif
2772827732
2772927733
/*
2773027734
** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
@@ -28015,11 +28019,11 @@
2801528019
** file-control operation. Enlarge the database to nBytes in size
2801628020
** (rounded up to the next chunk-size). If the database is already
2801728021
** nBytes or larger, this routine is a no-op.
2801828022
*/
2801928023
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
28020
- if( pFile->szChunk ){
28024
+ if( pFile->szChunk>0 ){
2802128025
i64 nSize; /* Required file size */
2802228026
struct stat buf; /* Used to hold return values of fstat() */
2802328027
2802428028
if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
2802528029
@@ -28210,15 +28214,13 @@
2821028214
*/
2821128215
struct unixShm {
2821228216
unixShmNode *pShmNode; /* The underlying unixShmNode object */
2821328217
unixShm *pNext; /* Next unixShm with the same unixShmNode */
2821428218
u8 hasMutex; /* True if holding the unixShmNode mutex */
28219
+ u8 id; /* Id of this connection within its unixShmNode */
2821528220
u16 sharedMask; /* Mask of shared locks held */
2821628221
u16 exclMask; /* Mask of exclusive locks held */
28217
-#ifdef SQLITE_DEBUG
28218
- u8 id; /* Id of this connection within its unixShmNode */
28219
-#endif
2822028222
};
2822128223
2822228224
/*
2822328225
** Constants used for locking
2822428226
*/
@@ -31435,11 +31437,11 @@
3143531437
*/
3143631438
#ifdef MEMORY_DEBUG
3143731439
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
3143831440
#endif
3143931441
31440
-#ifdef SQLITE_DEBUG
31442
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
3144131443
# ifndef SQLITE_DEBUG_OS_TRACE
3144231444
# define SQLITE_DEBUG_OS_TRACE 0
3144331445
# endif
3144431446
int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
3144531447
# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -32768,11 +32770,11 @@
3276832770
/* If the user has configured a chunk-size for this file, truncate the
3276932771
** file so that it consists of an integer number of chunks (i.e. the
3277032772
** actual file size after the operation may be larger than the requested
3277132773
** size).
3277232774
*/
32773
- if( pFile->szChunk ){
32775
+ if( pFile->szChunk>0 ){
3277432776
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
3277532777
}
3277632778
3277732779
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
3277832780
if( seekWinFile(pFile, nByte) ){
@@ -32797,13 +32799,23 @@
3279732799
3279832800
/*
3279932801
** Make sure all writes to a particular file are committed to disk.
3280032802
*/
3280132803
static int winSync(sqlite3_file *id, int flags){
32802
-#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
32803
- winFile *pFile = (winFile*)id;
32804
+#ifndef SQLITE_NO_SYNC
32805
+ /*
32806
+ ** Used only when SQLITE_NO_SYNC is not defined.
32807
+ */
3280432808
BOOL rc;
32809
+#endif
32810
+#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
32811
+ (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
32812
+ /*
32813
+ ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
32814
+ ** OSTRACE() macros.
32815
+ */
32816
+ winFile *pFile = (winFile*)id;
3280532817
#else
3280632818
UNUSED_PARAMETER(id);
3280732819
#endif
3280832820
3280932821
assert( pFile );
@@ -33155,22 +33167,24 @@
3315533167
case SQLITE_FCNTL_CHUNK_SIZE: {
3315633168
pFile->szChunk = *(int *)pArg;
3315733169
return SQLITE_OK;
3315833170
}
3315933171
case SQLITE_FCNTL_SIZE_HINT: {
33160
- winFile *pFile = (winFile*)id;
33161
- sqlite3_int64 oldSz;
33162
- int rc = winFileSize(id, &oldSz);
33163
- if( rc==SQLITE_OK ){
33164
- sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
33165
- if( newSz>oldSz ){
33166
- SimulateIOErrorBenign(1);
33167
- rc = winTruncate(id, newSz);
33168
- SimulateIOErrorBenign(0);
33169
- }
33170
- }
33171
- return rc;
33172
+ if( pFile->szChunk>0 ){
33173
+ sqlite3_int64 oldSz;
33174
+ int rc = winFileSize(id, &oldSz);
33175
+ if( rc==SQLITE_OK ){
33176
+ sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
33177
+ if( newSz>oldSz ){
33178
+ SimulateIOErrorBenign(1);
33179
+ rc = winTruncate(id, newSz);
33180
+ SimulateIOErrorBenign(0);
33181
+ }
33182
+ }
33183
+ return rc;
33184
+ }
33185
+ return SQLITE_OK;
3317233186
}
3317333187
case SQLITE_FCNTL_PERSIST_WAL: {
3317433188
int bPersist = *(int*)pArg;
3317533189
if( bPersist<0 ){
3317633190
*(int*)pArg = pFile->bPersistWal;
@@ -38136,12 +38150,10 @@
3813638150
u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
3813738151
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
3813838152
u8 tempFile; /* zFilename is a temporary file */
3813938153
u8 readOnly; /* True for a read-only database */
3814038154
u8 memDb; /* True to inhibit all file I/O */
38141
- u8 hasSeenStress; /* pagerStress() called one or more times */
38142
- u8 isSorter; /* True for a PAGER_SORTER */
3814338155
3814438156
/**************************************************************************
3814538157
** The following block contains those class members that change during
3814638158
** routine opertion. Class members not in this block are either fixed
3814738159
** when the pager is first created or else only change when there is a
@@ -38361,19 +38373,10 @@
3836138373
);
3836238374
assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
3836338375
assert( pagerUseWal(p)==0 );
3836438376
}
3836538377
38366
- /* A sorter is a temp file that never spills to disk and always has
38367
- ** the doNotSpill flag set
38368
- */
38369
- if( p->isSorter ){
38370
- assert( p->tempFile );
38371
- assert( p->doNotSpill );
38372
- assert( p->fd->pMethods==0 );
38373
- }
38374
-
3837538378
/* If changeCountDone is set, a RESERVED lock or greater must be held
3837638379
** on the file.
3837738380
*/
3837838381
assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
3837938382
assert( p->eLock!=PENDING_LOCK );
@@ -41701,11 +41704,10 @@
4170141704
** is impossible for sqlite3PCacheFetch() to be called with createFlag==1
4170241705
** while in the error state, hence it is impossible for this routine to
4170341706
** be called in the error state. Nevertheless, we include a NEVER()
4170441707
** test for the error state as a safeguard against future changes.
4170541708
*/
41706
- pPager->hasSeenStress = 1;
4170741709
if( NEVER(pPager->errCode) ) return SQLITE_OK;
4170841710
if( pPager->doNotSpill ) return SQLITE_OK;
4170941711
if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
4171041712
return SQLITE_OK;
4171141713
}
@@ -42073,16 +42075,10 @@
4207342075
}
4207442076
/* pPager->xBusyHandler = 0; */
4207542077
/* pPager->pBusyHandlerArg = 0; */
4207642078
pPager->xReiniter = xReinit;
4207742079
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
42078
-#ifndef SQLITE_OMIT_MERGE_SORT
42079
- if( flags & PAGER_SORTER ){
42080
- pPager->doNotSpill = 1;
42081
- pPager->isSorter = 1;
42082
- }
42083
-#endif
4208442080
4208542081
*ppPager = pPager;
4208642082
return SQLITE_OK;
4208742083
}
4208842084
@@ -43623,21 +43619,10 @@
4362343619
*/
4362443620
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
4362543621
return MEMDB;
4362643622
}
4362743623
43628
-#ifndef SQLITE_OMIT_MERGE_SORT
43629
-/*
43630
-** Return true if the pager has seen a pagerStress callback.
43631
-*/
43632
-SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager *pPager){
43633
- assert( pPager->isSorter );
43634
- assert( pPager->doNotSpill );
43635
- return pPager->hasSeenStress;
43636
-}
43637
-#endif
43638
-
4363943624
/*
4364043625
** Check that there are at least nSavepoint savepoints open. If there are
4364143626
** currently less than nSavepoints open, then open one or more savepoints
4364243627
** to make up the difference. If the number of savepoints is already
4364343628
** equal to nSavepoint, then this function is a no-op.
@@ -48924,22 +48909,25 @@
4892448909
int *pRes /* Write search results here */
4892548910
){
4892648911
int rc; /* Status code */
4892748912
UnpackedRecord *pIdxKey; /* Unpacked index key */
4892848913
char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */
48914
+ char *pFree = 0;
4892948915
4893048916
if( pKey ){
4893148917
assert( nKey==(i64)(int)nKey );
48932
- pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey,
48933
- aSpace, sizeof(aSpace));
48918
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(
48919
+ pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
48920
+ );
4893448921
if( pIdxKey==0 ) return SQLITE_NOMEM;
48922
+ sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
4893548923
}else{
4893648924
pIdxKey = 0;
4893748925
}
4893848926
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
48939
- if( pKey ){
48940
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
48927
+ if( pFree ){
48928
+ sqlite3DbFree(pCur->pKeyInfo->db, pFree);
4894148929
}
4894248930
return rc;
4894348931
}
4894448932
4894548933
/*
@@ -50002,26 +49990,15 @@
5000249990
assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
5000349991
5000449992
/* A BTREE_SINGLE database is always a temporary and/or ephemeral */
5000549993
assert( (flags & BTREE_SINGLE)==0 || isTempDb );
5000649994
50007
- /* The BTREE_SORTER flag is only used if SQLITE_OMIT_MERGE_SORT is undef */
50008
-#ifdef SQLITE_OMIT_MERGE_SORT
50009
- assert( (flags & BTREE_SORTER)==0 );
50010
-#endif
50011
-
50012
- /* BTREE_SORTER is always on a BTREE_SINGLE, BTREE_OMIT_JOURNAL */
50013
- assert( (flags & BTREE_SORTER)==0 ||
50014
- (flags & (BTREE_SINGLE|BTREE_OMIT_JOURNAL))
50015
- ==(BTREE_SINGLE|BTREE_OMIT_JOURNAL) );
50016
-
5001749995
if( db->flags & SQLITE_NoReadlock ){
5001849996
flags |= BTREE_NO_READLOCK;
5001949997
}
5002049998
if( isMemdb ){
5002149999
flags |= BTREE_MEMORY;
50022
- flags &= ~BTREE_SORTER;
5002350000
}
5002450001
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
5002550002
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
5002650003
}
5002750004
p = sqlite3MallocZero(sizeof(Btree));
@@ -51022,15 +50999,16 @@
5102250999
for(i=0; i<nCell; i++){
5102351000
u8 *pCell = findCell(pPage, i);
5102451001
if( eType==PTRMAP_OVERFLOW1 ){
5102551002
CellInfo info;
5102651003
btreeParseCellPtr(pPage, pCell, &info);
51027
- if( info.iOverflow ){
51028
- if( iFrom==get4byte(&pCell[info.iOverflow]) ){
51029
- put4byte(&pCell[info.iOverflow], iTo);
51030
- break;
51031
- }
51004
+ if( info.iOverflow
51005
+ && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
51006
+ && iFrom==get4byte(&pCell[info.iOverflow])
51007
+ ){
51008
+ put4byte(&pCell[info.iOverflow], iTo);
51009
+ break;
5103251010
}
5103351011
}else{
5103451012
if( get4byte(pCell)==iFrom ){
5103551013
put4byte(pCell, iTo);
5103651014
break;
@@ -53458,10 +53436,13 @@
5345853436
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
5345953437
btreeParseCellPtr(pPage, pCell, &info);
5346053438
if( info.iOverflow==0 ){
5346153439
return SQLITE_OK; /* No overflow pages. Return without doing anything */
5346253440
}
53441
+ if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
53442
+ return SQLITE_CORRUPT; /* Cell extends past end of page */
53443
+ }
5346353444
ovflPgno = get4byte(&pCell[info.iOverflow]);
5346453445
assert( pBt->usableSize > 4 );
5346553446
ovflPageSize = pBt->usableSize - 4;
5346653447
nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
5346753448
assert( ovflPgno==0 || nOvfl>0 );
@@ -55560,20 +55541,13 @@
5556055541
releasePage(pPage);
5556155542
}
5556255543
return rc;
5556355544
}
5556455545
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
55565
- BtShared *pBt = p->pBt;
5556655546
int rc;
5556755547
sqlite3BtreeEnter(p);
55568
- if( (pBt->openFlags&BTREE_SINGLE) ){
55569
- pBt->nPage = 0;
55570
- sqlite3PagerTruncateImage(pBt->pPager, 1);
55571
- rc = newDatabase(pBt);
55572
- }else{
55573
- rc = btreeDropTable(p, iTable, piMoved);
55574
- }
55548
+ rc = btreeDropTable(p, iTable, piMoved);
5557555549
sqlite3BtreeLeave(p);
5557655550
return rc;
5557755551
}
5557855552
5557955553
@@ -58758,11 +58732,11 @@
5875858732
assert( p->nOp - i >= 3 );
5875958733
assert( pOp[-1].opcode==OP_Integer );
5876058734
n = pOp[-1].p1;
5876158735
if( n>nMaxArgs ) nMaxArgs = n;
5876258736
#endif
58763
- }else if( opcode==OP_Next ){
58737
+ }else if( opcode==OP_Next || opcode==OP_SorterNext ){
5876458738
pOp->p4.xAdvance = sqlite3BtreeNext;
5876558739
pOp->p4type = P4_ADVANCE;
5876658740
}else if( opcode==OP_Prev ){
5876758741
pOp->p4.xAdvance = sqlite3BtreePrevious;
5876858742
pOp->p4type = P4_ADVANCE;
@@ -58995,22 +58969,19 @@
5899558969
p->pNext = pVdbe->pProgram;
5899658970
pVdbe->pProgram = p;
5899758971
}
5899858972
5899958973
/*
59000
-** Change N opcodes starting at addr to No-ops.
58974
+** Change the opcode at addr into OP_Noop
5900158975
*/
59002
-SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
58976
+SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
5900358977
if( p->aOp ){
5900458978
VdbeOp *pOp = &p->aOp[addr];
5900558979
sqlite3 *db = p->db;
59006
- while( N-- ){
59007
- freeP4(db, pOp->p4type, pOp->p4.p);
59008
- memset(pOp, 0, sizeof(pOp[0]));
59009
- pOp->opcode = OP_Noop;
59010
- pOp++;
59011
- }
58980
+ freeP4(db, pOp->p4type, pOp->p4.p);
58981
+ memset(pOp, 0, sizeof(pOp[0]));
58982
+ pOp->opcode = OP_Noop;
5901258983
}
5901358984
}
5901458985
5901558986
/*
5901658987
** Change the value of the P4 operand for a specific instruction.
@@ -59162,11 +59133,11 @@
5916259133
** check the value of p->nOp-1 before continuing.
5916359134
*/
5916459135
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
5916559136
/* C89 specifies that the constant "dummy" will be initialized to all
5916659137
** zeros, which is correct. MSVC generates a warning, nevertheless. */
59167
- static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
59138
+ static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
5916859139
assert( p->magic==VDBE_MAGIC_INIT );
5916959140
if( addr<0 ){
5917059141
#ifdef SQLITE_OMIT_TRACE
5917159142
if( p->nOp==0 ) return (VdbeOp*)&dummy;
5917259143
#endif
@@ -61155,61 +61126,74 @@
6115561126
}
6115661127
}
6115761128
return 0;
6115861129
}
6115961130
61160
-
61161
-/*
61162
-** Given the nKey-byte encoding of a record in pKey[], parse the
61163
-** record into a UnpackedRecord structure. Return a pointer to
61164
-** that structure.
61165
-**
61166
-** The calling function might provide szSpace bytes of memory
61167
-** space at pSpace. This space can be used to hold the returned
61168
-** VDbeParsedRecord structure if it is large enough. If it is
61169
-** not big enough, space is obtained from sqlite3_malloc().
61170
-**
61171
-** The returned structure should be closed by a call to
61172
-** sqlite3VdbeDeleteUnpackedRecord().
61173
-*/
61174
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
61175
- KeyInfo *pKeyInfo, /* Information about the record format */
61176
- int nKey, /* Size of the binary record */
61177
- const void *pKey, /* The binary record */
61178
- char *pSpace, /* Unaligned space available to hold the object */
61179
- int szSpace /* Size of pSpace[] in bytes */
61180
-){
61181
- const unsigned char *aKey = (const unsigned char *)pKey;
61182
- UnpackedRecord *p; /* The unpacked record that we will return */
61183
- int nByte; /* Memory space needed to hold p, in bytes */
61184
- int d;
61185
- u32 idx;
61186
- u16 u; /* Unsigned loop counter */
61187
- u32 szHdr;
61188
- Mem *pMem;
61189
- int nOff; /* Increase pSpace by this much to 8-byte align it */
61190
-
61191
- /*
61192
- ** We want to shift the pointer pSpace up such that it is 8-byte aligned.
61131
+/*
61132
+** This routine is used to allocate sufficient space for an UnpackedRecord
61133
+** structure large enough to be used with sqlite3VdbeRecordUnpack() if
61134
+** the first argument is a pointer to KeyInfo structure pKeyInfo.
61135
+**
61136
+** The space is either allocated using sqlite3DbMallocRaw() or from within
61137
+** the unaligned buffer passed via the second and third arguments (presumably
61138
+** stack space). If the former, then *ppFree is set to a pointer that should
61139
+** be eventually freed by the caller using sqlite3DbFree(). Or, if the
61140
+** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
61141
+** before returning.
61142
+**
61143
+** If an OOM error occurs, NULL is returned.
61144
+*/
61145
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
61146
+ KeyInfo *pKeyInfo, /* Description of the record */
61147
+ char *pSpace, /* Unaligned space available */
61148
+ int szSpace, /* Size of pSpace[] in bytes */
61149
+ char **ppFree /* OUT: Caller should free this pointer */
61150
+){
61151
+ UnpackedRecord *p; /* Unpacked record to return */
61152
+ int nOff; /* Increment pSpace by nOff to align it */
61153
+ int nByte; /* Number of bytes required for *p */
61154
+
61155
+ /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
6119361156
** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
6119461157
** it by. If pSpace is already 8-byte aligned, nOff should be zero.
6119561158
*/
6119661159
nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
61197
- pSpace += nOff;
61198
- szSpace -= nOff;
6119961160
nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
61200
- if( nByte>szSpace ){
61201
- p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
61202
- if( p==0 ) return 0;
61203
- p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
61161
+ if( nByte>szSpace+nOff ){
61162
+ p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
61163
+ *ppFree = (char *)p;
61164
+ if( !p ) return 0;
6120461165
}else{
61205
- p = (UnpackedRecord*)pSpace;
61206
- p->flags = UNPACKED_NEED_DESTROY;
61166
+ p = (UnpackedRecord*)&pSpace[nOff];
61167
+ *ppFree = 0;
6120761168
}
61169
+
61170
+ p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
6120861171
p->pKeyInfo = pKeyInfo;
6120961172
p->nField = pKeyInfo->nField + 1;
61210
- p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
61173
+ return p;
61174
+}
61175
+
61176
+/*
61177
+** Given the nKey-byte encoding of a record in pKey[], populate the
61178
+** UnpackedRecord structure indicated by the fourth argument with the
61179
+** contents of the decoded record.
61180
+*/
61181
+SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
61182
+ KeyInfo *pKeyInfo, /* Information about the record format */
61183
+ int nKey, /* Size of the binary record */
61184
+ const void *pKey, /* The binary record */
61185
+ UnpackedRecord *p /* Populate this structure before returning. */
61186
+){
61187
+ const unsigned char *aKey = (const unsigned char *)pKey;
61188
+ int d;
61189
+ u32 idx; /* Offset in aKey[] to read from */
61190
+ u16 u; /* Unsigned loop counter */
61191
+ u32 szHdr;
61192
+ Mem *pMem = p->aMem;
61193
+
61194
+ p->flags = 0;
6121161195
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
6121261196
idx = getVarint32(aKey, szHdr);
6121361197
d = szHdr;
6121461198
u = 0;
6121561199
while( idx<szHdr && u<p->nField && d<=nKey ){
@@ -61224,35 +61208,10 @@
6122461208
pMem++;
6122561209
u++;
6122661210
}
6122761211
assert( u<=pKeyInfo->nField + 1 );
6122861212
p->nField = u;
61229
- return (void*)p;
61230
-}
61231
-
61232
-/*
61233
-** This routine destroys a UnpackedRecord object.
61234
-*/
61235
-SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
61236
-#ifdef SQLITE_DEBUG
61237
- int i;
61238
- Mem *pMem;
61239
-
61240
- assert( p!=0 );
61241
- assert( p->flags & UNPACKED_NEED_DESTROY );
61242
- for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
61243
- /* The unpacked record is always constructed by the
61244
- ** sqlite3VdbeUnpackRecord() function above, which makes all
61245
- ** strings and blobs static. And none of the elements are
61246
- ** ever transformed, so there is never anything to delete.
61247
- */
61248
- if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem);
61249
- }
61250
-#endif
61251
- if( p->flags & UNPACKED_NEED_FREE ){
61252
- sqlite3DbFree(p->pKeyInfo->db, p);
61253
- }
6125461213
}
6125561214
6125661215
/*
6125761216
** This function compares the two table rows or index records
6125861217
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
@@ -63871,55 +63830,59 @@
6387163830
Db *pDb;
6387263831
} aw;
6387363832
struct OP_OpenEphemeral_stack_vars {
6387463833
VdbeCursor *pCx;
6387563834
} ax;
63876
- struct OP_OpenPseudo_stack_vars {
63835
+ struct OP_SorterOpen_stack_vars {
6387763836
VdbeCursor *pCx;
6387863837
} ay;
63838
+ struct OP_OpenPseudo_stack_vars {
63839
+ VdbeCursor *pCx;
63840
+ } az;
6387963841
struct OP_SeekGt_stack_vars {
6388063842
int res;
6388163843
int oc;
6388263844
VdbeCursor *pC;
6388363845
UnpackedRecord r;
6388463846
int nField;
6388563847
i64 iKey; /* The rowid we are to seek to */
63886
- } az;
63848
+ } ba;
6388763849
struct OP_Seek_stack_vars {
6388863850
VdbeCursor *pC;
63889
- } ba;
63851
+ } bb;
6389063852
struct OP_Found_stack_vars {
6389163853
int alreadyExists;
6389263854
VdbeCursor *pC;
6389363855
int res;
63856
+ char *pFree;
6389463857
UnpackedRecord *pIdxKey;
6389563858
UnpackedRecord r;
6389663859
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
63897
- } bb;
63860
+ } bc;
6389863861
struct OP_IsUnique_stack_vars {
6389963862
u16 ii;
6390063863
VdbeCursor *pCx;
6390163864
BtCursor *pCrsr;
6390263865
u16 nField;
6390363866
Mem *aMx;
6390463867
UnpackedRecord r; /* B-Tree index search key */
6390563868
i64 R; /* Rowid stored in register P3 */
63906
- } bc;
63869
+ } bd;
6390763870
struct OP_NotExists_stack_vars {
6390863871
VdbeCursor *pC;
6390963872
BtCursor *pCrsr;
6391063873
int res;
6391163874
u64 iKey;
63912
- } bd;
63875
+ } be;
6391363876
struct OP_NewRowid_stack_vars {
6391463877
i64 v; /* The new rowid */
6391563878
VdbeCursor *pC; /* Cursor of table to get the new rowid */
6391663879
int res; /* Result of an sqlite3BtreeLast() */
6391763880
int cnt; /* Counter to limit the number of searches */
6391863881
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
6391963882
VdbeFrame *pFrame; /* Root frame of VDBE */
63920
- } be;
63883
+ } bf;
6392163884
struct OP_InsertInt_stack_vars {
6392263885
Mem *pData; /* MEM cell holding data for the record to be inserted */
6392363886
Mem *pKey; /* MEM cell holding key for the record */
6392463887
i64 iKey; /* The integer ROWID or key for the record to be inserted */
6392563888
VdbeCursor *pC; /* Cursor to table into which insert is written */
@@ -63926,154 +63889,161 @@
6392663889
int nZero; /* Number of zero-bytes to append */
6392763890
int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
6392863891
const char *zDb; /* database name - used by the update hook */
6392963892
const char *zTbl; /* Table name - used by the opdate hook */
6393063893
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
63931
- } bf;
63894
+ } bg;
6393263895
struct OP_Delete_stack_vars {
6393363896
i64 iKey;
6393463897
VdbeCursor *pC;
63935
- } bg;
63898
+ } bh;
63899
+ struct OP_SorterCompare_stack_vars {
63900
+ VdbeCursor *pC;
63901
+ int res;
63902
+ } bi;
63903
+ struct OP_SorterData_stack_vars {
63904
+ VdbeCursor *pC;
63905
+ } bj;
6393663906
struct OP_RowData_stack_vars {
6393763907
VdbeCursor *pC;
6393863908
BtCursor *pCrsr;
6393963909
u32 n;
6394063910
i64 n64;
63941
- } bh;
63911
+ } bk;
6394263912
struct OP_Rowid_stack_vars {
6394363913
VdbeCursor *pC;
6394463914
i64 v;
6394563915
sqlite3_vtab *pVtab;
6394663916
const sqlite3_module *pModule;
63947
- } bi;
63917
+ } bl;
6394863918
struct OP_NullRow_stack_vars {
6394963919
VdbeCursor *pC;
63950
- } bj;
63920
+ } bm;
6395163921
struct OP_Last_stack_vars {
6395263922
VdbeCursor *pC;
6395363923
BtCursor *pCrsr;
6395463924
int res;
63955
- } bk;
63925
+ } bn;
6395663926
struct OP_Rewind_stack_vars {
6395763927
VdbeCursor *pC;
6395863928
BtCursor *pCrsr;
6395963929
int res;
63960
- } bl;
63930
+ } bo;
6396163931
struct OP_Next_stack_vars {
6396263932
VdbeCursor *pC;
6396363933
int res;
63964
- } bm;
63934
+ } bp;
6396563935
struct OP_IdxInsert_stack_vars {
6396663936
VdbeCursor *pC;
6396763937
BtCursor *pCrsr;
6396863938
int nKey;
6396963939
const char *zKey;
63970
- } bn;
63940
+ } bq;
6397163941
struct OP_IdxDelete_stack_vars {
6397263942
VdbeCursor *pC;
6397363943
BtCursor *pCrsr;
6397463944
int res;
6397563945
UnpackedRecord r;
63976
- } bo;
63946
+ } br;
6397763947
struct OP_IdxRowid_stack_vars {
6397863948
BtCursor *pCrsr;
6397963949
VdbeCursor *pC;
6398063950
i64 rowid;
63981
- } bp;
63951
+ } bs;
6398263952
struct OP_IdxGE_stack_vars {
6398363953
VdbeCursor *pC;
6398463954
int res;
6398563955
UnpackedRecord r;
63986
- } bq;
63956
+ } bt;
6398763957
struct OP_Destroy_stack_vars {
6398863958
int iMoved;
6398963959
int iCnt;
6399063960
Vdbe *pVdbe;
6399163961
int iDb;
63992
- } br;
63962
+ } bu;
6399363963
struct OP_Clear_stack_vars {
6399463964
int nChange;
63995
- } bs;
63965
+ } bv;
6399663966
struct OP_CreateTable_stack_vars {
6399763967
int pgno;
6399863968
int flags;
6399963969
Db *pDb;
64000
- } bt;
63970
+ } bw;
6400163971
struct OP_ParseSchema_stack_vars {
6400263972
int iDb;
6400363973
const char *zMaster;
6400463974
char *zSql;
6400563975
InitData initData;
64006
- } bu;
63976
+ } bx;
6400763977
struct OP_IntegrityCk_stack_vars {
6400863978
int nRoot; /* Number of tables to check. (Number of root pages.) */
6400963979
int *aRoot; /* Array of rootpage numbers for tables to be checked */
6401063980
int j; /* Loop counter */
6401163981
int nErr; /* Number of errors reported */
6401263982
char *z; /* Text of the error report */
6401363983
Mem *pnErr; /* Register keeping track of errors remaining */
64014
- } bv;
63984
+ } by;
6401563985
struct OP_RowSetRead_stack_vars {
6401663986
i64 val;
64017
- } bw;
63987
+ } bz;
6401863988
struct OP_RowSetTest_stack_vars {
6401963989
int iSet;
6402063990
int exists;
64021
- } bx;
63991
+ } ca;
6402263992
struct OP_Program_stack_vars {
6402363993
int nMem; /* Number of memory registers for sub-program */
6402463994
int nByte; /* Bytes of runtime space required for sub-program */
6402563995
Mem *pRt; /* Register to allocate runtime space */
6402663996
Mem *pMem; /* Used to iterate through memory cells */
6402763997
Mem *pEnd; /* Last memory cell in new array */
6402863998
VdbeFrame *pFrame; /* New vdbe frame to execute in */
6402963999
SubProgram *pProgram; /* Sub-program to execute */
6403064000
void *t; /* Token identifying trigger */
64031
- } by;
64001
+ } cb;
6403264002
struct OP_Param_stack_vars {
6403364003
VdbeFrame *pFrame;
6403464004
Mem *pIn;
64035
- } bz;
64005
+ } cc;
6403664006
struct OP_MemMax_stack_vars {
6403764007
Mem *pIn1;
6403864008
VdbeFrame *pFrame;
64039
- } ca;
64009
+ } cd;
6404064010
struct OP_AggStep_stack_vars {
6404164011
int n;
6404264012
int i;
6404364013
Mem *pMem;
6404464014
Mem *pRec;
6404564015
sqlite3_context ctx;
6404664016
sqlite3_value **apVal;
64047
- } cb;
64017
+ } ce;
6404864018
struct OP_AggFinal_stack_vars {
6404964019
Mem *pMem;
64050
- } cc;
64020
+ } cf;
6405164021
struct OP_Checkpoint_stack_vars {
6405264022
int i; /* Loop counter */
6405364023
int aRes[3]; /* Results */
6405464024
Mem *pMem; /* Write results here */
64055
- } cd;
64025
+ } cg;
6405664026
struct OP_JournalMode_stack_vars {
6405764027
Btree *pBt; /* Btree to change journal mode of */
6405864028
Pager *pPager; /* Pager associated with pBt */
6405964029
int eNew; /* New journal mode */
6406064030
int eOld; /* The old journal mode */
6406164031
const char *zFilename; /* Name of database file for pPager */
64062
- } ce;
64032
+ } ch;
6406364033
struct OP_IncrVacuum_stack_vars {
6406464034
Btree *pBt;
64065
- } cf;
64035
+ } ci;
6406664036
struct OP_VBegin_stack_vars {
6406764037
VTable *pVTab;
64068
- } cg;
64038
+ } cj;
6406964039
struct OP_VOpen_stack_vars {
6407064040
VdbeCursor *pCur;
6407164041
sqlite3_vtab_cursor *pVtabCursor;
6407264042
sqlite3_vtab *pVtab;
6407364043
sqlite3_module *pModule;
64074
- } ch;
64044
+ } ck;
6407564045
struct OP_VFilter_stack_vars {
6407664046
int nArg;
6407764047
int iQuery;
6407864048
const sqlite3_module *pModule;
6407964049
Mem *pQuery;
@@ -64082,40 +64052,40 @@
6408264052
sqlite3_vtab *pVtab;
6408364053
VdbeCursor *pCur;
6408464054
int res;
6408564055
int i;
6408664056
Mem **apArg;
64087
- } ci;
64057
+ } cl;
6408864058
struct OP_VColumn_stack_vars {
6408964059
sqlite3_vtab *pVtab;
6409064060
const sqlite3_module *pModule;
6409164061
Mem *pDest;
6409264062
sqlite3_context sContext;
64093
- } cj;
64063
+ } cm;
6409464064
struct OP_VNext_stack_vars {
6409564065
sqlite3_vtab *pVtab;
6409664066
const sqlite3_module *pModule;
6409764067
int res;
6409864068
VdbeCursor *pCur;
64099
- } ck;
64069
+ } cn;
6410064070
struct OP_VRename_stack_vars {
6410164071
sqlite3_vtab *pVtab;
6410264072
Mem *pName;
64103
- } cl;
64073
+ } co;
6410464074
struct OP_VUpdate_stack_vars {
6410564075
sqlite3_vtab *pVtab;
6410664076
sqlite3_module *pModule;
6410764077
int nArg;
6410864078
int i;
6410964079
sqlite_int64 rowid;
6411064080
Mem **apArg;
6411164081
Mem *pX;
64112
- } cm;
64082
+ } cp;
6411364083
struct OP_Trace_stack_vars {
6411464084
char *zTrace;
6411564085
char *z;
64116
- } cn;
64086
+ } cq;
6411764087
} u;
6411864088
/* End automatically generated code
6411964089
********************************************************************/
6412064090
6412164091
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
@@ -65581,10 +65551,20 @@
6558165551
sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
6558265552
}
6558365553
break;
6558465554
}
6558565555
65556
+/* Opcode: Once P1 P2 * * *
65557
+**
65558
+** Jump to P2 if the value in register P1 is a not null or zero. If
65559
+** the value is NULL or zero, fall through and change the P1 register
65560
+** to an integer 1.
65561
+**
65562
+** When P1 is not used otherwise in a program, this opcode falls through
65563
+** once and jumps on all subsequent invocations. It is the equivalent
65564
+** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
65565
+*/
6558665566
/* Opcode: If P1 P2 P3 * *
6558765567
**
6558865568
** Jump to P2 if the value in register P1 is true. The value
6558965569
** is considered true if it is numeric and non-zero. If the value
6559065570
** in P1 is NULL then take the jump if P3 is true.
@@ -65593,10 +65573,11 @@
6559365573
**
6559465574
** Jump to P2 if the value in register P1 is False. The value
6559565575
** is considered true if it has a numeric value of zero. If the value
6559665576
** in P1 is NULL then take the jump if P3 is true.
6559765577
*/
65578
+case OP_Once: /* jump, in1 */
6559865579
case OP_If: /* jump, in1 */
6559965580
case OP_IfNot: { /* jump, in1 */
6560065581
#if 0 /* local variables moved into u.al */
6560165582
int c;
6560265583
#endif /* local variables moved into u.al */
@@ -65611,10 +65592,16 @@
6561165592
#endif
6561265593
if( pOp->opcode==OP_IfNot ) u.al.c = !u.al.c;
6561365594
}
6561465595
if( u.al.c ){
6561565596
pc = pOp->p2-1;
65597
+ }else if( pOp->opcode==OP_Once ){
65598
+ assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
65599
+ memAboutToChange(p, pIn1);
65600
+ pIn1->flags = MEM_Int;
65601
+ pIn1->u.i = 1;
65602
+ REGISTER_TRACE(pOp->p1, pIn1);
6561665603
}
6561765604
break;
6561865605
}
6561965606
6562065607
/* Opcode: IsNull P1 P2 * * *
@@ -66746,17 +66733,10 @@
6674666733
** This opcode works the same as OP_OpenEphemeral. It has a
6674766734
** different name to distinguish its use. Tables created using
6674866735
** by this opcode will be used for automatically created transient
6674966736
** indices in joins.
6675066737
*/
66751
-/* Opcode: OpenSorter P1 P2 * P4 *
66752
-**
66753
-** This opcode works like OP_OpenEphemeral except that it opens
66754
-** a transient index that is specifically designed to sort large
66755
-** tables using an external merge-sort algorithm.
66756
-*/
66757
-case OP_OpenSorter:
6675866738
case OP_OpenAutoindex:
6675966739
case OP_OpenEphemeral: {
6676066740
#if 0 /* local variables moved into u.ax */
6676166741
VdbeCursor *pCx;
6676266742
#endif /* local variables moved into u.ax */
@@ -66766,11 +66746,10 @@
6676666746
SQLITE_OPEN_EXCLUSIVE |
6676766747
SQLITE_OPEN_DELETEONCLOSE |
6676866748
SQLITE_OPEN_TRANSIENT_DB;
6676966749
6677066750
assert( pOp->p1>=0 );
66771
- assert( (pOp->opcode==OP_OpenSorter)==((pOp->p5 & BTREE_SORTER)!=0) );
6677266751
u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
6677366752
if( u.ax.pCx==0 ) goto no_mem;
6677466753
u.ax.pCx->nullRow = 1;
6677566754
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
6677666755
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
@@ -66800,14 +66779,33 @@
6680066779
u.ax.pCx->isTable = 1;
6680166780
}
6680266781
}
6680366782
u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
6680466783
u.ax.pCx->isIndex = !u.ax.pCx->isTable;
66784
+ break;
66785
+}
66786
+
66787
+/* Opcode: OpenSorter P1 P2 * P4 *
66788
+**
66789
+** This opcode works like OP_OpenEphemeral except that it opens
66790
+** a transient index that is specifically designed to sort large
66791
+** tables using an external merge-sort algorithm.
66792
+*/
66793
+case OP_SorterOpen: {
66794
+#if 0 /* local variables moved into u.ay */
66795
+ VdbeCursor *pCx;
66796
+#endif /* local variables moved into u.ay */
6680566797
#ifndef SQLITE_OMIT_MERGE_SORT
66806
- if( rc==SQLITE_OK && pOp->opcode==OP_OpenSorter ){
66807
- rc = sqlite3VdbeSorterInit(db, u.ax.pCx);
66808
- }
66798
+ u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
66799
+ if( u.ay.pCx==0 ) goto no_mem;
66800
+ u.ay.pCx->pKeyInfo = pOp->p4.pKeyInfo;
66801
+ u.ay.pCx->pKeyInfo->enc = ENC(p->db);
66802
+ u.ay.pCx->isSorter = 1;
66803
+ rc = sqlite3VdbeSorterInit(db, u.ay.pCx);
66804
+#else
66805
+ pOp->opcode = OP_OpenEphemeral;
66806
+ pc--;
6680966807
#endif
6681066808
break;
6681166809
}
6681266810
6681366811
/* Opcode: OpenPseudo P1 P2 P3 * *
@@ -66824,21 +66822,21 @@
6682466822
**
6682566823
** P3 is the number of fields in the records that will be stored by
6682666824
** the pseudo-table.
6682766825
*/
6682866826
case OP_OpenPseudo: {
66829
-#if 0 /* local variables moved into u.ay */
66827
+#if 0 /* local variables moved into u.az */
6683066828
VdbeCursor *pCx;
66831
-#endif /* local variables moved into u.ay */
66829
+#endif /* local variables moved into u.az */
6683266830
6683366831
assert( pOp->p1>=0 );
66834
- u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
66835
- if( u.ay.pCx==0 ) goto no_mem;
66836
- u.ay.pCx->nullRow = 1;
66837
- u.ay.pCx->pseudoTableReg = pOp->p2;
66838
- u.ay.pCx->isTable = 1;
66839
- u.ay.pCx->isIndex = 0;
66832
+ u.az.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
66833
+ if( u.az.pCx==0 ) goto no_mem;
66834
+ u.az.pCx->nullRow = 1;
66835
+ u.az.pCx->pseudoTableReg = pOp->p2;
66836
+ u.az.pCx->isTable = 1;
66837
+ u.az.pCx->isIndex = 0;
6684066838
break;
6684166839
}
6684266840
6684366841
/* Opcode: Close P1 * * * *
6684466842
**
@@ -66906,39 +66904,39 @@
6690666904
*/
6690766905
case OP_SeekLt: /* jump, in3 */
6690866906
case OP_SeekLe: /* jump, in3 */
6690966907
case OP_SeekGe: /* jump, in3 */
6691066908
case OP_SeekGt: { /* jump, in3 */
66911
-#if 0 /* local variables moved into u.az */
66909
+#if 0 /* local variables moved into u.ba */
6691266910
int res;
6691366911
int oc;
6691466912
VdbeCursor *pC;
6691566913
UnpackedRecord r;
6691666914
int nField;
6691766915
i64 iKey; /* The rowid we are to seek to */
66918
-#endif /* local variables moved into u.az */
66916
+#endif /* local variables moved into u.ba */
6691966917
6692066918
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
6692166919
assert( pOp->p2!=0 );
66922
- u.az.pC = p->apCsr[pOp->p1];
66923
- assert( u.az.pC!=0 );
66924
- assert( u.az.pC->pseudoTableReg==0 );
66920
+ u.ba.pC = p->apCsr[pOp->p1];
66921
+ assert( u.ba.pC!=0 );
66922
+ assert( u.ba.pC->pseudoTableReg==0 );
6692566923
assert( OP_SeekLe == OP_SeekLt+1 );
6692666924
assert( OP_SeekGe == OP_SeekLt+2 );
6692766925
assert( OP_SeekGt == OP_SeekLt+3 );
66928
- assert( u.az.pC->isOrdered );
66929
- if( ALWAYS(u.az.pC->pCursor!=0) ){
66930
- u.az.oc = pOp->opcode;
66931
- u.az.pC->nullRow = 0;
66932
- if( u.az.pC->isTable ){
66926
+ assert( u.ba.pC->isOrdered );
66927
+ if( ALWAYS(u.ba.pC->pCursor!=0) ){
66928
+ u.ba.oc = pOp->opcode;
66929
+ u.ba.pC->nullRow = 0;
66930
+ if( u.ba.pC->isTable ){
6693366931
/* The input value in P3 might be of any type: integer, real, string,
6693466932
** blob, or NULL. But it needs to be an integer before we can do
6693566933
** the seek, so covert it. */
6693666934
pIn3 = &aMem[pOp->p3];
6693766935
applyNumericAffinity(pIn3);
66938
- u.az.iKey = sqlite3VdbeIntValue(pIn3);
66939
- u.az.pC->rowidIsValid = 0;
66936
+ u.ba.iKey = sqlite3VdbeIntValue(pIn3);
66937
+ u.ba.pC->rowidIsValid = 0;
6694066938
6694166939
/* If the P3 value could not be converted into an integer without
6694266940
** loss of information, then special processing is required... */
6694366941
if( (pIn3->flags & MEM_Int)==0 ){
6694466942
if( (pIn3->flags & MEM_Real)==0 ){
@@ -66949,105 +66947,105 @@
6694966947
}
6695066948
/* If we reach this point, then the P3 value must be a floating
6695166949
** point number. */
6695266950
assert( (pIn3->flags & MEM_Real)!=0 );
6695366951
66954
- if( u.az.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.az.iKey || pIn3->r>0) ){
66955
- /* The P3 value is too large in magnitude to be expressed as an
66956
- ** integer. */
66957
- u.az.res = 1;
66958
- if( pIn3->r<0 ){
66959
- if( u.az.oc>=OP_SeekGe ){ assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
66960
- rc = sqlite3BtreeFirst(u.az.pC->pCursor, &u.az.res);
66961
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
66962
- }
66963
- }else{
66964
- if( u.az.oc<=OP_SeekLe ){ assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
66965
- rc = sqlite3BtreeLast(u.az.pC->pCursor, &u.az.res);
66966
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
66967
- }
66968
- }
66969
- if( u.az.res ){
66970
- pc = pOp->p2 - 1;
66971
- }
66972
- break;
66973
- }else if( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekGe ){
66974
- /* Use the ceiling() function to convert real->int */
66975
- if( pIn3->r > (double)u.az.iKey ) u.az.iKey++;
66976
- }else{
66977
- /* Use the floor() function to convert real->int */
66978
- assert( u.az.oc==OP_SeekLe || u.az.oc==OP_SeekGt );
66979
- if( pIn3->r < (double)u.az.iKey ) u.az.iKey--;
66980
- }
66981
- }
66982
- rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, 0, (u64)u.az.iKey, 0, &u.az.res);
66983
- if( rc!=SQLITE_OK ){
66984
- goto abort_due_to_error;
66985
- }
66986
- if( u.az.res==0 ){
66987
- u.az.pC->rowidIsValid = 1;
66988
- u.az.pC->lastRowid = u.az.iKey;
66989
- }
66990
- }else{
66991
- u.az.nField = pOp->p4.i;
66992
- assert( pOp->p4type==P4_INT32 );
66993
- assert( u.az.nField>0 );
66994
- u.az.r.pKeyInfo = u.az.pC->pKeyInfo;
66995
- u.az.r.nField = (u16)u.az.nField;
66996
-
66997
- /* The next line of code computes as follows, only faster:
66998
- ** if( u.az.oc==OP_SeekGt || u.az.oc==OP_SeekLe ){
66999
- ** u.az.r.flags = UNPACKED_INCRKEY;
67000
- ** }else{
67001
- ** u.az.r.flags = 0;
67002
- ** }
67003
- */
67004
- u.az.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt)));
67005
- assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY );
67006
- assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY );
67007
- assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 );
67008
- assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 );
67009
-
67010
- u.az.r.aMem = &aMem[pOp->p3];
67011
-#ifdef SQLITE_DEBUG
67012
- { int i; for(i=0; i<u.az.r.nField; i++) assert( memIsValid(&u.az.r.aMem[i]) ); }
67013
-#endif
67014
- ExpandBlob(u.az.r.aMem);
67015
- rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, &u.az.r, 0, 0, &u.az.res);
67016
- if( rc!=SQLITE_OK ){
67017
- goto abort_due_to_error;
67018
- }
67019
- u.az.pC->rowidIsValid = 0;
67020
- }
67021
- u.az.pC->deferredMoveto = 0;
67022
- u.az.pC->cacheStatus = CACHE_STALE;
67023
-#ifdef SQLITE_TEST
67024
- sqlite3_search_count++;
67025
-#endif
67026
- if( u.az.oc>=OP_SeekGe ){ assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
67027
- if( u.az.res<0 || (u.az.res==0 && u.az.oc==OP_SeekGt) ){
67028
- rc = sqlite3BtreeNext(u.az.pC->pCursor, &u.az.res);
67029
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
67030
- u.az.pC->rowidIsValid = 0;
67031
- }else{
67032
- u.az.res = 0;
67033
- }
67034
- }else{
67035
- assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
67036
- if( u.az.res>0 || (u.az.res==0 && u.az.oc==OP_SeekLt) ){
67037
- rc = sqlite3BtreePrevious(u.az.pC->pCursor, &u.az.res);
67038
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
67039
- u.az.pC->rowidIsValid = 0;
67040
- }else{
67041
- /* u.az.res might be negative because the table is empty. Check to
67042
- ** see if this is the case.
67043
- */
67044
- u.az.res = sqlite3BtreeEof(u.az.pC->pCursor);
67045
- }
67046
- }
67047
- assert( pOp->p2>0 );
67048
- if( u.az.res ){
66952
+ if( u.ba.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.ba.iKey || pIn3->r>0) ){
66953
+ /* The P3 value is too large in magnitude to be expressed as an
66954
+ ** integer. */
66955
+ u.ba.res = 1;
66956
+ if( pIn3->r<0 ){
66957
+ if( u.ba.oc>=OP_SeekGe ){ assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
66958
+ rc = sqlite3BtreeFirst(u.ba.pC->pCursor, &u.ba.res);
66959
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
66960
+ }
66961
+ }else{
66962
+ if( u.ba.oc<=OP_SeekLe ){ assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
66963
+ rc = sqlite3BtreeLast(u.ba.pC->pCursor, &u.ba.res);
66964
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
66965
+ }
66966
+ }
66967
+ if( u.ba.res ){
66968
+ pc = pOp->p2 - 1;
66969
+ }
66970
+ break;
66971
+ }else if( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekGe ){
66972
+ /* Use the ceiling() function to convert real->int */
66973
+ if( pIn3->r > (double)u.ba.iKey ) u.ba.iKey++;
66974
+ }else{
66975
+ /* Use the floor() function to convert real->int */
66976
+ assert( u.ba.oc==OP_SeekLe || u.ba.oc==OP_SeekGt );
66977
+ if( pIn3->r < (double)u.ba.iKey ) u.ba.iKey--;
66978
+ }
66979
+ }
66980
+ rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, 0, (u64)u.ba.iKey, 0, &u.ba.res);
66981
+ if( rc!=SQLITE_OK ){
66982
+ goto abort_due_to_error;
66983
+ }
66984
+ if( u.ba.res==0 ){
66985
+ u.ba.pC->rowidIsValid = 1;
66986
+ u.ba.pC->lastRowid = u.ba.iKey;
66987
+ }
66988
+ }else{
66989
+ u.ba.nField = pOp->p4.i;
66990
+ assert( pOp->p4type==P4_INT32 );
66991
+ assert( u.ba.nField>0 );
66992
+ u.ba.r.pKeyInfo = u.ba.pC->pKeyInfo;
66993
+ u.ba.r.nField = (u16)u.ba.nField;
66994
+
66995
+ /* The next line of code computes as follows, only faster:
66996
+ ** if( u.ba.oc==OP_SeekGt || u.ba.oc==OP_SeekLe ){
66997
+ ** u.ba.r.flags = UNPACKED_INCRKEY;
66998
+ ** }else{
66999
+ ** u.ba.r.flags = 0;
67000
+ ** }
67001
+ */
67002
+ u.ba.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.ba.oc - OP_SeekLt)));
67003
+ assert( u.ba.oc!=OP_SeekGt || u.ba.r.flags==UNPACKED_INCRKEY );
67004
+ assert( u.ba.oc!=OP_SeekLe || u.ba.r.flags==UNPACKED_INCRKEY );
67005
+ assert( u.ba.oc!=OP_SeekGe || u.ba.r.flags==0 );
67006
+ assert( u.ba.oc!=OP_SeekLt || u.ba.r.flags==0 );
67007
+
67008
+ u.ba.r.aMem = &aMem[pOp->p3];
67009
+#ifdef SQLITE_DEBUG
67010
+ { int i; for(i=0; i<u.ba.r.nField; i++) assert( memIsValid(&u.ba.r.aMem[i]) ); }
67011
+#endif
67012
+ ExpandBlob(u.ba.r.aMem);
67013
+ rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, &u.ba.r, 0, 0, &u.ba.res);
67014
+ if( rc!=SQLITE_OK ){
67015
+ goto abort_due_to_error;
67016
+ }
67017
+ u.ba.pC->rowidIsValid = 0;
67018
+ }
67019
+ u.ba.pC->deferredMoveto = 0;
67020
+ u.ba.pC->cacheStatus = CACHE_STALE;
67021
+#ifdef SQLITE_TEST
67022
+ sqlite3_search_count++;
67023
+#endif
67024
+ if( u.ba.oc>=OP_SeekGe ){ assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
67025
+ if( u.ba.res<0 || (u.ba.res==0 && u.ba.oc==OP_SeekGt) ){
67026
+ rc = sqlite3BtreeNext(u.ba.pC->pCursor, &u.ba.res);
67027
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
67028
+ u.ba.pC->rowidIsValid = 0;
67029
+ }else{
67030
+ u.ba.res = 0;
67031
+ }
67032
+ }else{
67033
+ assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
67034
+ if( u.ba.res>0 || (u.ba.res==0 && u.ba.oc==OP_SeekLt) ){
67035
+ rc = sqlite3BtreePrevious(u.ba.pC->pCursor, &u.ba.res);
67036
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
67037
+ u.ba.pC->rowidIsValid = 0;
67038
+ }else{
67039
+ /* u.ba.res might be negative because the table is empty. Check to
67040
+ ** see if this is the case.
67041
+ */
67042
+ u.ba.res = sqlite3BtreeEof(u.ba.pC->pCursor);
67043
+ }
67044
+ }
67045
+ assert( pOp->p2>0 );
67046
+ if( u.ba.res ){
6704967047
pc = pOp->p2 - 1;
6705067048
}
6705167049
}else{
6705267050
/* This happens when attempting to open the sqlite3_master table
6705367051
** for read access returns SQLITE_EMPTY. In this case always
@@ -67066,24 +67064,24 @@
6706667064
** This is actually a deferred seek. Nothing actually happens until
6706767065
** the cursor is used to read a record. That way, if no reads
6706867066
** occur, no unnecessary I/O happens.
6706967067
*/
6707067068
case OP_Seek: { /* in2 */
67071
-#if 0 /* local variables moved into u.ba */
67069
+#if 0 /* local variables moved into u.bb */
6707267070
VdbeCursor *pC;
67073
-#endif /* local variables moved into u.ba */
67071
+#endif /* local variables moved into u.bb */
6707467072
6707567073
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67076
- u.ba.pC = p->apCsr[pOp->p1];
67077
- assert( u.ba.pC!=0 );
67078
- if( ALWAYS(u.ba.pC->pCursor!=0) ){
67079
- assert( u.ba.pC->isTable );
67080
- u.ba.pC->nullRow = 0;
67074
+ u.bb.pC = p->apCsr[pOp->p1];
67075
+ assert( u.bb.pC!=0 );
67076
+ if( ALWAYS(u.bb.pC->pCursor!=0) ){
67077
+ assert( u.bb.pC->isTable );
67078
+ u.bb.pC->nullRow = 0;
6708167079
pIn2 = &aMem[pOp->p2];
67082
- u.ba.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
67083
- u.ba.pC->rowidIsValid = 0;
67084
- u.ba.pC->deferredMoveto = 1;
67080
+ u.bb.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
67081
+ u.bb.pC->rowidIsValid = 0;
67082
+ u.bb.pC->deferredMoveto = 1;
6708567083
}
6708667084
break;
6708767085
}
6708867086
6708967087
@@ -67111,66 +67109,67 @@
6711167109
**
6711267110
** See also: Found, NotExists, IsUnique
6711367111
*/
6711467112
case OP_NotFound: /* jump, in3 */
6711567113
case OP_Found: { /* jump, in3 */
67116
-#if 0 /* local variables moved into u.bb */
67114
+#if 0 /* local variables moved into u.bc */
6711767115
int alreadyExists;
6711867116
VdbeCursor *pC;
6711967117
int res;
67118
+ char *pFree;
6712067119
UnpackedRecord *pIdxKey;
6712167120
UnpackedRecord r;
6712267121
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
67123
-#endif /* local variables moved into u.bb */
67122
+#endif /* local variables moved into u.bc */
6712467123
6712567124
#ifdef SQLITE_TEST
6712667125
sqlite3_found_count++;
6712767126
#endif
6712867127
67129
- u.bb.alreadyExists = 0;
67128
+ u.bc.alreadyExists = 0;
6713067129
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
6713167130
assert( pOp->p4type==P4_INT32 );
67132
- u.bb.pC = p->apCsr[pOp->p1];
67133
- assert( u.bb.pC!=0 );
67131
+ u.bc.pC = p->apCsr[pOp->p1];
67132
+ assert( u.bc.pC!=0 );
6713467133
pIn3 = &aMem[pOp->p3];
67135
- if( ALWAYS(u.bb.pC->pCursor!=0) ){
67134
+ if( ALWAYS(u.bc.pC->pCursor!=0) ){
6713667135
67137
- assert( u.bb.pC->isTable==0 );
67136
+ assert( u.bc.pC->isTable==0 );
6713867137
if( pOp->p4.i>0 ){
67139
- u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo;
67140
- u.bb.r.nField = (u16)pOp->p4.i;
67141
- u.bb.r.aMem = pIn3;
67138
+ u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
67139
+ u.bc.r.nField = (u16)pOp->p4.i;
67140
+ u.bc.r.aMem = pIn3;
6714267141
#ifdef SQLITE_DEBUG
67143
- { int i; for(i=0; i<u.bb.r.nField; i++) assert( memIsValid(&u.bb.r.aMem[i]) ); }
67142
+ { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
6714467143
#endif
67145
- u.bb.r.flags = UNPACKED_PREFIX_MATCH;
67146
- u.bb.pIdxKey = &u.bb.r;
67144
+ u.bc.r.flags = UNPACKED_PREFIX_MATCH;
67145
+ u.bc.pIdxKey = &u.bc.r;
6714767146
}else{
67147
+ u.bc.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
67148
+ u.bc.pC->pKeyInfo, u.bc.aTempRec, sizeof(u.bc.aTempRec), &u.bc.pFree
67149
+ );
67150
+ if( u.bc.pIdxKey==0 ) goto no_mem;
6714867151
assert( pIn3->flags & MEM_Blob );
6714967152
assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
67150
- u.bb.pIdxKey = sqlite3VdbeRecordUnpack(u.bb.pC->pKeyInfo, pIn3->n, pIn3->z,
67151
- u.bb.aTempRec, sizeof(u.bb.aTempRec));
67152
- if( u.bb.pIdxKey==0 ){
67153
- goto no_mem;
67154
- }
67155
- u.bb.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
67156
- }
67157
- rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, u.bb.pIdxKey, 0, 0, &u.bb.res);
67153
+ sqlite3VdbeRecordUnpack(u.bc.pC->pKeyInfo, pIn3->n, pIn3->z, u.bc.pIdxKey);
67154
+ u.bc.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
67155
+ }
67156
+ rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, u.bc.pIdxKey, 0, 0, &u.bc.res);
6715867157
if( pOp->p4.i==0 ){
67159
- sqlite3VdbeDeleteUnpackedRecord(u.bb.pIdxKey);
67158
+ sqlite3DbFree(db, u.bc.pFree);
6716067159
}
6716167160
if( rc!=SQLITE_OK ){
6716267161
break;
6716367162
}
67164
- u.bb.alreadyExists = (u.bb.res==0);
67165
- u.bb.pC->deferredMoveto = 0;
67166
- u.bb.pC->cacheStatus = CACHE_STALE;
67163
+ u.bc.alreadyExists = (u.bc.res==0);
67164
+ u.bc.pC->deferredMoveto = 0;
67165
+ u.bc.pC->cacheStatus = CACHE_STALE;
6716767166
}
6716867167
if( pOp->opcode==OP_Found ){
67169
- if( u.bb.alreadyExists ) pc = pOp->p2 - 1;
67168
+ if( u.bc.alreadyExists ) pc = pOp->p2 - 1;
6717067169
}else{
67171
- if( !u.bb.alreadyExists ) pc = pOp->p2 - 1;
67170
+ if( !u.bc.alreadyExists ) pc = pOp->p2 - 1;
6717267171
}
6717367172
break;
6717467173
}
6717567174
6717667175
/* Opcode: IsUnique P1 P2 P3 P4 *
@@ -67198,67 +67197,67 @@
6719867197
** instruction.
6719967198
**
6720067199
** See also: NotFound, NotExists, Found
6720167200
*/
6720267201
case OP_IsUnique: { /* jump, in3 */
67203
-#if 0 /* local variables moved into u.bc */
67202
+#if 0 /* local variables moved into u.bd */
6720467203
u16 ii;
6720567204
VdbeCursor *pCx;
6720667205
BtCursor *pCrsr;
6720767206
u16 nField;
6720867207
Mem *aMx;
6720967208
UnpackedRecord r; /* B-Tree index search key */
6721067209
i64 R; /* Rowid stored in register P3 */
67211
-#endif /* local variables moved into u.bc */
67210
+#endif /* local variables moved into u.bd */
6721267211
6721367212
pIn3 = &aMem[pOp->p3];
67214
- u.bc.aMx = &aMem[pOp->p4.i];
67213
+ u.bd.aMx = &aMem[pOp->p4.i];
6721567214
/* Assert that the values of parameters P1 and P4 are in range. */
6721667215
assert( pOp->p4type==P4_INT32 );
6721767216
assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
6721867217
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
6721967218
6722067219
/* Find the index cursor. */
67221
- u.bc.pCx = p->apCsr[pOp->p1];
67222
- assert( u.bc.pCx->deferredMoveto==0 );
67223
- u.bc.pCx->seekResult = 0;
67224
- u.bc.pCx->cacheStatus = CACHE_STALE;
67225
- u.bc.pCrsr = u.bc.pCx->pCursor;
67220
+ u.bd.pCx = p->apCsr[pOp->p1];
67221
+ assert( u.bd.pCx->deferredMoveto==0 );
67222
+ u.bd.pCx->seekResult = 0;
67223
+ u.bd.pCx->cacheStatus = CACHE_STALE;
67224
+ u.bd.pCrsr = u.bd.pCx->pCursor;
6722667225
6722767226
/* If any of the values are NULL, take the jump. */
67228
- u.bc.nField = u.bc.pCx->pKeyInfo->nField;
67229
- for(u.bc.ii=0; u.bc.ii<u.bc.nField; u.bc.ii++){
67230
- if( u.bc.aMx[u.bc.ii].flags & MEM_Null ){
67227
+ u.bd.nField = u.bd.pCx->pKeyInfo->nField;
67228
+ for(u.bd.ii=0; u.bd.ii<u.bd.nField; u.bd.ii++){
67229
+ if( u.bd.aMx[u.bd.ii].flags & MEM_Null ){
6723167230
pc = pOp->p2 - 1;
67232
- u.bc.pCrsr = 0;
67231
+ u.bd.pCrsr = 0;
6723367232
break;
6723467233
}
6723567234
}
67236
- assert( (u.bc.aMx[u.bc.nField].flags & MEM_Null)==0 );
67235
+ assert( (u.bd.aMx[u.bd.nField].flags & MEM_Null)==0 );
6723767236
67238
- if( u.bc.pCrsr!=0 ){
67237
+ if( u.bd.pCrsr!=0 ){
6723967238
/* Populate the index search key. */
67240
- u.bc.r.pKeyInfo = u.bc.pCx->pKeyInfo;
67241
- u.bc.r.nField = u.bc.nField + 1;
67242
- u.bc.r.flags = UNPACKED_PREFIX_SEARCH;
67243
- u.bc.r.aMem = u.bc.aMx;
67239
+ u.bd.r.pKeyInfo = u.bd.pCx->pKeyInfo;
67240
+ u.bd.r.nField = u.bd.nField + 1;
67241
+ u.bd.r.flags = UNPACKED_PREFIX_SEARCH;
67242
+ u.bd.r.aMem = u.bd.aMx;
6724467243
#ifdef SQLITE_DEBUG
67245
- { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
67244
+ { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
6724667245
#endif
6724767246
67248
- /* Extract the value of u.bc.R from register P3. */
67247
+ /* Extract the value of u.bd.R from register P3. */
6724967248
sqlite3VdbeMemIntegerify(pIn3);
67250
- u.bc.R = pIn3->u.i;
67249
+ u.bd.R = pIn3->u.i;
6725167250
6725267251
/* Search the B-Tree index. If no conflicting record is found, jump
6725367252
** to P2. Otherwise, copy the rowid of the conflicting record to
6725467253
** register P3 and fall through to the next instruction. */
67255
- rc = sqlite3BtreeMovetoUnpacked(u.bc.pCrsr, &u.bc.r, 0, 0, &u.bc.pCx->seekResult);
67256
- if( (u.bc.r.flags & UNPACKED_PREFIX_SEARCH) || u.bc.r.rowid==u.bc.R ){
67254
+ rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, &u.bd.r, 0, 0, &u.bd.pCx->seekResult);
67255
+ if( (u.bd.r.flags & UNPACKED_PREFIX_SEARCH) || u.bd.r.rowid==u.bd.R ){
6725767256
pc = pOp->p2 - 1;
6725867257
}else{
67259
- pIn3->u.i = u.bc.r.rowid;
67258
+ pIn3->u.i = u.bd.r.rowid;
6726067259
}
6726167260
}
6726267261
break;
6726367262
}
6726467263
@@ -67275,46 +67274,46 @@
6727567274
** P1 is an index.
6727667275
**
6727767276
** See also: Found, NotFound, IsUnique
6727867277
*/
6727967278
case OP_NotExists: { /* jump, in3 */
67280
-#if 0 /* local variables moved into u.bd */
67279
+#if 0 /* local variables moved into u.be */
6728167280
VdbeCursor *pC;
6728267281
BtCursor *pCrsr;
6728367282
int res;
6728467283
u64 iKey;
67285
-#endif /* local variables moved into u.bd */
67284
+#endif /* local variables moved into u.be */
6728667285
6728767286
pIn3 = &aMem[pOp->p3];
6728867287
assert( pIn3->flags & MEM_Int );
6728967288
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67290
- u.bd.pC = p->apCsr[pOp->p1];
67291
- assert( u.bd.pC!=0 );
67292
- assert( u.bd.pC->isTable );
67293
- assert( u.bd.pC->pseudoTableReg==0 );
67294
- u.bd.pCrsr = u.bd.pC->pCursor;
67295
- if( ALWAYS(u.bd.pCrsr!=0) ){
67296
- u.bd.res = 0;
67297
- u.bd.iKey = pIn3->u.i;
67298
- rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res);
67299
- u.bd.pC->lastRowid = pIn3->u.i;
67300
- u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0;
67301
- u.bd.pC->nullRow = 0;
67302
- u.bd.pC->cacheStatus = CACHE_STALE;
67303
- u.bd.pC->deferredMoveto = 0;
67304
- if( u.bd.res!=0 ){
67289
+ u.be.pC = p->apCsr[pOp->p1];
67290
+ assert( u.be.pC!=0 );
67291
+ assert( u.be.pC->isTable );
67292
+ assert( u.be.pC->pseudoTableReg==0 );
67293
+ u.be.pCrsr = u.be.pC->pCursor;
67294
+ if( ALWAYS(u.be.pCrsr!=0) ){
67295
+ u.be.res = 0;
67296
+ u.be.iKey = pIn3->u.i;
67297
+ rc = sqlite3BtreeMovetoUnpacked(u.be.pCrsr, 0, u.be.iKey, 0, &u.be.res);
67298
+ u.be.pC->lastRowid = pIn3->u.i;
67299
+ u.be.pC->rowidIsValid = u.be.res==0 ?1:0;
67300
+ u.be.pC->nullRow = 0;
67301
+ u.be.pC->cacheStatus = CACHE_STALE;
67302
+ u.be.pC->deferredMoveto = 0;
67303
+ if( u.be.res!=0 ){
6730567304
pc = pOp->p2 - 1;
67306
- assert( u.bd.pC->rowidIsValid==0 );
67305
+ assert( u.be.pC->rowidIsValid==0 );
6730767306
}
67308
- u.bd.pC->seekResult = u.bd.res;
67307
+ u.be.pC->seekResult = u.be.res;
6730967308
}else{
6731067309
/* This happens when an attempt to open a read cursor on the
6731167310
** sqlite_master table returns SQLITE_EMPTY.
6731267311
*/
6731367312
pc = pOp->p2 - 1;
67314
- assert( u.bd.pC->rowidIsValid==0 );
67315
- u.bd.pC->seekResult = 0;
67313
+ assert( u.be.pC->rowidIsValid==0 );
67314
+ u.be.pC->seekResult = 0;
6731667315
}
6731767316
break;
6731867317
}
6731967318
6732067319
/* Opcode: Sequence P1 P2 * * *
@@ -67345,25 +67344,25 @@
6734567344
** an SQLITE_FULL error is generated. The P3 register is updated with the '
6734667345
** generated record number. This P3 mechanism is used to help implement the
6734767346
** AUTOINCREMENT feature.
6734867347
*/
6734967348
case OP_NewRowid: { /* out2-prerelease */
67350
-#if 0 /* local variables moved into u.be */
67349
+#if 0 /* local variables moved into u.bf */
6735167350
i64 v; /* The new rowid */
6735267351
VdbeCursor *pC; /* Cursor of table to get the new rowid */
6735367352
int res; /* Result of an sqlite3BtreeLast() */
6735467353
int cnt; /* Counter to limit the number of searches */
6735567354
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
6735667355
VdbeFrame *pFrame; /* Root frame of VDBE */
67357
-#endif /* local variables moved into u.be */
67356
+#endif /* local variables moved into u.bf */
6735867357
67359
- u.be.v = 0;
67360
- u.be.res = 0;
67358
+ u.bf.v = 0;
67359
+ u.bf.res = 0;
6736167360
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67362
- u.be.pC = p->apCsr[pOp->p1];
67363
- assert( u.be.pC!=0 );
67364
- if( NEVER(u.be.pC->pCursor==0) ){
67361
+ u.bf.pC = p->apCsr[pOp->p1];
67362
+ assert( u.bf.pC!=0 );
67363
+ if( NEVER(u.bf.pC->pCursor==0) ){
6736567364
/* The zero initialization above is all that is needed */
6736667365
}else{
6736767366
/* The next rowid or record number (different terms for the same
6736867367
** thing) is obtained in a two-step algorithm.
6736967368
**
@@ -67375,11 +67374,11 @@
6737567374
** The second algorithm is to select a rowid at random and see if
6737667375
** it already exists in the table. If it does not exist, we have
6737767376
** succeeded. If the random rowid does exist, we select a new one
6737867377
** and try again, up to 100 times.
6737967378
*/
67380
- assert( u.be.pC->isTable );
67379
+ assert( u.bf.pC->isTable );
6738167380
6738267381
#ifdef SQLITE_32BIT_ROWID
6738367382
# define MAX_ROWID 0x7fffffff
6738467383
#else
6738567384
/* Some compilers complain about constants of the form 0x7fffffffffffffff.
@@ -67387,101 +67386,101 @@
6738767386
** to provide the constant while making all compilers happy.
6738867387
*/
6738967388
# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
6739067389
#endif
6739167390
67392
- if( !u.be.pC->useRandomRowid ){
67393
- u.be.v = sqlite3BtreeGetCachedRowid(u.be.pC->pCursor);
67394
- if( u.be.v==0 ){
67395
- rc = sqlite3BtreeLast(u.be.pC->pCursor, &u.be.res);
67391
+ if( !u.bf.pC->useRandomRowid ){
67392
+ u.bf.v = sqlite3BtreeGetCachedRowid(u.bf.pC->pCursor);
67393
+ if( u.bf.v==0 ){
67394
+ rc = sqlite3BtreeLast(u.bf.pC->pCursor, &u.bf.res);
6739667395
if( rc!=SQLITE_OK ){
6739767396
goto abort_due_to_error;
6739867397
}
67399
- if( u.be.res ){
67400
- u.be.v = 1; /* IMP: R-61914-48074 */
67398
+ if( u.bf.res ){
67399
+ u.bf.v = 1; /* IMP: R-61914-48074 */
6740167400
}else{
67402
- assert( sqlite3BtreeCursorIsValid(u.be.pC->pCursor) );
67403
- rc = sqlite3BtreeKeySize(u.be.pC->pCursor, &u.be.v);
67401
+ assert( sqlite3BtreeCursorIsValid(u.bf.pC->pCursor) );
67402
+ rc = sqlite3BtreeKeySize(u.bf.pC->pCursor, &u.bf.v);
6740467403
assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
67405
- if( u.be.v==MAX_ROWID ){
67406
- u.be.pC->useRandomRowid = 1;
67404
+ if( u.bf.v==MAX_ROWID ){
67405
+ u.bf.pC->useRandomRowid = 1;
6740767406
}else{
67408
- u.be.v++; /* IMP: R-29538-34987 */
67407
+ u.bf.v++; /* IMP: R-29538-34987 */
6740967408
}
6741067409
}
6741167410
}
6741267411
6741367412
#ifndef SQLITE_OMIT_AUTOINCREMENT
6741467413
if( pOp->p3 ){
6741567414
/* Assert that P3 is a valid memory cell. */
6741667415
assert( pOp->p3>0 );
6741767416
if( p->pFrame ){
67418
- for(u.be.pFrame=p->pFrame; u.be.pFrame->pParent; u.be.pFrame=u.be.pFrame->pParent);
67417
+ for(u.bf.pFrame=p->pFrame; u.bf.pFrame->pParent; u.bf.pFrame=u.bf.pFrame->pParent);
6741967418
/* Assert that P3 is a valid memory cell. */
67420
- assert( pOp->p3<=u.be.pFrame->nMem );
67421
- u.be.pMem = &u.be.pFrame->aMem[pOp->p3];
67419
+ assert( pOp->p3<=u.bf.pFrame->nMem );
67420
+ u.bf.pMem = &u.bf.pFrame->aMem[pOp->p3];
6742267421
}else{
6742367422
/* Assert that P3 is a valid memory cell. */
6742467423
assert( pOp->p3<=p->nMem );
67425
- u.be.pMem = &aMem[pOp->p3];
67426
- memAboutToChange(p, u.be.pMem);
67427
- }
67428
- assert( memIsValid(u.be.pMem) );
67429
-
67430
- REGISTER_TRACE(pOp->p3, u.be.pMem);
67431
- sqlite3VdbeMemIntegerify(u.be.pMem);
67432
- assert( (u.be.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
67433
- if( u.be.pMem->u.i==MAX_ROWID || u.be.pC->useRandomRowid ){
67424
+ u.bf.pMem = &aMem[pOp->p3];
67425
+ memAboutToChange(p, u.bf.pMem);
67426
+ }
67427
+ assert( memIsValid(u.bf.pMem) );
67428
+
67429
+ REGISTER_TRACE(pOp->p3, u.bf.pMem);
67430
+ sqlite3VdbeMemIntegerify(u.bf.pMem);
67431
+ assert( (u.bf.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
67432
+ if( u.bf.pMem->u.i==MAX_ROWID || u.bf.pC->useRandomRowid ){
6743467433
rc = SQLITE_FULL; /* IMP: R-12275-61338 */
6743567434
goto abort_due_to_error;
6743667435
}
67437
- if( u.be.v<u.be.pMem->u.i+1 ){
67438
- u.be.v = u.be.pMem->u.i + 1;
67436
+ if( u.bf.v<u.bf.pMem->u.i+1 ){
67437
+ u.bf.v = u.bf.pMem->u.i + 1;
6743967438
}
67440
- u.be.pMem->u.i = u.be.v;
67439
+ u.bf.pMem->u.i = u.bf.v;
6744167440
}
6744267441
#endif
6744367442
67444
- sqlite3BtreeSetCachedRowid(u.be.pC->pCursor, u.be.v<MAX_ROWID ? u.be.v+1 : 0);
67443
+ sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, u.bf.v<MAX_ROWID ? u.bf.v+1 : 0);
6744567444
}
67446
- if( u.be.pC->useRandomRowid ){
67445
+ if( u.bf.pC->useRandomRowid ){
6744767446
/* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
6744867447
** largest possible integer (9223372036854775807) then the database
6744967448
** engine starts picking positive candidate ROWIDs at random until
6745067449
** it finds one that is not previously used. */
6745167450
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
6745267451
** an AUTOINCREMENT table. */
6745367452
/* on the first attempt, simply do one more than previous */
67454
- u.be.v = lastRowid;
67455
- u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
67456
- u.be.v++; /* ensure non-zero */
67457
- u.be.cnt = 0;
67458
- while( ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v,
67459
- 0, &u.be.res))==SQLITE_OK)
67460
- && (u.be.res==0)
67461
- && (++u.be.cnt<100)){
67453
+ u.bf.v = lastRowid;
67454
+ u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
67455
+ u.bf.v++; /* ensure non-zero */
67456
+ u.bf.cnt = 0;
67457
+ while( ((rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, 0, (u64)u.bf.v,
67458
+ 0, &u.bf.res))==SQLITE_OK)
67459
+ && (u.bf.res==0)
67460
+ && (++u.bf.cnt<100)){
6746267461
/* collision - try another random rowid */
67463
- sqlite3_randomness(sizeof(u.be.v), &u.be.v);
67464
- if( u.be.cnt<5 ){
67462
+ sqlite3_randomness(sizeof(u.bf.v), &u.bf.v);
67463
+ if( u.bf.cnt<5 ){
6746567464
/* try "small" random rowids for the initial attempts */
67466
- u.be.v &= 0xffffff;
67465
+ u.bf.v &= 0xffffff;
6746767466
}else{
67468
- u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
67467
+ u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
6746967468
}
67470
- u.be.v++; /* ensure non-zero */
67469
+ u.bf.v++; /* ensure non-zero */
6747167470
}
67472
- if( rc==SQLITE_OK && u.be.res==0 ){
67471
+ if( rc==SQLITE_OK && u.bf.res==0 ){
6747367472
rc = SQLITE_FULL; /* IMP: R-38219-53002 */
6747467473
goto abort_due_to_error;
6747567474
}
67476
- assert( u.be.v>0 ); /* EV: R-40812-03570 */
67475
+ assert( u.bf.v>0 ); /* EV: R-40812-03570 */
6747767476
}
67478
- u.be.pC->rowidIsValid = 0;
67479
- u.be.pC->deferredMoveto = 0;
67480
- u.be.pC->cacheStatus = CACHE_STALE;
67477
+ u.bf.pC->rowidIsValid = 0;
67478
+ u.bf.pC->deferredMoveto = 0;
67479
+ u.bf.pC->cacheStatus = CACHE_STALE;
6748167480
}
67482
- pOut->u.i = u.be.v;
67481
+ pOut->u.i = u.bf.v;
6748367482
break;
6748467483
}
6748567484
6748667485
/* Opcode: Insert P1 P2 P3 P4 P5
6748767486
**
@@ -67527,74 +67526,74 @@
6752767526
** This works exactly like OP_Insert except that the key is the
6752867527
** integer value P3, not the value of the integer stored in register P3.
6752967528
*/
6753067529
case OP_Insert:
6753167530
case OP_InsertInt: {
67532
-#if 0 /* local variables moved into u.bf */
67531
+#if 0 /* local variables moved into u.bg */
6753367532
Mem *pData; /* MEM cell holding data for the record to be inserted */
6753467533
Mem *pKey; /* MEM cell holding key for the record */
6753567534
i64 iKey; /* The integer ROWID or key for the record to be inserted */
6753667535
VdbeCursor *pC; /* Cursor to table into which insert is written */
6753767536
int nZero; /* Number of zero-bytes to append */
6753867537
int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
6753967538
const char *zDb; /* database name - used by the update hook */
6754067539
const char *zTbl; /* Table name - used by the opdate hook */
6754167540
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
67542
-#endif /* local variables moved into u.bf */
67541
+#endif /* local variables moved into u.bg */
6754367542
67544
- u.bf.pData = &aMem[pOp->p2];
67543
+ u.bg.pData = &aMem[pOp->p2];
6754567544
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67546
- assert( memIsValid(u.bf.pData) );
67547
- u.bf.pC = p->apCsr[pOp->p1];
67548
- assert( u.bf.pC!=0 );
67549
- assert( u.bf.pC->pCursor!=0 );
67550
- assert( u.bf.pC->pseudoTableReg==0 );
67551
- assert( u.bf.pC->isTable );
67552
- REGISTER_TRACE(pOp->p2, u.bf.pData);
67545
+ assert( memIsValid(u.bg.pData) );
67546
+ u.bg.pC = p->apCsr[pOp->p1];
67547
+ assert( u.bg.pC!=0 );
67548
+ assert( u.bg.pC->pCursor!=0 );
67549
+ assert( u.bg.pC->pseudoTableReg==0 );
67550
+ assert( u.bg.pC->isTable );
67551
+ REGISTER_TRACE(pOp->p2, u.bg.pData);
6755367552
6755467553
if( pOp->opcode==OP_Insert ){
67555
- u.bf.pKey = &aMem[pOp->p3];
67556
- assert( u.bf.pKey->flags & MEM_Int );
67557
- assert( memIsValid(u.bf.pKey) );
67558
- REGISTER_TRACE(pOp->p3, u.bf.pKey);
67559
- u.bf.iKey = u.bf.pKey->u.i;
67554
+ u.bg.pKey = &aMem[pOp->p3];
67555
+ assert( u.bg.pKey->flags & MEM_Int );
67556
+ assert( memIsValid(u.bg.pKey) );
67557
+ REGISTER_TRACE(pOp->p3, u.bg.pKey);
67558
+ u.bg.iKey = u.bg.pKey->u.i;
6756067559
}else{
6756167560
assert( pOp->opcode==OP_InsertInt );
67562
- u.bf.iKey = pOp->p3;
67561
+ u.bg.iKey = pOp->p3;
6756367562
}
6756467563
6756567564
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
67566
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bf.iKey;
67567
- if( u.bf.pData->flags & MEM_Null ){
67568
- u.bf.pData->z = 0;
67569
- u.bf.pData->n = 0;
67570
- }else{
67571
- assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) );
67572
- }
67573
- u.bf.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bf.pC->seekResult : 0);
67574
- if( u.bf.pData->flags & MEM_Zero ){
67575
- u.bf.nZero = u.bf.pData->u.nZero;
67576
- }else{
67577
- u.bf.nZero = 0;
67578
- }
67579
- sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, 0);
67580
- rc = sqlite3BtreeInsert(u.bf.pC->pCursor, 0, u.bf.iKey,
67581
- u.bf.pData->z, u.bf.pData->n, u.bf.nZero,
67582
- pOp->p5 & OPFLAG_APPEND, u.bf.seekResult
67565
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bg.iKey;
67566
+ if( u.bg.pData->flags & MEM_Null ){
67567
+ u.bg.pData->z = 0;
67568
+ u.bg.pData->n = 0;
67569
+ }else{
67570
+ assert( u.bg.pData->flags & (MEM_Blob|MEM_Str) );
67571
+ }
67572
+ u.bg.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bg.pC->seekResult : 0);
67573
+ if( u.bg.pData->flags & MEM_Zero ){
67574
+ u.bg.nZero = u.bg.pData->u.nZero;
67575
+ }else{
67576
+ u.bg.nZero = 0;
67577
+ }
67578
+ sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
67579
+ rc = sqlite3BtreeInsert(u.bg.pC->pCursor, 0, u.bg.iKey,
67580
+ u.bg.pData->z, u.bg.pData->n, u.bg.nZero,
67581
+ pOp->p5 & OPFLAG_APPEND, u.bg.seekResult
6758367582
);
67584
- u.bf.pC->rowidIsValid = 0;
67585
- u.bf.pC->deferredMoveto = 0;
67586
- u.bf.pC->cacheStatus = CACHE_STALE;
67583
+ u.bg.pC->rowidIsValid = 0;
67584
+ u.bg.pC->deferredMoveto = 0;
67585
+ u.bg.pC->cacheStatus = CACHE_STALE;
6758767586
6758867587
/* Invoke the update-hook if required. */
6758967588
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
67590
- u.bf.zDb = db->aDb[u.bf.pC->iDb].zName;
67591
- u.bf.zTbl = pOp->p4.z;
67592
- u.bf.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
67593
- assert( u.bf.pC->isTable );
67594
- db->xUpdateCallback(db->pUpdateArg, u.bf.op, u.bf.zDb, u.bf.zTbl, u.bf.iKey);
67595
- assert( u.bf.pC->iDb>=0 );
67589
+ u.bg.zDb = db->aDb[u.bg.pC->iDb].zName;
67590
+ u.bg.zTbl = pOp->p4.z;
67591
+ u.bg.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
67592
+ assert( u.bg.pC->isTable );
67593
+ db->xUpdateCallback(db->pUpdateArg, u.bg.op, u.bg.zDb, u.bg.zTbl, u.bg.iKey);
67594
+ assert( u.bg.pC->iDb>=0 );
6759667595
}
6759767596
break;
6759867597
}
6759967598
6760067599
/* Opcode: Delete P1 P2 * P4 *
@@ -67616,51 +67615,51 @@
6761667615
** pointing to. The update hook will be invoked, if it exists.
6761767616
** If P4 is not NULL then the P1 cursor must have been positioned
6761867617
** using OP_NotFound prior to invoking this opcode.
6761967618
*/
6762067619
case OP_Delete: {
67621
-#if 0 /* local variables moved into u.bg */
67620
+#if 0 /* local variables moved into u.bh */
6762267621
i64 iKey;
6762367622
VdbeCursor *pC;
67624
-#endif /* local variables moved into u.bg */
67623
+#endif /* local variables moved into u.bh */
6762567624
67626
- u.bg.iKey = 0;
67625
+ u.bh.iKey = 0;
6762767626
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67628
- u.bg.pC = p->apCsr[pOp->p1];
67629
- assert( u.bg.pC!=0 );
67630
- assert( u.bg.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
67627
+ u.bh.pC = p->apCsr[pOp->p1];
67628
+ assert( u.bh.pC!=0 );
67629
+ assert( u.bh.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
6763167630
67632
- /* If the update-hook will be invoked, set u.bg.iKey to the rowid of the
67631
+ /* If the update-hook will be invoked, set u.bh.iKey to the rowid of the
6763367632
** row being deleted.
6763467633
*/
6763567634
if( db->xUpdateCallback && pOp->p4.z ){
67636
- assert( u.bg.pC->isTable );
67637
- assert( u.bg.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
67638
- u.bg.iKey = u.bg.pC->lastRowid;
67635
+ assert( u.bh.pC->isTable );
67636
+ assert( u.bh.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
67637
+ u.bh.iKey = u.bh.pC->lastRowid;
6763967638
}
6764067639
6764167640
/* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
6764267641
** OP_Column on the same table without any intervening operations that
67643
- ** might move or invalidate the cursor. Hence cursor u.bg.pC is always pointing
67642
+ ** might move or invalidate the cursor. Hence cursor u.bh.pC is always pointing
6764467643
** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
6764567644
** below is always a no-op and cannot fail. We will run it anyhow, though,
6764667645
** to guard against future changes to the code generator.
6764767646
**/
67648
- assert( u.bg.pC->deferredMoveto==0 );
67649
- rc = sqlite3VdbeCursorMoveto(u.bg.pC);
67647
+ assert( u.bh.pC->deferredMoveto==0 );
67648
+ rc = sqlite3VdbeCursorMoveto(u.bh.pC);
6765067649
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
6765167650
67652
- sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
67653
- rc = sqlite3BtreeDelete(u.bg.pC->pCursor);
67654
- u.bg.pC->cacheStatus = CACHE_STALE;
67651
+ sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
67652
+ rc = sqlite3BtreeDelete(u.bh.pC->pCursor);
67653
+ u.bh.pC->cacheStatus = CACHE_STALE;
6765567654
6765667655
/* Invoke the update-hook if required. */
6765767656
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
67658
- const char *zDb = db->aDb[u.bg.pC->iDb].zName;
67657
+ const char *zDb = db->aDb[u.bh.pC->iDb].zName;
6765967658
const char *zTbl = pOp->p4.z;
67660
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bg.iKey);
67661
- assert( u.bg.pC->iDb>=0 );
67659
+ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bh.iKey);
67660
+ assert( u.bh.pC->iDb>=0 );
6766267661
}
6766367662
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
6766467663
break;
6766567664
}
6766667665
/* Opcode: ResetCount * * * * *
@@ -67673,10 +67672,53 @@
6767367672
case OP_ResetCount: {
6767467673
sqlite3VdbeSetChanges(db, p->nChange);
6767567674
p->nChange = 0;
6767667675
break;
6767767676
}
67677
+
67678
+/* Opcode: SorterCompare P1 P2 P3
67679
+**
67680
+** P1 is a sorter cursor. This instruction compares the record blob in
67681
+** register P3 with the entry that the sorter cursor currently points to.
67682
+** If, excluding the rowid fields at the end, the two records are a match,
67683
+** fall through to the next instruction. Otherwise, jump to instruction P2.
67684
+*/
67685
+case OP_SorterCompare: {
67686
+#if 0 /* local variables moved into u.bi */
67687
+ VdbeCursor *pC;
67688
+ int res;
67689
+#endif /* local variables moved into u.bi */
67690
+
67691
+ u.bi.pC = p->apCsr[pOp->p1];
67692
+ assert( isSorter(u.bi.pC) );
67693
+ pIn3 = &aMem[pOp->p3];
67694
+ rc = sqlite3VdbeSorterCompare(u.bi.pC, pIn3, &u.bi.res);
67695
+ if( u.bi.res ){
67696
+ pc = pOp->p2-1;
67697
+ }
67698
+ break;
67699
+};
67700
+
67701
+/* Opcode: SorterData P1 P2 * * *
67702
+**
67703
+** Write into register P2 the current sorter data for sorter cursor P1.
67704
+*/
67705
+case OP_SorterData: {
67706
+#if 0 /* local variables moved into u.bj */
67707
+ VdbeCursor *pC;
67708
+#endif /* local variables moved into u.bj */
67709
+#ifndef SQLITE_OMIT_MERGE_SORT
67710
+ pOut = &aMem[pOp->p2];
67711
+ u.bj.pC = p->apCsr[pOp->p1];
67712
+ assert( u.bj.pC->isSorter );
67713
+ rc = sqlite3VdbeSorterRowkey(u.bj.pC, pOut);
67714
+#else
67715
+ pOp->opcode = OP_RowKey;
67716
+ pc--;
67717
+#endif
67718
+ break;
67719
+}
6767867720
6767967721
/* Opcode: RowData P1 P2 * * *
6768067722
**
6768167723
** Write into register P2 the complete row data for cursor P1.
6768267724
** There is no interpretation of the data.
@@ -67696,72 +67738,67 @@
6769667738
** If the P1 cursor must be pointing to a valid row (not a NULL row)
6769767739
** of a real table, not a pseudo-table.
6769867740
*/
6769967741
case OP_RowKey:
6770067742
case OP_RowData: {
67701
-#if 0 /* local variables moved into u.bh */
67743
+#if 0 /* local variables moved into u.bk */
6770267744
VdbeCursor *pC;
6770367745
BtCursor *pCrsr;
6770467746
u32 n;
6770567747
i64 n64;
67706
-#endif /* local variables moved into u.bh */
67748
+#endif /* local variables moved into u.bk */
6770767749
6770867750
pOut = &aMem[pOp->p2];
6770967751
memAboutToChange(p, pOut);
6771067752
6771167753
/* Note that RowKey and RowData are really exactly the same instruction */
6771267754
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67713
- u.bh.pC = p->apCsr[pOp->p1];
67714
- assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey );
67715
- assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData );
67716
- assert( u.bh.pC!=0 );
67717
- assert( u.bh.pC->nullRow==0 );
67718
- assert( u.bh.pC->pseudoTableReg==0 );
67719
-
67720
- if( isSorter(u.bh.pC) ){
67721
- assert( pOp->opcode==OP_RowKey );
67722
- rc = sqlite3VdbeSorterRowkey(u.bh.pC, pOut);
67723
- break;
67724
- }
67725
-
67726
- assert( u.bh.pC->pCursor!=0 );
67727
- u.bh.pCrsr = u.bh.pC->pCursor;
67728
- assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) );
67755
+ u.bk.pC = p->apCsr[pOp->p1];
67756
+ assert( u.bk.pC->isSorter==0 );
67757
+ assert( u.bk.pC->isTable || pOp->opcode!=OP_RowData );
67758
+ assert( u.bk.pC->isIndex || pOp->opcode==OP_RowData );
67759
+ assert( u.bk.pC!=0 );
67760
+ assert( u.bk.pC->nullRow==0 );
67761
+ assert( u.bk.pC->pseudoTableReg==0 );
67762
+ assert( !u.bk.pC->isSorter );
67763
+ assert( u.bk.pC->pCursor!=0 );
67764
+ u.bk.pCrsr = u.bk.pC->pCursor;
67765
+ assert( sqlite3BtreeCursorIsValid(u.bk.pCrsr) );
6772967766
6773067767
/* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
6773167768
** OP_Rewind/Op_Next with no intervening instructions that might invalidate
6773267769
** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always
6773367770
** a no-op and can never fail. But we leave it in place as a safety.
6773467771
*/
67735
- assert( u.bh.pC->deferredMoveto==0 );
67736
- rc = sqlite3VdbeCursorMoveto(u.bh.pC);
67737
- if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
67738
-
67739
- if( u.bh.pC->isIndex ){
67740
- assert( !u.bh.pC->isTable );
67741
- rc = sqlite3BtreeKeySize(u.bh.pCrsr, &u.bh.n64);
67742
- assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
67743
- if( u.bh.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
67744
- goto too_big;
67745
- }
67746
- u.bh.n = (u32)u.bh.n64;
67747
- }else{
67748
- rc = sqlite3BtreeDataSize(u.bh.pCrsr, &u.bh.n);
67749
- assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
67750
- if( u.bh.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
67751
- goto too_big;
67752
- }
67753
- }
67754
- if( sqlite3VdbeMemGrow(pOut, u.bh.n, 0) ){
67755
- goto no_mem;
67756
- }
67757
- pOut->n = u.bh.n;
67758
- MemSetTypeFlag(pOut, MEM_Blob);
67759
- if( u.bh.pC->isIndex ){
67760
- rc = sqlite3BtreeKey(u.bh.pCrsr, 0, u.bh.n, pOut->z);
67761
- }else{
67762
- rc = sqlite3BtreeData(u.bh.pCrsr, 0, u.bh.n, pOut->z);
67772
+ assert( u.bk.pC->deferredMoveto==0 );
67773
+ rc = sqlite3VdbeCursorMoveto(u.bk.pC);
67774
+ if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
67775
+
67776
+ if( u.bk.pC->isIndex ){
67777
+ assert( !u.bk.pC->isTable );
67778
+ rc = sqlite3BtreeKeySize(u.bk.pCrsr, &u.bk.n64);
67779
+ assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
67780
+ if( u.bk.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
67781
+ goto too_big;
67782
+ }
67783
+ u.bk.n = (u32)u.bk.n64;
67784
+ }else{
67785
+ rc = sqlite3BtreeDataSize(u.bk.pCrsr, &u.bk.n);
67786
+ assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
67787
+ if( u.bk.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
67788
+ goto too_big;
67789
+ }
67790
+ }
67791
+ if( sqlite3VdbeMemGrow(pOut, u.bk.n, 0) ){
67792
+ goto no_mem;
67793
+ }
67794
+ pOut->n = u.bk.n;
67795
+ MemSetTypeFlag(pOut, MEM_Blob);
67796
+ if( u.bk.pC->isIndex ){
67797
+ rc = sqlite3BtreeKey(u.bk.pCrsr, 0, u.bk.n, pOut->z);
67798
+ }else{
67799
+ rc = sqlite3BtreeData(u.bk.pCrsr, 0, u.bk.n, pOut->z);
6776367800
}
6776467801
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
6776567802
UPDATE_MAX_BLOBSIZE(pOut);
6776667803
break;
6776767804
}
@@ -67774,46 +67811,46 @@
6777467811
** P1 can be either an ordinary table or a virtual table. There used to
6777567812
** be a separate OP_VRowid opcode for use with virtual tables, but this
6777667813
** one opcode now works for both table types.
6777767814
*/
6777867815
case OP_Rowid: { /* out2-prerelease */
67779
-#if 0 /* local variables moved into u.bi */
67816
+#if 0 /* local variables moved into u.bl */
6778067817
VdbeCursor *pC;
6778167818
i64 v;
6778267819
sqlite3_vtab *pVtab;
6778367820
const sqlite3_module *pModule;
67784
-#endif /* local variables moved into u.bi */
67821
+#endif /* local variables moved into u.bl */
6778567822
6778667823
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67787
- u.bi.pC = p->apCsr[pOp->p1];
67788
- assert( u.bi.pC!=0 );
67789
- assert( u.bi.pC->pseudoTableReg==0 );
67790
- if( u.bi.pC->nullRow ){
67824
+ u.bl.pC = p->apCsr[pOp->p1];
67825
+ assert( u.bl.pC!=0 );
67826
+ assert( u.bl.pC->pseudoTableReg==0 );
67827
+ if( u.bl.pC->nullRow ){
6779167828
pOut->flags = MEM_Null;
6779267829
break;
67793
- }else if( u.bi.pC->deferredMoveto ){
67794
- u.bi.v = u.bi.pC->movetoTarget;
67830
+ }else if( u.bl.pC->deferredMoveto ){
67831
+ u.bl.v = u.bl.pC->movetoTarget;
6779567832
#ifndef SQLITE_OMIT_VIRTUALTABLE
67796
- }else if( u.bi.pC->pVtabCursor ){
67797
- u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab;
67798
- u.bi.pModule = u.bi.pVtab->pModule;
67799
- assert( u.bi.pModule->xRowid );
67800
- rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v);
67801
- importVtabErrMsg(p, u.bi.pVtab);
67833
+ }else if( u.bl.pC->pVtabCursor ){
67834
+ u.bl.pVtab = u.bl.pC->pVtabCursor->pVtab;
67835
+ u.bl.pModule = u.bl.pVtab->pModule;
67836
+ assert( u.bl.pModule->xRowid );
67837
+ rc = u.bl.pModule->xRowid(u.bl.pC->pVtabCursor, &u.bl.v);
67838
+ importVtabErrMsg(p, u.bl.pVtab);
6780267839
#endif /* SQLITE_OMIT_VIRTUALTABLE */
6780367840
}else{
67804
- assert( u.bi.pC->pCursor!=0 );
67805
- rc = sqlite3VdbeCursorMoveto(u.bi.pC);
67841
+ assert( u.bl.pC->pCursor!=0 );
67842
+ rc = sqlite3VdbeCursorMoveto(u.bl.pC);
6780667843
if( rc ) goto abort_due_to_error;
67807
- if( u.bi.pC->rowidIsValid ){
67808
- u.bi.v = u.bi.pC->lastRowid;
67844
+ if( u.bl.pC->rowidIsValid ){
67845
+ u.bl.v = u.bl.pC->lastRowid;
6780967846
}else{
67810
- rc = sqlite3BtreeKeySize(u.bi.pC->pCursor, &u.bi.v);
67847
+ rc = sqlite3BtreeKeySize(u.bl.pC->pCursor, &u.bl.v);
6781167848
assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */
6781267849
}
6781367850
}
67814
- pOut->u.i = u.bi.v;
67851
+ pOut->u.i = u.bl.v;
6781567852
break;
6781667853
}
6781767854
6781867855
/* Opcode: NullRow P1 * * * *
6781967856
**
@@ -67820,22 +67857,22 @@
6782067857
** Move the cursor P1 to a null row. Any OP_Column operations
6782167858
** that occur while the cursor is on the null row will always
6782267859
** write a NULL.
6782367860
*/
6782467861
case OP_NullRow: {
67825
-#if 0 /* local variables moved into u.bj */
67862
+#if 0 /* local variables moved into u.bm */
6782667863
VdbeCursor *pC;
67827
-#endif /* local variables moved into u.bj */
67864
+#endif /* local variables moved into u.bm */
6782867865
6782967866
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67830
- u.bj.pC = p->apCsr[pOp->p1];
67831
- assert( u.bj.pC!=0 );
67832
- u.bj.pC->nullRow = 1;
67833
- u.bj.pC->rowidIsValid = 0;
67834
- assert( u.bj.pC->pCursor || u.bj.pC->pVtabCursor );
67835
- if( u.bj.pC->pCursor ){
67836
- sqlite3BtreeClearCursor(u.bj.pC->pCursor);
67867
+ u.bm.pC = p->apCsr[pOp->p1];
67868
+ assert( u.bm.pC!=0 );
67869
+ u.bm.pC->nullRow = 1;
67870
+ u.bm.pC->rowidIsValid = 0;
67871
+ assert( u.bm.pC->pCursor || u.bm.pC->pVtabCursor );
67872
+ if( u.bm.pC->pCursor ){
67873
+ sqlite3BtreeClearCursor(u.bm.pC->pCursor);
6783767874
}
6783867875
break;
6783967876
}
6784067877
6784167878
/* Opcode: Last P1 P2 * * *
@@ -67845,30 +67882,30 @@
6784567882
** If the table or index is empty and P2>0, then jump immediately to P2.
6784667883
** If P2 is 0 or if the table or index is not empty, fall through
6784767884
** to the following instruction.
6784867885
*/
6784967886
case OP_Last: { /* jump */
67850
-#if 0 /* local variables moved into u.bk */
67887
+#if 0 /* local variables moved into u.bn */
6785167888
VdbeCursor *pC;
6785267889
BtCursor *pCrsr;
6785367890
int res;
67854
-#endif /* local variables moved into u.bk */
67891
+#endif /* local variables moved into u.bn */
6785567892
6785667893
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67857
- u.bk.pC = p->apCsr[pOp->p1];
67858
- assert( u.bk.pC!=0 );
67859
- u.bk.pCrsr = u.bk.pC->pCursor;
67860
- if( NEVER(u.bk.pCrsr==0) ){
67861
- u.bk.res = 1;
67894
+ u.bn.pC = p->apCsr[pOp->p1];
67895
+ assert( u.bn.pC!=0 );
67896
+ u.bn.pCrsr = u.bn.pC->pCursor;
67897
+ if( NEVER(u.bn.pCrsr==0) ){
67898
+ u.bn.res = 1;
6786267899
}else{
67863
- rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res);
67900
+ rc = sqlite3BtreeLast(u.bn.pCrsr, &u.bn.res);
6786467901
}
67865
- u.bk.pC->nullRow = (u8)u.bk.res;
67866
- u.bk.pC->deferredMoveto = 0;
67867
- u.bk.pC->rowidIsValid = 0;
67868
- u.bk.pC->cacheStatus = CACHE_STALE;
67869
- if( pOp->p2>0 && u.bk.res ){
67902
+ u.bn.pC->nullRow = (u8)u.bn.res;
67903
+ u.bn.pC->deferredMoveto = 0;
67904
+ u.bn.pC->rowidIsValid = 0;
67905
+ u.bn.pC->cacheStatus = CACHE_STALE;
67906
+ if( pOp->p2>0 && u.bn.res ){
6787067907
pc = pOp->p2 - 1;
6787167908
}
6787267909
break;
6787367910
}
6787467911
@@ -67883,10 +67920,14 @@
6788367920
** end. We use the OP_Sort opcode instead of OP_Rewind to do the
6788467921
** rewinding so that the global variable will be incremented and
6788567922
** regression tests can determine whether or not the optimizer is
6788667923
** correctly optimizing out sorts.
6788767924
*/
67925
+case OP_SorterSort: /* jump */
67926
+#ifdef SQLITE_OMIT_MERGE_SORT
67927
+ pOp->opcode = OP_Sort;
67928
+#endif
6788867929
case OP_Sort: { /* jump */
6788967930
#ifdef SQLITE_TEST
6789067931
sqlite3_sort_count++;
6789167932
sqlite3_search_count--;
6789267933
#endif
@@ -67900,34 +67941,35 @@
6790067941
** If the table or index is empty and P2>0, then jump immediately to P2.
6790167942
** If P2 is 0 or if the table or index is not empty, fall through
6790267943
** to the following instruction.
6790367944
*/
6790467945
case OP_Rewind: { /* jump */
67905
-#if 0 /* local variables moved into u.bl */
67946
+#if 0 /* local variables moved into u.bo */
6790667947
VdbeCursor *pC;
6790767948
BtCursor *pCrsr;
6790867949
int res;
67909
-#endif /* local variables moved into u.bl */
67950
+#endif /* local variables moved into u.bo */
6791067951
6791167952
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67912
- u.bl.pC = p->apCsr[pOp->p1];
67913
- assert( u.bl.pC!=0 );
67914
- u.bl.res = 1;
67915
- if( isSorter(u.bl.pC) ){
67916
- rc = sqlite3VdbeSorterRewind(db, u.bl.pC, &u.bl.res);
67953
+ u.bo.pC = p->apCsr[pOp->p1];
67954
+ assert( u.bo.pC!=0 );
67955
+ assert( u.bo.pC->isSorter==(pOp->opcode==OP_SorterSort) );
67956
+ u.bo.res = 1;
67957
+ if( isSorter(u.bo.pC) ){
67958
+ rc = sqlite3VdbeSorterRewind(db, u.bo.pC, &u.bo.res);
6791767959
}else{
67918
- u.bl.pCrsr = u.bl.pC->pCursor;
67919
- assert( u.bl.pCrsr );
67920
- rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
67921
- u.bl.pC->atFirst = u.bl.res==0 ?1:0;
67922
- u.bl.pC->deferredMoveto = 0;
67923
- u.bl.pC->cacheStatus = CACHE_STALE;
67924
- u.bl.pC->rowidIsValid = 0;
67925
- }
67926
- u.bl.pC->nullRow = (u8)u.bl.res;
67960
+ u.bo.pCrsr = u.bo.pC->pCursor;
67961
+ assert( u.bo.pCrsr );
67962
+ rc = sqlite3BtreeFirst(u.bo.pCrsr, &u.bo.res);
67963
+ u.bo.pC->atFirst = u.bo.res==0 ?1:0;
67964
+ u.bo.pC->deferredMoveto = 0;
67965
+ u.bo.pC->cacheStatus = CACHE_STALE;
67966
+ u.bo.pC->rowidIsValid = 0;
67967
+ }
67968
+ u.bo.pC->nullRow = (u8)u.bo.res;
6792767969
assert( pOp->p2>0 && pOp->p2<p->nOp );
67928
- if( u.bl.res ){
67970
+ if( u.bo.res ){
6792967971
pc = pOp->p2 - 1;
6793067972
}
6793167973
break;
6793267974
}
6793367975
@@ -67961,45 +68003,50 @@
6796168003
** sqlite3BtreePrevious().
6796268004
**
6796368005
** If P5 is positive and the jump is taken, then event counter
6796468006
** number P5-1 in the prepared statement is incremented.
6796568007
*/
68008
+case OP_SorterNext: /* jump */
68009
+#ifdef SQLITE_OMIT_MERGE_SORT
68010
+ pOp->opcode = OP_Next;
68011
+#endif
6796668012
case OP_Prev: /* jump */
6796768013
case OP_Next: { /* jump */
67968
-#if 0 /* local variables moved into u.bm */
68014
+#if 0 /* local variables moved into u.bp */
6796968015
VdbeCursor *pC;
6797068016
int res;
67971
-#endif /* local variables moved into u.bm */
68017
+#endif /* local variables moved into u.bp */
6797268018
6797368019
CHECK_FOR_INTERRUPT;
6797468020
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
6797568021
assert( pOp->p5<=ArraySize(p->aCounter) );
67976
- u.bm.pC = p->apCsr[pOp->p1];
67977
- if( u.bm.pC==0 ){
68022
+ u.bp.pC = p->apCsr[pOp->p1];
68023
+ if( u.bp.pC==0 ){
6797868024
break; /* See ticket #2273 */
6797968025
}
67980
- if( isSorter(u.bm.pC) ){
67981
- assert( pOp->opcode==OP_Next );
67982
- rc = sqlite3VdbeSorterNext(db, u.bm.pC, &u.bm.res);
68026
+ assert( u.bp.pC->isSorter==(pOp->opcode==OP_SorterNext) );
68027
+ if( isSorter(u.bp.pC) ){
68028
+ assert( pOp->opcode==OP_SorterNext );
68029
+ rc = sqlite3VdbeSorterNext(db, u.bp.pC, &u.bp.res);
6798368030
}else{
67984
- u.bm.res = 1;
67985
- assert( u.bm.pC->deferredMoveto==0 );
67986
- assert( u.bm.pC->pCursor );
68031
+ u.bp.res = 1;
68032
+ assert( u.bp.pC->deferredMoveto==0 );
68033
+ assert( u.bp.pC->pCursor );
6798768034
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
6798868035
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
67989
- rc = pOp->p4.xAdvance(u.bm.pC->pCursor, &u.bm.res);
68036
+ rc = pOp->p4.xAdvance(u.bp.pC->pCursor, &u.bp.res);
6799068037
}
67991
- u.bm.pC->nullRow = (u8)u.bm.res;
67992
- u.bm.pC->cacheStatus = CACHE_STALE;
67993
- if( u.bm.res==0 ){
68038
+ u.bp.pC->nullRow = (u8)u.bp.res;
68039
+ u.bp.pC->cacheStatus = CACHE_STALE;
68040
+ if( u.bp.res==0 ){
6799468041
pc = pOp->p2 - 1;
6799568042
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
6799668043
#ifdef SQLITE_TEST
6799768044
sqlite3_search_count++;
6799868045
#endif
6799968046
}
68000
- u.bm.pC->rowidIsValid = 0;
68047
+ u.bp.pC->rowidIsValid = 0;
6800168048
break;
6800268049
}
6800368050
6800468051
/* Opcode: IdxInsert P1 P2 P3 * P5
6800568052
**
@@ -68011,38 +68058,44 @@
6801168058
** insert is likely to be an append.
6801268059
**
6801368060
** This instruction only works for indices. The equivalent instruction
6801468061
** for tables is OP_Insert.
6801568062
*/
68063
+case OP_SorterInsert: /* in2 */
68064
+#ifdef SQLITE_OMIT_MERGE_SORT
68065
+ pOp->opcode = OP_IdxInsert;
68066
+#endif
6801668067
case OP_IdxInsert: { /* in2 */
68017
-#if 0 /* local variables moved into u.bn */
68068
+#if 0 /* local variables moved into u.bq */
6801868069
VdbeCursor *pC;
6801968070
BtCursor *pCrsr;
6802068071
int nKey;
6802168072
const char *zKey;
68022
-#endif /* local variables moved into u.bn */
68073
+#endif /* local variables moved into u.bq */
6802368074
6802468075
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68025
- u.bn.pC = p->apCsr[pOp->p1];
68026
- assert( u.bn.pC!=0 );
68076
+ u.bq.pC = p->apCsr[pOp->p1];
68077
+ assert( u.bq.pC!=0 );
68078
+ assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
6802768079
pIn2 = &aMem[pOp->p2];
6802868080
assert( pIn2->flags & MEM_Blob );
68029
- u.bn.pCrsr = u.bn.pC->pCursor;
68030
- if( ALWAYS(u.bn.pCrsr!=0) ){
68031
- assert( u.bn.pC->isTable==0 );
68081
+ u.bq.pCrsr = u.bq.pC->pCursor;
68082
+ if( ALWAYS(u.bq.pCrsr!=0) ){
68083
+ assert( u.bq.pC->isTable==0 );
6803268084
rc = ExpandBlob(pIn2);
6803368085
if( rc==SQLITE_OK ){
68034
- u.bn.nKey = pIn2->n;
68035
- u.bn.zKey = pIn2->z;
68036
- rc = sqlite3VdbeSorterWrite(db, u.bn.pC, u.bn.nKey);
68037
- if( rc==SQLITE_OK ){
68038
- rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
68039
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
68040
- );
68041
- assert( u.bn.pC->deferredMoveto==0 );
68042
- }
68043
- u.bn.pC->cacheStatus = CACHE_STALE;
68086
+ if( isSorter(u.bq.pC) ){
68087
+ rc = sqlite3VdbeSorterWrite(db, u.bq.pC, pIn2);
68088
+ }else{
68089
+ u.bq.nKey = pIn2->n;
68090
+ u.bq.zKey = pIn2->z;
68091
+ rc = sqlite3BtreeInsert(u.bq.pCrsr, u.bq.zKey, u.bq.nKey, "", 0, 0, pOp->p3,
68092
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bq.pC->seekResult : 0)
68093
+ );
68094
+ assert( u.bq.pC->deferredMoveto==0 );
68095
+ u.bq.pC->cacheStatus = CACHE_STALE;
68096
+ }
6804468097
}
6804568098
}
6804668099
break;
6804768100
}
6804868101
@@ -68051,37 +68104,37 @@
6805168104
** The content of P3 registers starting at register P2 form
6805268105
** an unpacked index key. This opcode removes that entry from the
6805368106
** index opened by cursor P1.
6805468107
*/
6805568108
case OP_IdxDelete: {
68056
-#if 0 /* local variables moved into u.bo */
68109
+#if 0 /* local variables moved into u.br */
6805768110
VdbeCursor *pC;
6805868111
BtCursor *pCrsr;
6805968112
int res;
6806068113
UnpackedRecord r;
68061
-#endif /* local variables moved into u.bo */
68114
+#endif /* local variables moved into u.br */
6806268115
6806368116
assert( pOp->p3>0 );
6806468117
assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
6806568118
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68066
- u.bo.pC = p->apCsr[pOp->p1];
68067
- assert( u.bo.pC!=0 );
68068
- u.bo.pCrsr = u.bo.pC->pCursor;
68069
- if( ALWAYS(u.bo.pCrsr!=0) ){
68070
- u.bo.r.pKeyInfo = u.bo.pC->pKeyInfo;
68071
- u.bo.r.nField = (u16)pOp->p3;
68072
- u.bo.r.flags = 0;
68073
- u.bo.r.aMem = &aMem[pOp->p2];
68119
+ u.br.pC = p->apCsr[pOp->p1];
68120
+ assert( u.br.pC!=0 );
68121
+ u.br.pCrsr = u.br.pC->pCursor;
68122
+ if( ALWAYS(u.br.pCrsr!=0) ){
68123
+ u.br.r.pKeyInfo = u.br.pC->pKeyInfo;
68124
+ u.br.r.nField = (u16)pOp->p3;
68125
+ u.br.r.flags = 0;
68126
+ u.br.r.aMem = &aMem[pOp->p2];
6807468127
#ifdef SQLITE_DEBUG
68075
- { int i; for(i=0; i<u.bo.r.nField; i++) assert( memIsValid(&u.bo.r.aMem[i]) ); }
68128
+ { int i; for(i=0; i<u.br.r.nField; i++) assert( memIsValid(&u.br.r.aMem[i]) ); }
6807668129
#endif
68077
- rc = sqlite3BtreeMovetoUnpacked(u.bo.pCrsr, &u.bo.r, 0, 0, &u.bo.res);
68078
- if( rc==SQLITE_OK && u.bo.res==0 ){
68079
- rc = sqlite3BtreeDelete(u.bo.pCrsr);
68130
+ rc = sqlite3BtreeMovetoUnpacked(u.br.pCrsr, &u.br.r, 0, 0, &u.br.res);
68131
+ if( rc==SQLITE_OK && u.br.res==0 ){
68132
+ rc = sqlite3BtreeDelete(u.br.pCrsr);
6808068133
}
68081
- assert( u.bo.pC->deferredMoveto==0 );
68082
- u.bo.pC->cacheStatus = CACHE_STALE;
68134
+ assert( u.br.pC->deferredMoveto==0 );
68135
+ u.br.pC->cacheStatus = CACHE_STALE;
6808368136
}
6808468137
break;
6808568138
}
6808668139
6808768140
/* Opcode: IdxRowid P1 P2 * * *
@@ -68091,32 +68144,32 @@
6809168144
** the rowid of the table entry to which this index entry points.
6809268145
**
6809368146
** See also: Rowid, MakeRecord.
6809468147
*/
6809568148
case OP_IdxRowid: { /* out2-prerelease */
68096
-#if 0 /* local variables moved into u.bp */
68149
+#if 0 /* local variables moved into u.bs */
6809768150
BtCursor *pCrsr;
6809868151
VdbeCursor *pC;
6809968152
i64 rowid;
68100
-#endif /* local variables moved into u.bp */
68153
+#endif /* local variables moved into u.bs */
6810168154
6810268155
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68103
- u.bp.pC = p->apCsr[pOp->p1];
68104
- assert( u.bp.pC!=0 );
68105
- u.bp.pCrsr = u.bp.pC->pCursor;
68156
+ u.bs.pC = p->apCsr[pOp->p1];
68157
+ assert( u.bs.pC!=0 );
68158
+ u.bs.pCrsr = u.bs.pC->pCursor;
6810668159
pOut->flags = MEM_Null;
68107
- if( ALWAYS(u.bp.pCrsr!=0) ){
68108
- rc = sqlite3VdbeCursorMoveto(u.bp.pC);
68160
+ if( ALWAYS(u.bs.pCrsr!=0) ){
68161
+ rc = sqlite3VdbeCursorMoveto(u.bs.pC);
6810968162
if( NEVER(rc) ) goto abort_due_to_error;
68110
- assert( u.bp.pC->deferredMoveto==0 );
68111
- assert( u.bp.pC->isTable==0 );
68112
- if( !u.bp.pC->nullRow ){
68113
- rc = sqlite3VdbeIdxRowid(db, u.bp.pCrsr, &u.bp.rowid);
68163
+ assert( u.bs.pC->deferredMoveto==0 );
68164
+ assert( u.bs.pC->isTable==0 );
68165
+ if( !u.bs.pC->nullRow ){
68166
+ rc = sqlite3VdbeIdxRowid(db, u.bs.pCrsr, &u.bs.rowid);
6811468167
if( rc!=SQLITE_OK ){
6811568168
goto abort_due_to_error;
6811668169
}
68117
- pOut->u.i = u.bp.rowid;
68170
+ pOut->u.i = u.bs.rowid;
6811868171
pOut->flags = MEM_Int;
6811968172
}
6812068173
}
6812168174
break;
6812268175
}
@@ -68147,43 +68200,43 @@
6814768200
** If P5 is non-zero then the key value is increased by an epsilon prior
6814868201
** to the comparison. This makes the opcode work like IdxLE.
6814968202
*/
6815068203
case OP_IdxLT: /* jump */
6815168204
case OP_IdxGE: { /* jump */
68152
-#if 0 /* local variables moved into u.bq */
68205
+#if 0 /* local variables moved into u.bt */
6815368206
VdbeCursor *pC;
6815468207
int res;
6815568208
UnpackedRecord r;
68156
-#endif /* local variables moved into u.bq */
68209
+#endif /* local variables moved into u.bt */
6815768210
6815868211
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68159
- u.bq.pC = p->apCsr[pOp->p1];
68160
- assert( u.bq.pC!=0 );
68161
- assert( u.bq.pC->isOrdered );
68162
- if( ALWAYS(u.bq.pC->pCursor!=0) ){
68163
- assert( u.bq.pC->deferredMoveto==0 );
68212
+ u.bt.pC = p->apCsr[pOp->p1];
68213
+ assert( u.bt.pC!=0 );
68214
+ assert( u.bt.pC->isOrdered );
68215
+ if( ALWAYS(u.bt.pC->pCursor!=0) ){
68216
+ assert( u.bt.pC->deferredMoveto==0 );
6816468217
assert( pOp->p5==0 || pOp->p5==1 );
6816568218
assert( pOp->p4type==P4_INT32 );
68166
- u.bq.r.pKeyInfo = u.bq.pC->pKeyInfo;
68167
- u.bq.r.nField = (u16)pOp->p4.i;
68219
+ u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
68220
+ u.bt.r.nField = (u16)pOp->p4.i;
6816868221
if( pOp->p5 ){
68169
- u.bq.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
68222
+ u.bt.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
6817068223
}else{
68171
- u.bq.r.flags = UNPACKED_IGNORE_ROWID;
68224
+ u.bt.r.flags = UNPACKED_IGNORE_ROWID;
6817268225
}
68173
- u.bq.r.aMem = &aMem[pOp->p3];
68226
+ u.bt.r.aMem = &aMem[pOp->p3];
6817468227
#ifdef SQLITE_DEBUG
68175
- { int i; for(i=0; i<u.bq.r.nField; i++) assert( memIsValid(&u.bq.r.aMem[i]) ); }
68228
+ { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
6817668229
#endif
68177
- rc = sqlite3VdbeIdxKeyCompare(u.bq.pC, &u.bq.r, &u.bq.res);
68230
+ rc = sqlite3VdbeIdxKeyCompare(u.bt.pC, &u.bt.r, &u.bt.res);
6817868231
if( pOp->opcode==OP_IdxLT ){
68179
- u.bq.res = -u.bq.res;
68232
+ u.bt.res = -u.bt.res;
6818068233
}else{
6818168234
assert( pOp->opcode==OP_IdxGE );
68182
- u.bq.res++;
68235
+ u.bt.res++;
6818368236
}
68184
- if( u.bq.res>0 ){
68237
+ if( u.bt.res>0 ){
6818568238
pc = pOp->p2 - 1 ;
6818668239
}
6818768240
}
6818868241
break;
6818968242
}
@@ -68207,43 +68260,43 @@
6820768260
** If AUTOVACUUM is disabled then a zero is stored in register P2.
6820868261
**
6820968262
** See also: Clear
6821068263
*/
6821168264
case OP_Destroy: { /* out2-prerelease */
68212
-#if 0 /* local variables moved into u.br */
68265
+#if 0 /* local variables moved into u.bu */
6821368266
int iMoved;
6821468267
int iCnt;
6821568268
Vdbe *pVdbe;
6821668269
int iDb;
68217
-#endif /* local variables moved into u.br */
68270
+#endif /* local variables moved into u.bu */
6821868271
#ifndef SQLITE_OMIT_VIRTUALTABLE
68219
- u.br.iCnt = 0;
68220
- for(u.br.pVdbe=db->pVdbe; u.br.pVdbe; u.br.pVdbe = u.br.pVdbe->pNext){
68221
- if( u.br.pVdbe->magic==VDBE_MAGIC_RUN && u.br.pVdbe->inVtabMethod<2 && u.br.pVdbe->pc>=0 ){
68222
- u.br.iCnt++;
68272
+ u.bu.iCnt = 0;
68273
+ for(u.bu.pVdbe=db->pVdbe; u.bu.pVdbe; u.bu.pVdbe = u.bu.pVdbe->pNext){
68274
+ if( u.bu.pVdbe->magic==VDBE_MAGIC_RUN && u.bu.pVdbe->inVtabMethod<2 && u.bu.pVdbe->pc>=0 ){
68275
+ u.bu.iCnt++;
6822368276
}
6822468277
}
6822568278
#else
68226
- u.br.iCnt = db->activeVdbeCnt;
68279
+ u.bu.iCnt = db->activeVdbeCnt;
6822768280
#endif
6822868281
pOut->flags = MEM_Null;
68229
- if( u.br.iCnt>1 ){
68282
+ if( u.bu.iCnt>1 ){
6823068283
rc = SQLITE_LOCKED;
6823168284
p->errorAction = OE_Abort;
6823268285
}else{
68233
- u.br.iDb = pOp->p3;
68234
- assert( u.br.iCnt==1 );
68235
- assert( (p->btreeMask & (((yDbMask)1)<<u.br.iDb))!=0 );
68236
- rc = sqlite3BtreeDropTable(db->aDb[u.br.iDb].pBt, pOp->p1, &u.br.iMoved);
68286
+ u.bu.iDb = pOp->p3;
68287
+ assert( u.bu.iCnt==1 );
68288
+ assert( (p->btreeMask & (((yDbMask)1)<<u.bu.iDb))!=0 );
68289
+ rc = sqlite3BtreeDropTable(db->aDb[u.bu.iDb].pBt, pOp->p1, &u.bu.iMoved);
6823768290
pOut->flags = MEM_Int;
68238
- pOut->u.i = u.br.iMoved;
68291
+ pOut->u.i = u.bu.iMoved;
6823968292
#ifndef SQLITE_OMIT_AUTOVACUUM
68240
- if( rc==SQLITE_OK && u.br.iMoved!=0 ){
68241
- sqlite3RootPageMoved(db, u.br.iDb, u.br.iMoved, pOp->p1);
68293
+ if( rc==SQLITE_OK && u.bu.iMoved!=0 ){
68294
+ sqlite3RootPageMoved(db, u.bu.iDb, u.bu.iMoved, pOp->p1);
6824268295
/* All OP_Destroy operations occur on the same btree */
68243
- assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.br.iDb+1 );
68244
- resetSchemaOnFault = u.br.iDb+1;
68296
+ assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bu.iDb+1 );
68297
+ resetSchemaOnFault = u.bu.iDb+1;
6824568298
}
6824668299
#endif
6824768300
}
6824868301
break;
6824968302
}
@@ -68265,25 +68318,25 @@
6826568318
** also incremented by the number of rows in the table being cleared.
6826668319
**
6826768320
** See also: Destroy
6826868321
*/
6826968322
case OP_Clear: {
68270
-#if 0 /* local variables moved into u.bs */
68323
+#if 0 /* local variables moved into u.bv */
6827168324
int nChange;
68272
-#endif /* local variables moved into u.bs */
68325
+#endif /* local variables moved into u.bv */
6827368326
68274
- u.bs.nChange = 0;
68327
+ u.bv.nChange = 0;
6827568328
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
6827668329
rc = sqlite3BtreeClearTable(
68277
- db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bs.nChange : 0)
68330
+ db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bv.nChange : 0)
6827868331
);
6827968332
if( pOp->p3 ){
68280
- p->nChange += u.bs.nChange;
68333
+ p->nChange += u.bv.nChange;
6828168334
if( pOp->p3>0 ){
6828268335
assert( memIsValid(&aMem[pOp->p3]) );
6828368336
memAboutToChange(p, &aMem[pOp->p3]);
68284
- aMem[pOp->p3].u.i += u.bs.nChange;
68337
+ aMem[pOp->p3].u.i += u.bv.nChange;
6828568338
}
6828668339
}
6828768340
break;
6828868341
}
6828968342
@@ -68309,29 +68362,29 @@
6830968362
**
6831068363
** See documentation on OP_CreateTable for additional information.
6831168364
*/
6831268365
case OP_CreateIndex: /* out2-prerelease */
6831368366
case OP_CreateTable: { /* out2-prerelease */
68314
-#if 0 /* local variables moved into u.bt */
68367
+#if 0 /* local variables moved into u.bw */
6831568368
int pgno;
6831668369
int flags;
6831768370
Db *pDb;
68318
-#endif /* local variables moved into u.bt */
68371
+#endif /* local variables moved into u.bw */
6831968372
68320
- u.bt.pgno = 0;
68373
+ u.bw.pgno = 0;
6832168374
assert( pOp->p1>=0 && pOp->p1<db->nDb );
6832268375
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
68323
- u.bt.pDb = &db->aDb[pOp->p1];
68324
- assert( u.bt.pDb->pBt!=0 );
68376
+ u.bw.pDb = &db->aDb[pOp->p1];
68377
+ assert( u.bw.pDb->pBt!=0 );
6832568378
if( pOp->opcode==OP_CreateTable ){
68326
- /* u.bt.flags = BTREE_INTKEY; */
68327
- u.bt.flags = BTREE_INTKEY;
68379
+ /* u.bw.flags = BTREE_INTKEY; */
68380
+ u.bw.flags = BTREE_INTKEY;
6832868381
}else{
68329
- u.bt.flags = BTREE_BLOBKEY;
68382
+ u.bw.flags = BTREE_BLOBKEY;
6833068383
}
68331
- rc = sqlite3BtreeCreateTable(u.bt.pDb->pBt, &u.bt.pgno, u.bt.flags);
68332
- pOut->u.i = u.bt.pgno;
68384
+ rc = sqlite3BtreeCreateTable(u.bw.pDb->pBt, &u.bw.pgno, u.bw.flags);
68385
+ pOut->u.i = u.bw.pgno;
6833368386
break;
6833468387
}
6833568388
6833668389
/* Opcode: ParseSchema P1 * * P4 *
6833768390
**
@@ -68340,48 +68393,48 @@
6834068393
**
6834168394
** This opcode invokes the parser to create a new virtual machine,
6834268395
** then runs the new virtual machine. It is thus a re-entrant opcode.
6834368396
*/
6834468397
case OP_ParseSchema: {
68345
-#if 0 /* local variables moved into u.bu */
68398
+#if 0 /* local variables moved into u.bx */
6834668399
int iDb;
6834768400
const char *zMaster;
6834868401
char *zSql;
6834968402
InitData initData;
68350
-#endif /* local variables moved into u.bu */
68403
+#endif /* local variables moved into u.bx */
6835168404
6835268405
/* Any prepared statement that invokes this opcode will hold mutexes
6835368406
** on every btree. This is a prerequisite for invoking
6835468407
** sqlite3InitCallback().
6835568408
*/
6835668409
#ifdef SQLITE_DEBUG
68357
- for(u.bu.iDb=0; u.bu.iDb<db->nDb; u.bu.iDb++){
68358
- assert( u.bu.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bu.iDb].pBt) );
68410
+ for(u.bx.iDb=0; u.bx.iDb<db->nDb; u.bx.iDb++){
68411
+ assert( u.bx.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bx.iDb].pBt) );
6835968412
}
6836068413
#endif
6836168414
68362
- u.bu.iDb = pOp->p1;
68363
- assert( u.bu.iDb>=0 && u.bu.iDb<db->nDb );
68364
- assert( DbHasProperty(db, u.bu.iDb, DB_SchemaLoaded) );
68415
+ u.bx.iDb = pOp->p1;
68416
+ assert( u.bx.iDb>=0 && u.bx.iDb<db->nDb );
68417
+ assert( DbHasProperty(db, u.bx.iDb, DB_SchemaLoaded) );
6836568418
/* Used to be a conditional */ {
68366
- u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb);
68367
- u.bu.initData.db = db;
68368
- u.bu.initData.iDb = pOp->p1;
68369
- u.bu.initData.pzErrMsg = &p->zErrMsg;
68370
- u.bu.zSql = sqlite3MPrintf(db,
68419
+ u.bx.zMaster = SCHEMA_TABLE(u.bx.iDb);
68420
+ u.bx.initData.db = db;
68421
+ u.bx.initData.iDb = pOp->p1;
68422
+ u.bx.initData.pzErrMsg = &p->zErrMsg;
68423
+ u.bx.zSql = sqlite3MPrintf(db,
6837168424
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
68372
- db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z);
68373
- if( u.bu.zSql==0 ){
68425
+ db->aDb[u.bx.iDb].zName, u.bx.zMaster, pOp->p4.z);
68426
+ if( u.bx.zSql==0 ){
6837468427
rc = SQLITE_NOMEM;
6837568428
}else{
6837668429
assert( db->init.busy==0 );
6837768430
db->init.busy = 1;
68378
- u.bu.initData.rc = SQLITE_OK;
68431
+ u.bx.initData.rc = SQLITE_OK;
6837968432
assert( !db->mallocFailed );
68380
- rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0);
68381
- if( rc==SQLITE_OK ) rc = u.bu.initData.rc;
68382
- sqlite3DbFree(db, u.bu.zSql);
68433
+ rc = sqlite3_exec(db, u.bx.zSql, sqlite3InitCallback, &u.bx.initData, 0);
68434
+ if( rc==SQLITE_OK ) rc = u.bx.initData.rc;
68435
+ sqlite3DbFree(db, u.bx.zSql);
6838368436
db->init.busy = 0;
6838468437
}
6838568438
}
6838668439
if( rc==SQLITE_NOMEM ){
6838768440
goto no_mem;
@@ -68460,45 +68513,45 @@
6846068513
** file, not the main database file.
6846168514
**
6846268515
** This opcode is used to implement the integrity_check pragma.
6846368516
*/
6846468517
case OP_IntegrityCk: {
68465
-#if 0 /* local variables moved into u.bv */
68518
+#if 0 /* local variables moved into u.by */
6846668519
int nRoot; /* Number of tables to check. (Number of root pages.) */
6846768520
int *aRoot; /* Array of rootpage numbers for tables to be checked */
6846868521
int j; /* Loop counter */
6846968522
int nErr; /* Number of errors reported */
6847068523
char *z; /* Text of the error report */
6847168524
Mem *pnErr; /* Register keeping track of errors remaining */
68472
-#endif /* local variables moved into u.bv */
68525
+#endif /* local variables moved into u.by */
6847368526
68474
- u.bv.nRoot = pOp->p2;
68475
- assert( u.bv.nRoot>0 );
68476
- u.bv.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bv.nRoot+1) );
68477
- if( u.bv.aRoot==0 ) goto no_mem;
68527
+ u.by.nRoot = pOp->p2;
68528
+ assert( u.by.nRoot>0 );
68529
+ u.by.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.by.nRoot+1) );
68530
+ if( u.by.aRoot==0 ) goto no_mem;
6847868531
assert( pOp->p3>0 && pOp->p3<=p->nMem );
68479
- u.bv.pnErr = &aMem[pOp->p3];
68480
- assert( (u.bv.pnErr->flags & MEM_Int)!=0 );
68481
- assert( (u.bv.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
68532
+ u.by.pnErr = &aMem[pOp->p3];
68533
+ assert( (u.by.pnErr->flags & MEM_Int)!=0 );
68534
+ assert( (u.by.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
6848268535
pIn1 = &aMem[pOp->p1];
68483
- for(u.bv.j=0; u.bv.j<u.bv.nRoot; u.bv.j++){
68484
- u.bv.aRoot[u.bv.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bv.j]);
68536
+ for(u.by.j=0; u.by.j<u.by.nRoot; u.by.j++){
68537
+ u.by.aRoot[u.by.j] = (int)sqlite3VdbeIntValue(&pIn1[u.by.j]);
6848568538
}
68486
- u.bv.aRoot[u.bv.j] = 0;
68539
+ u.by.aRoot[u.by.j] = 0;
6848768540
assert( pOp->p5<db->nDb );
6848868541
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
68489
- u.bv.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bv.aRoot, u.bv.nRoot,
68490
- (int)u.bv.pnErr->u.i, &u.bv.nErr);
68491
- sqlite3DbFree(db, u.bv.aRoot);
68492
- u.bv.pnErr->u.i -= u.bv.nErr;
68542
+ u.by.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.by.aRoot, u.by.nRoot,
68543
+ (int)u.by.pnErr->u.i, &u.by.nErr);
68544
+ sqlite3DbFree(db, u.by.aRoot);
68545
+ u.by.pnErr->u.i -= u.by.nErr;
6849368546
sqlite3VdbeMemSetNull(pIn1);
68494
- if( u.bv.nErr==0 ){
68495
- assert( u.bv.z==0 );
68496
- }else if( u.bv.z==0 ){
68547
+ if( u.by.nErr==0 ){
68548
+ assert( u.by.z==0 );
68549
+ }else if( u.by.z==0 ){
6849768550
goto no_mem;
6849868551
}else{
68499
- sqlite3VdbeMemSetStr(pIn1, u.bv.z, -1, SQLITE_UTF8, sqlite3_free);
68552
+ sqlite3VdbeMemSetStr(pIn1, u.by.z, -1, SQLITE_UTF8, sqlite3_free);
6850068553
}
6850168554
UPDATE_MAX_BLOBSIZE(pIn1);
6850268555
sqlite3VdbeChangeEncoding(pIn1, encoding);
6850368556
break;
6850468557
}
@@ -68528,24 +68581,24 @@
6852868581
** Extract the smallest value from boolean index P1 and put that value into
6852968582
** register P3. Or, if boolean index P1 is initially empty, leave P3
6853068583
** unchanged and jump to instruction P2.
6853168584
*/
6853268585
case OP_RowSetRead: { /* jump, in1, out3 */
68533
-#if 0 /* local variables moved into u.bw */
68586
+#if 0 /* local variables moved into u.bz */
6853468587
i64 val;
68535
-#endif /* local variables moved into u.bw */
68588
+#endif /* local variables moved into u.bz */
6853668589
CHECK_FOR_INTERRUPT;
6853768590
pIn1 = &aMem[pOp->p1];
6853868591
if( (pIn1->flags & MEM_RowSet)==0
68539
- || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bw.val)==0
68592
+ || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bz.val)==0
6854068593
){
6854168594
/* The boolean index is empty */
6854268595
sqlite3VdbeMemSetNull(pIn1);
6854368596
pc = pOp->p2 - 1;
6854468597
}else{
6854568598
/* A value was pulled from the index */
68546
- sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bw.val);
68599
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bz.val);
6854768600
}
6854868601
break;
6854968602
}
6855068603
6855168604
/* Opcode: RowSetTest P1 P2 P3 P4
@@ -68570,18 +68623,18 @@
6857068623
** inserted, there is no need to search to see if the same value was
6857168624
** previously inserted as part of set X (only if it was previously
6857268625
** inserted as part of some other set).
6857368626
*/
6857468627
case OP_RowSetTest: { /* jump, in1, in3 */
68575
-#if 0 /* local variables moved into u.bx */
68628
+#if 0 /* local variables moved into u.ca */
6857668629
int iSet;
6857768630
int exists;
68578
-#endif /* local variables moved into u.bx */
68631
+#endif /* local variables moved into u.ca */
6857968632
6858068633
pIn1 = &aMem[pOp->p1];
6858168634
pIn3 = &aMem[pOp->p3];
68582
- u.bx.iSet = pOp->p4.i;
68635
+ u.ca.iSet = pOp->p4.i;
6858368636
assert( pIn3->flags&MEM_Int );
6858468637
6858568638
/* If there is anything other than a rowset object in memory cell P1,
6858668639
** delete it now and initialize P1 with an empty rowset
6858768640
*/
@@ -68589,21 +68642,21 @@
6858968642
sqlite3VdbeMemSetRowSet(pIn1);
6859068643
if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
6859168644
}
6859268645
6859368646
assert( pOp->p4type==P4_INT32 );
68594
- assert( u.bx.iSet==-1 || u.bx.iSet>=0 );
68595
- if( u.bx.iSet ){
68596
- u.bx.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
68597
- (u8)(u.bx.iSet>=0 ? u.bx.iSet & 0xf : 0xff),
68647
+ assert( u.ca.iSet==-1 || u.ca.iSet>=0 );
68648
+ if( u.ca.iSet ){
68649
+ u.ca.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
68650
+ (u8)(u.ca.iSet>=0 ? u.ca.iSet & 0xf : 0xff),
6859868651
pIn3->u.i);
68599
- if( u.bx.exists ){
68652
+ if( u.ca.exists ){
6860068653
pc = pOp->p2 - 1;
6860168654
break;
6860268655
}
6860368656
}
68604
- if( u.bx.iSet>=0 ){
68657
+ if( u.ca.iSet>=0 ){
6860568658
sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
6860668659
}
6860768660
break;
6860868661
}
6860968662
@@ -68622,25 +68675,25 @@
6862268675
** memory required by the sub-vdbe at runtime.
6862368676
**
6862468677
** P4 is a pointer to the VM containing the trigger program.
6862568678
*/
6862668679
case OP_Program: { /* jump */
68627
-#if 0 /* local variables moved into u.by */
68680
+#if 0 /* local variables moved into u.cb */
6862868681
int nMem; /* Number of memory registers for sub-program */
6862968682
int nByte; /* Bytes of runtime space required for sub-program */
6863068683
Mem *pRt; /* Register to allocate runtime space */
6863168684
Mem *pMem; /* Used to iterate through memory cells */
6863268685
Mem *pEnd; /* Last memory cell in new array */
6863368686
VdbeFrame *pFrame; /* New vdbe frame to execute in */
6863468687
SubProgram *pProgram; /* Sub-program to execute */
6863568688
void *t; /* Token identifying trigger */
68636
-#endif /* local variables moved into u.by */
68689
+#endif /* local variables moved into u.cb */
6863768690
68638
- u.by.pProgram = pOp->p4.pProgram;
68639
- u.by.pRt = &aMem[pOp->p3];
68640
- assert( memIsValid(u.by.pRt) );
68641
- assert( u.by.pProgram->nOp>0 );
68691
+ u.cb.pProgram = pOp->p4.pProgram;
68692
+ u.cb.pRt = &aMem[pOp->p3];
68693
+ assert( memIsValid(u.cb.pRt) );
68694
+ assert( u.cb.pProgram->nOp>0 );
6864268695
6864368696
/* If the p5 flag is clear, then recursive invocation of triggers is
6864468697
** disabled for backwards compatibility (p5 is set if this sub-program
6864568698
** is really a trigger, not a foreign key action, and the flag set
6864668699
** and cleared by the "PRAGMA recursive_triggers" command is clear).
@@ -68650,79 +68703,79 @@
6865068703
** SubProgram (if the trigger may be executed with more than one different
6865168704
** ON CONFLICT algorithm). SubProgram structures associated with a
6865268705
** single trigger all have the same value for the SubProgram.token
6865368706
** variable. */
6865468707
if( pOp->p5 ){
68655
- u.by.t = u.by.pProgram->token;
68656
- for(u.by.pFrame=p->pFrame; u.by.pFrame && u.by.pFrame->token!=u.by.t; u.by.pFrame=u.by.pFrame->pParent);
68657
- if( u.by.pFrame ) break;
68708
+ u.cb.t = u.cb.pProgram->token;
68709
+ for(u.cb.pFrame=p->pFrame; u.cb.pFrame && u.cb.pFrame->token!=u.cb.t; u.cb.pFrame=u.cb.pFrame->pParent);
68710
+ if( u.cb.pFrame ) break;
6865868711
}
6865968712
6866068713
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
6866168714
rc = SQLITE_ERROR;
6866268715
sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
6866368716
break;
6866468717
}
6866568718
68666
- /* Register u.by.pRt is used to store the memory required to save the state
68719
+ /* Register u.cb.pRt is used to store the memory required to save the state
6866768720
** of the current program, and the memory required at runtime to execute
68668
- ** the trigger program. If this trigger has been fired before, then u.by.pRt
68721
+ ** the trigger program. If this trigger has been fired before, then u.cb.pRt
6866968722
** is already allocated. Otherwise, it must be initialized. */
68670
- if( (u.by.pRt->flags&MEM_Frame)==0 ){
68723
+ if( (u.cb.pRt->flags&MEM_Frame)==0 ){
6867168724
/* SubProgram.nMem is set to the number of memory cells used by the
6867268725
** program stored in SubProgram.aOp. As well as these, one memory
6867368726
** cell is required for each cursor used by the program. Set local
68674
- ** variable u.by.nMem (and later, VdbeFrame.nChildMem) to this value.
68727
+ ** variable u.cb.nMem (and later, VdbeFrame.nChildMem) to this value.
6867568728
*/
68676
- u.by.nMem = u.by.pProgram->nMem + u.by.pProgram->nCsr;
68677
- u.by.nByte = ROUND8(sizeof(VdbeFrame))
68678
- + u.by.nMem * sizeof(Mem)
68679
- + u.by.pProgram->nCsr * sizeof(VdbeCursor *);
68680
- u.by.pFrame = sqlite3DbMallocZero(db, u.by.nByte);
68681
- if( !u.by.pFrame ){
68729
+ u.cb.nMem = u.cb.pProgram->nMem + u.cb.pProgram->nCsr;
68730
+ u.cb.nByte = ROUND8(sizeof(VdbeFrame))
68731
+ + u.cb.nMem * sizeof(Mem)
68732
+ + u.cb.pProgram->nCsr * sizeof(VdbeCursor *);
68733
+ u.cb.pFrame = sqlite3DbMallocZero(db, u.cb.nByte);
68734
+ if( !u.cb.pFrame ){
6868268735
goto no_mem;
6868368736
}
68684
- sqlite3VdbeMemRelease(u.by.pRt);
68685
- u.by.pRt->flags = MEM_Frame;
68686
- u.by.pRt->u.pFrame = u.by.pFrame;
68687
-
68688
- u.by.pFrame->v = p;
68689
- u.by.pFrame->nChildMem = u.by.nMem;
68690
- u.by.pFrame->nChildCsr = u.by.pProgram->nCsr;
68691
- u.by.pFrame->pc = pc;
68692
- u.by.pFrame->aMem = p->aMem;
68693
- u.by.pFrame->nMem = p->nMem;
68694
- u.by.pFrame->apCsr = p->apCsr;
68695
- u.by.pFrame->nCursor = p->nCursor;
68696
- u.by.pFrame->aOp = p->aOp;
68697
- u.by.pFrame->nOp = p->nOp;
68698
- u.by.pFrame->token = u.by.pProgram->token;
68699
-
68700
- u.by.pEnd = &VdbeFrameMem(u.by.pFrame)[u.by.pFrame->nChildMem];
68701
- for(u.by.pMem=VdbeFrameMem(u.by.pFrame); u.by.pMem!=u.by.pEnd; u.by.pMem++){
68702
- u.by.pMem->flags = MEM_Null;
68703
- u.by.pMem->db = db;
68737
+ sqlite3VdbeMemRelease(u.cb.pRt);
68738
+ u.cb.pRt->flags = MEM_Frame;
68739
+ u.cb.pRt->u.pFrame = u.cb.pFrame;
68740
+
68741
+ u.cb.pFrame->v = p;
68742
+ u.cb.pFrame->nChildMem = u.cb.nMem;
68743
+ u.cb.pFrame->nChildCsr = u.cb.pProgram->nCsr;
68744
+ u.cb.pFrame->pc = pc;
68745
+ u.cb.pFrame->aMem = p->aMem;
68746
+ u.cb.pFrame->nMem = p->nMem;
68747
+ u.cb.pFrame->apCsr = p->apCsr;
68748
+ u.cb.pFrame->nCursor = p->nCursor;
68749
+ u.cb.pFrame->aOp = p->aOp;
68750
+ u.cb.pFrame->nOp = p->nOp;
68751
+ u.cb.pFrame->token = u.cb.pProgram->token;
68752
+
68753
+ u.cb.pEnd = &VdbeFrameMem(u.cb.pFrame)[u.cb.pFrame->nChildMem];
68754
+ for(u.cb.pMem=VdbeFrameMem(u.cb.pFrame); u.cb.pMem!=u.cb.pEnd; u.cb.pMem++){
68755
+ u.cb.pMem->flags = MEM_Null;
68756
+ u.cb.pMem->db = db;
6870468757
}
6870568758
}else{
68706
- u.by.pFrame = u.by.pRt->u.pFrame;
68707
- assert( u.by.pProgram->nMem+u.by.pProgram->nCsr==u.by.pFrame->nChildMem );
68708
- assert( u.by.pProgram->nCsr==u.by.pFrame->nChildCsr );
68709
- assert( pc==u.by.pFrame->pc );
68759
+ u.cb.pFrame = u.cb.pRt->u.pFrame;
68760
+ assert( u.cb.pProgram->nMem+u.cb.pProgram->nCsr==u.cb.pFrame->nChildMem );
68761
+ assert( u.cb.pProgram->nCsr==u.cb.pFrame->nChildCsr );
68762
+ assert( pc==u.cb.pFrame->pc );
6871068763
}
6871168764
6871268765
p->nFrame++;
68713
- u.by.pFrame->pParent = p->pFrame;
68714
- u.by.pFrame->lastRowid = lastRowid;
68715
- u.by.pFrame->nChange = p->nChange;
68766
+ u.cb.pFrame->pParent = p->pFrame;
68767
+ u.cb.pFrame->lastRowid = lastRowid;
68768
+ u.cb.pFrame->nChange = p->nChange;
6871668769
p->nChange = 0;
68717
- p->pFrame = u.by.pFrame;
68718
- p->aMem = aMem = &VdbeFrameMem(u.by.pFrame)[-1];
68719
- p->nMem = u.by.pFrame->nChildMem;
68720
- p->nCursor = (u16)u.by.pFrame->nChildCsr;
68770
+ p->pFrame = u.cb.pFrame;
68771
+ p->aMem = aMem = &VdbeFrameMem(u.cb.pFrame)[-1];
68772
+ p->nMem = u.cb.pFrame->nChildMem;
68773
+ p->nCursor = (u16)u.cb.pFrame->nChildCsr;
6872168774
p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
68722
- p->aOp = aOp = u.by.pProgram->aOp;
68723
- p->nOp = u.by.pProgram->nOp;
68775
+ p->aOp = aOp = u.cb.pProgram->aOp;
68776
+ p->nOp = u.cb.pProgram->nOp;
6872468777
pc = -1;
6872568778
6872668779
break;
6872768780
}
6872868781
@@ -68737,17 +68790,17 @@
6873768790
** The address of the cell in the parent frame is determined by adding
6873868791
** the value of the P1 argument to the value of the P1 argument to the
6873968792
** calling OP_Program instruction.
6874068793
*/
6874168794
case OP_Param: { /* out2-prerelease */
68742
-#if 0 /* local variables moved into u.bz */
68795
+#if 0 /* local variables moved into u.cc */
6874368796
VdbeFrame *pFrame;
6874468797
Mem *pIn;
68745
-#endif /* local variables moved into u.bz */
68746
- u.bz.pFrame = p->pFrame;
68747
- u.bz.pIn = &u.bz.pFrame->aMem[pOp->p1 + u.bz.pFrame->aOp[u.bz.pFrame->pc].p1];
68748
- sqlite3VdbeMemShallowCopy(pOut, u.bz.pIn, MEM_Ephem);
68798
+#endif /* local variables moved into u.cc */
68799
+ u.cc.pFrame = p->pFrame;
68800
+ u.cc.pIn = &u.cc.pFrame->aMem[pOp->p1 + u.cc.pFrame->aOp[u.cc.pFrame->pc].p1];
68801
+ sqlite3VdbeMemShallowCopy(pOut, u.cc.pIn, MEM_Ephem);
6874968802
break;
6875068803
}
6875168804
6875268805
#endif /* #ifndef SQLITE_OMIT_TRIGGER */
6875368806
@@ -68799,26 +68852,26 @@
6879968852
**
6880068853
** This instruction throws an error if the memory cell is not initially
6880168854
** an integer.
6880268855
*/
6880368856
case OP_MemMax: { /* in2 */
68804
-#if 0 /* local variables moved into u.ca */
68857
+#if 0 /* local variables moved into u.cd */
6880568858
Mem *pIn1;
6880668859
VdbeFrame *pFrame;
68807
-#endif /* local variables moved into u.ca */
68860
+#endif /* local variables moved into u.cd */
6880868861
if( p->pFrame ){
68809
- for(u.ca.pFrame=p->pFrame; u.ca.pFrame->pParent; u.ca.pFrame=u.ca.pFrame->pParent);
68810
- u.ca.pIn1 = &u.ca.pFrame->aMem[pOp->p1];
68862
+ for(u.cd.pFrame=p->pFrame; u.cd.pFrame->pParent; u.cd.pFrame=u.cd.pFrame->pParent);
68863
+ u.cd.pIn1 = &u.cd.pFrame->aMem[pOp->p1];
6881168864
}else{
68812
- u.ca.pIn1 = &aMem[pOp->p1];
68865
+ u.cd.pIn1 = &aMem[pOp->p1];
6881368866
}
68814
- assert( memIsValid(u.ca.pIn1) );
68815
- sqlite3VdbeMemIntegerify(u.ca.pIn1);
68867
+ assert( memIsValid(u.cd.pIn1) );
68868
+ sqlite3VdbeMemIntegerify(u.cd.pIn1);
6881668869
pIn2 = &aMem[pOp->p2];
6881768870
sqlite3VdbeMemIntegerify(pIn2);
68818
- if( u.ca.pIn1->u.i<pIn2->u.i){
68819
- u.ca.pIn1->u.i = pIn2->u.i;
68871
+ if( u.cd.pIn1->u.i<pIn2->u.i){
68872
+ u.cd.pIn1->u.i = pIn2->u.i;
6882068873
}
6882168874
break;
6882268875
}
6882368876
#endif /* SQLITE_OMIT_AUTOINCREMENT */
6882468877
@@ -68881,54 +68934,54 @@
6888168934
**
6888268935
** The P5 arguments are taken from register P2 and its
6888368936
** successors.
6888468937
*/
6888568938
case OP_AggStep: {
68886
-#if 0 /* local variables moved into u.cb */
68939
+#if 0 /* local variables moved into u.ce */
6888768940
int n;
6888868941
int i;
6888968942
Mem *pMem;
6889068943
Mem *pRec;
6889168944
sqlite3_context ctx;
6889268945
sqlite3_value **apVal;
68893
-#endif /* local variables moved into u.cb */
68894
-
68895
- u.cb.n = pOp->p5;
68896
- assert( u.cb.n>=0 );
68897
- u.cb.pRec = &aMem[pOp->p2];
68898
- u.cb.apVal = p->apArg;
68899
- assert( u.cb.apVal || u.cb.n==0 );
68900
- for(u.cb.i=0; u.cb.i<u.cb.n; u.cb.i++, u.cb.pRec++){
68901
- assert( memIsValid(u.cb.pRec) );
68902
- u.cb.apVal[u.cb.i] = u.cb.pRec;
68903
- memAboutToChange(p, u.cb.pRec);
68904
- sqlite3VdbeMemStoreType(u.cb.pRec);
68905
- }
68906
- u.cb.ctx.pFunc = pOp->p4.pFunc;
68946
+#endif /* local variables moved into u.ce */
68947
+
68948
+ u.ce.n = pOp->p5;
68949
+ assert( u.ce.n>=0 );
68950
+ u.ce.pRec = &aMem[pOp->p2];
68951
+ u.ce.apVal = p->apArg;
68952
+ assert( u.ce.apVal || u.ce.n==0 );
68953
+ for(u.ce.i=0; u.ce.i<u.ce.n; u.ce.i++, u.ce.pRec++){
68954
+ assert( memIsValid(u.ce.pRec) );
68955
+ u.ce.apVal[u.ce.i] = u.ce.pRec;
68956
+ memAboutToChange(p, u.ce.pRec);
68957
+ sqlite3VdbeMemStoreType(u.ce.pRec);
68958
+ }
68959
+ u.ce.ctx.pFunc = pOp->p4.pFunc;
6890768960
assert( pOp->p3>0 && pOp->p3<=p->nMem );
68908
- u.cb.ctx.pMem = u.cb.pMem = &aMem[pOp->p3];
68909
- u.cb.pMem->n++;
68910
- u.cb.ctx.s.flags = MEM_Null;
68911
- u.cb.ctx.s.z = 0;
68912
- u.cb.ctx.s.zMalloc = 0;
68913
- u.cb.ctx.s.xDel = 0;
68914
- u.cb.ctx.s.db = db;
68915
- u.cb.ctx.isError = 0;
68916
- u.cb.ctx.pColl = 0;
68917
- if( u.cb.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
68961
+ u.ce.ctx.pMem = u.ce.pMem = &aMem[pOp->p3];
68962
+ u.ce.pMem->n++;
68963
+ u.ce.ctx.s.flags = MEM_Null;
68964
+ u.ce.ctx.s.z = 0;
68965
+ u.ce.ctx.s.zMalloc = 0;
68966
+ u.ce.ctx.s.xDel = 0;
68967
+ u.ce.ctx.s.db = db;
68968
+ u.ce.ctx.isError = 0;
68969
+ u.ce.ctx.pColl = 0;
68970
+ if( u.ce.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
6891868971
assert( pOp>p->aOp );
6891968972
assert( pOp[-1].p4type==P4_COLLSEQ );
6892068973
assert( pOp[-1].opcode==OP_CollSeq );
68921
- u.cb.ctx.pColl = pOp[-1].p4.pColl;
68974
+ u.ce.ctx.pColl = pOp[-1].p4.pColl;
6892268975
}
68923
- (u.cb.ctx.pFunc->xStep)(&u.cb.ctx, u.cb.n, u.cb.apVal); /* IMP: R-24505-23230 */
68924
- if( u.cb.ctx.isError ){
68925
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cb.ctx.s));
68926
- rc = u.cb.ctx.isError;
68976
+ (u.ce.ctx.pFunc->xStep)(&u.ce.ctx, u.ce.n, u.ce.apVal); /* IMP: R-24505-23230 */
68977
+ if( u.ce.ctx.isError ){
68978
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ce.ctx.s));
68979
+ rc = u.ce.ctx.isError;
6892768980
}
6892868981
68929
- sqlite3VdbeMemRelease(&u.cb.ctx.s);
68982
+ sqlite3VdbeMemRelease(&u.ce.ctx.s);
6893068983
6893168984
break;
6893268985
}
6893368986
6893468987
/* Opcode: AggFinal P1 P2 * P4 *
@@ -68942,23 +68995,23 @@
6894268995
** functions that can take varying numbers of arguments. The
6894368996
** P4 argument is only needed for the degenerate case where
6894468997
** the step function was not previously called.
6894568998
*/
6894668999
case OP_AggFinal: {
68947
-#if 0 /* local variables moved into u.cc */
69000
+#if 0 /* local variables moved into u.cf */
6894869001
Mem *pMem;
68949
-#endif /* local variables moved into u.cc */
69002
+#endif /* local variables moved into u.cf */
6895069003
assert( pOp->p1>0 && pOp->p1<=p->nMem );
68951
- u.cc.pMem = &aMem[pOp->p1];
68952
- assert( (u.cc.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
68953
- rc = sqlite3VdbeMemFinalize(u.cc.pMem, pOp->p4.pFunc);
69004
+ u.cf.pMem = &aMem[pOp->p1];
69005
+ assert( (u.cf.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
69006
+ rc = sqlite3VdbeMemFinalize(u.cf.pMem, pOp->p4.pFunc);
6895469007
if( rc ){
68955
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cc.pMem));
69008
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cf.pMem));
6895669009
}
68957
- sqlite3VdbeChangeEncoding(u.cc.pMem, encoding);
68958
- UPDATE_MAX_BLOBSIZE(u.cc.pMem);
68959
- if( sqlite3VdbeMemTooBig(u.cc.pMem) ){
69010
+ sqlite3VdbeChangeEncoding(u.cf.pMem, encoding);
69011
+ UPDATE_MAX_BLOBSIZE(u.cf.pMem);
69012
+ if( sqlite3VdbeMemTooBig(u.cf.pMem) ){
6896069013
goto too_big;
6896169014
}
6896269015
break;
6896369016
}
6896469017
@@ -68973,29 +69026,29 @@
6897369026
** in the WAL that have been checkpointed after the checkpoint
6897469027
** completes into mem[P3+2]. However on an error, mem[P3+1] and
6897569028
** mem[P3+2] are initialized to -1.
6897669029
*/
6897769030
case OP_Checkpoint: {
68978
-#if 0 /* local variables moved into u.cd */
69031
+#if 0 /* local variables moved into u.cg */
6897969032
int i; /* Loop counter */
6898069033
int aRes[3]; /* Results */
6898169034
Mem *pMem; /* Write results here */
68982
-#endif /* local variables moved into u.cd */
69035
+#endif /* local variables moved into u.cg */
6898369036
68984
- u.cd.aRes[0] = 0;
68985
- u.cd.aRes[1] = u.cd.aRes[2] = -1;
69037
+ u.cg.aRes[0] = 0;
69038
+ u.cg.aRes[1] = u.cg.aRes[2] = -1;
6898669039
assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
6898769040
|| pOp->p2==SQLITE_CHECKPOINT_FULL
6898869041
|| pOp->p2==SQLITE_CHECKPOINT_RESTART
6898969042
);
68990
- rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cd.aRes[1], &u.cd.aRes[2]);
69043
+ rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cg.aRes[1], &u.cg.aRes[2]);
6899169044
if( rc==SQLITE_BUSY ){
6899269045
rc = SQLITE_OK;
68993
- u.cd.aRes[0] = 1;
69046
+ u.cg.aRes[0] = 1;
6899469047
}
68995
- for(u.cd.i=0, u.cd.pMem = &aMem[pOp->p3]; u.cd.i<3; u.cd.i++, u.cd.pMem++){
68996
- sqlite3VdbeMemSetInt64(u.cd.pMem, (i64)u.cd.aRes[u.cd.i]);
69048
+ for(u.cg.i=0, u.cg.pMem = &aMem[pOp->p3]; u.cg.i<3; u.cg.i++, u.cg.pMem++){
69049
+ sqlite3VdbeMemSetInt64(u.cg.pMem, (i64)u.cg.aRes[u.cg.i]);
6899769050
}
6899869051
break;
6899969052
};
6900069053
#endif
6900169054
@@ -69010,95 +69063,95 @@
6901069063
** If changing into or out of WAL mode the procedure is more complicated.
6901169064
**
6901269065
** Write a string containing the final journal-mode to register P2.
6901369066
*/
6901469067
case OP_JournalMode: { /* out2-prerelease */
69015
-#if 0 /* local variables moved into u.ce */
69068
+#if 0 /* local variables moved into u.ch */
6901669069
Btree *pBt; /* Btree to change journal mode of */
6901769070
Pager *pPager; /* Pager associated with pBt */
6901869071
int eNew; /* New journal mode */
6901969072
int eOld; /* The old journal mode */
6902069073
const char *zFilename; /* Name of database file for pPager */
69021
-#endif /* local variables moved into u.ce */
69022
-
69023
- u.ce.eNew = pOp->p3;
69024
- assert( u.ce.eNew==PAGER_JOURNALMODE_DELETE
69025
- || u.ce.eNew==PAGER_JOURNALMODE_TRUNCATE
69026
- || u.ce.eNew==PAGER_JOURNALMODE_PERSIST
69027
- || u.ce.eNew==PAGER_JOURNALMODE_OFF
69028
- || u.ce.eNew==PAGER_JOURNALMODE_MEMORY
69029
- || u.ce.eNew==PAGER_JOURNALMODE_WAL
69030
- || u.ce.eNew==PAGER_JOURNALMODE_QUERY
69074
+#endif /* local variables moved into u.ch */
69075
+
69076
+ u.ch.eNew = pOp->p3;
69077
+ assert( u.ch.eNew==PAGER_JOURNALMODE_DELETE
69078
+ || u.ch.eNew==PAGER_JOURNALMODE_TRUNCATE
69079
+ || u.ch.eNew==PAGER_JOURNALMODE_PERSIST
69080
+ || u.ch.eNew==PAGER_JOURNALMODE_OFF
69081
+ || u.ch.eNew==PAGER_JOURNALMODE_MEMORY
69082
+ || u.ch.eNew==PAGER_JOURNALMODE_WAL
69083
+ || u.ch.eNew==PAGER_JOURNALMODE_QUERY
6903169084
);
6903269085
assert( pOp->p1>=0 && pOp->p1<db->nDb );
6903369086
69034
- u.ce.pBt = db->aDb[pOp->p1].pBt;
69035
- u.ce.pPager = sqlite3BtreePager(u.ce.pBt);
69036
- u.ce.eOld = sqlite3PagerGetJournalMode(u.ce.pPager);
69037
- if( u.ce.eNew==PAGER_JOURNALMODE_QUERY ) u.ce.eNew = u.ce.eOld;
69038
- if( !sqlite3PagerOkToChangeJournalMode(u.ce.pPager) ) u.ce.eNew = u.ce.eOld;
69087
+ u.ch.pBt = db->aDb[pOp->p1].pBt;
69088
+ u.ch.pPager = sqlite3BtreePager(u.ch.pBt);
69089
+ u.ch.eOld = sqlite3PagerGetJournalMode(u.ch.pPager);
69090
+ if( u.ch.eNew==PAGER_JOURNALMODE_QUERY ) u.ch.eNew = u.ch.eOld;
69091
+ if( !sqlite3PagerOkToChangeJournalMode(u.ch.pPager) ) u.ch.eNew = u.ch.eOld;
6903969092
6904069093
#ifndef SQLITE_OMIT_WAL
69041
- u.ce.zFilename = sqlite3PagerFilename(u.ce.pPager);
69094
+ u.ch.zFilename = sqlite3PagerFilename(u.ch.pPager);
6904269095
6904369096
/* Do not allow a transition to journal_mode=WAL for a database
6904469097
** in temporary storage or if the VFS does not support shared memory
6904569098
*/
69046
- if( u.ce.eNew==PAGER_JOURNALMODE_WAL
69047
- && (u.ce.zFilename[0]==0 /* Temp file */
69048
- || !sqlite3PagerWalSupported(u.ce.pPager)) /* No shared-memory support */
69099
+ if( u.ch.eNew==PAGER_JOURNALMODE_WAL
69100
+ && (u.ch.zFilename[0]==0 /* Temp file */
69101
+ || !sqlite3PagerWalSupported(u.ch.pPager)) /* No shared-memory support */
6904969102
){
69050
- u.ce.eNew = u.ce.eOld;
69103
+ u.ch.eNew = u.ch.eOld;
6905169104
}
6905269105
69053
- if( (u.ce.eNew!=u.ce.eOld)
69054
- && (u.ce.eOld==PAGER_JOURNALMODE_WAL || u.ce.eNew==PAGER_JOURNALMODE_WAL)
69106
+ if( (u.ch.eNew!=u.ch.eOld)
69107
+ && (u.ch.eOld==PAGER_JOURNALMODE_WAL || u.ch.eNew==PAGER_JOURNALMODE_WAL)
6905569108
){
6905669109
if( !db->autoCommit || db->activeVdbeCnt>1 ){
6905769110
rc = SQLITE_ERROR;
6905869111
sqlite3SetString(&p->zErrMsg, db,
6905969112
"cannot change %s wal mode from within a transaction",
69060
- (u.ce.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
69113
+ (u.ch.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
6906169114
);
6906269115
break;
6906369116
}else{
6906469117
69065
- if( u.ce.eOld==PAGER_JOURNALMODE_WAL ){
69118
+ if( u.ch.eOld==PAGER_JOURNALMODE_WAL ){
6906669119
/* If leaving WAL mode, close the log file. If successful, the call
6906769120
** to PagerCloseWal() checkpoints and deletes the write-ahead-log
6906869121
** file. An EXCLUSIVE lock may still be held on the database file
6906969122
** after a successful return.
6907069123
*/
69071
- rc = sqlite3PagerCloseWal(u.ce.pPager);
69124
+ rc = sqlite3PagerCloseWal(u.ch.pPager);
6907269125
if( rc==SQLITE_OK ){
69073
- sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);
69126
+ sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);
6907469127
}
69075
- }else if( u.ce.eOld==PAGER_JOURNALMODE_MEMORY ){
69128
+ }else if( u.ch.eOld==PAGER_JOURNALMODE_MEMORY ){
6907669129
/* Cannot transition directly from MEMORY to WAL. Use mode OFF
6907769130
** as an intermediate */
69078
- sqlite3PagerSetJournalMode(u.ce.pPager, PAGER_JOURNALMODE_OFF);
69131
+ sqlite3PagerSetJournalMode(u.ch.pPager, PAGER_JOURNALMODE_OFF);
6907969132
}
6908069133
6908169134
/* Open a transaction on the database file. Regardless of the journal
6908269135
** mode, this transaction always uses a rollback journal.
6908369136
*/
69084
- assert( sqlite3BtreeIsInTrans(u.ce.pBt)==0 );
69137
+ assert( sqlite3BtreeIsInTrans(u.ch.pBt)==0 );
6908569138
if( rc==SQLITE_OK ){
69086
- rc = sqlite3BtreeSetVersion(u.ce.pBt, (u.ce.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
69139
+ rc = sqlite3BtreeSetVersion(u.ch.pBt, (u.ch.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
6908769140
}
6908869141
}
6908969142
}
6909069143
#endif /* ifndef SQLITE_OMIT_WAL */
6909169144
6909269145
if( rc ){
69093
- u.ce.eNew = u.ce.eOld;
69146
+ u.ch.eNew = u.ch.eOld;
6909469147
}
69095
- u.ce.eNew = sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);
69148
+ u.ch.eNew = sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);
6909669149
6909769150
pOut = &aMem[pOp->p2];
6909869151
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
69099
- pOut->z = (char *)sqlite3JournalModename(u.ce.eNew);
69152
+ pOut->z = (char *)sqlite3JournalModename(u.ch.eNew);
6910069153
pOut->n = sqlite3Strlen30(pOut->z);
6910169154
pOut->enc = SQLITE_UTF8;
6910269155
sqlite3VdbeChangeEncoding(pOut, encoding);
6910369156
break;
6910469157
};
@@ -69123,18 +69176,18 @@
6912369176
** Perform a single step of the incremental vacuum procedure on
6912469177
** the P1 database. If the vacuum has finished, jump to instruction
6912569178
** P2. Otherwise, fall through to the next instruction.
6912669179
*/
6912769180
case OP_IncrVacuum: { /* jump */
69128
-#if 0 /* local variables moved into u.cf */
69181
+#if 0 /* local variables moved into u.ci */
6912969182
Btree *pBt;
69130
-#endif /* local variables moved into u.cf */
69183
+#endif /* local variables moved into u.ci */
6913169184
6913269185
assert( pOp->p1>=0 && pOp->p1<db->nDb );
6913369186
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
69134
- u.cf.pBt = db->aDb[pOp->p1].pBt;
69135
- rc = sqlite3BtreeIncrVacuum(u.cf.pBt);
69187
+ u.ci.pBt = db->aDb[pOp->p1].pBt;
69188
+ rc = sqlite3BtreeIncrVacuum(u.ci.pBt);
6913669189
if( rc==SQLITE_DONE ){
6913769190
pc = pOp->p2 - 1;
6913869191
rc = SQLITE_OK;
6913969192
}
6914069193
break;
@@ -69200,16 +69253,16 @@
6920069253
** Also, whether or not P4 is set, check that this is not being called from
6920169254
** within a callback to a virtual table xSync() method. If it is, the error
6920269255
** code will be set to SQLITE_LOCKED.
6920369256
*/
6920469257
case OP_VBegin: {
69205
-#if 0 /* local variables moved into u.cg */
69258
+#if 0 /* local variables moved into u.cj */
6920669259
VTable *pVTab;
69207
-#endif /* local variables moved into u.cg */
69208
- u.cg.pVTab = pOp->p4.pVtab;
69209
- rc = sqlite3VtabBegin(db, u.cg.pVTab);
69210
- if( u.cg.pVTab ) importVtabErrMsg(p, u.cg.pVTab->pVtab);
69260
+#endif /* local variables moved into u.cj */
69261
+ u.cj.pVTab = pOp->p4.pVtab;
69262
+ rc = sqlite3VtabBegin(db, u.cj.pVTab);
69263
+ if( u.cj.pVTab ) importVtabErrMsg(p, u.cj.pVTab->pVtab);
6921169264
break;
6921269265
}
6921369266
#endif /* SQLITE_OMIT_VIRTUALTABLE */
6921469267
6921569268
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -69244,36 +69297,36 @@
6924469297
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
6924569298
** P1 is a cursor number. This opcode opens a cursor to the virtual
6924669299
** table and stores that cursor in P1.
6924769300
*/
6924869301
case OP_VOpen: {
69249
-#if 0 /* local variables moved into u.ch */
69302
+#if 0 /* local variables moved into u.ck */
6925069303
VdbeCursor *pCur;
6925169304
sqlite3_vtab_cursor *pVtabCursor;
6925269305
sqlite3_vtab *pVtab;
6925369306
sqlite3_module *pModule;
69254
-#endif /* local variables moved into u.ch */
69255
-
69256
- u.ch.pCur = 0;
69257
- u.ch.pVtabCursor = 0;
69258
- u.ch.pVtab = pOp->p4.pVtab->pVtab;
69259
- u.ch.pModule = (sqlite3_module *)u.ch.pVtab->pModule;
69260
- assert(u.ch.pVtab && u.ch.pModule);
69261
- rc = u.ch.pModule->xOpen(u.ch.pVtab, &u.ch.pVtabCursor);
69262
- importVtabErrMsg(p, u.ch.pVtab);
69307
+#endif /* local variables moved into u.ck */
69308
+
69309
+ u.ck.pCur = 0;
69310
+ u.ck.pVtabCursor = 0;
69311
+ u.ck.pVtab = pOp->p4.pVtab->pVtab;
69312
+ u.ck.pModule = (sqlite3_module *)u.ck.pVtab->pModule;
69313
+ assert(u.ck.pVtab && u.ck.pModule);
69314
+ rc = u.ck.pModule->xOpen(u.ck.pVtab, &u.ck.pVtabCursor);
69315
+ importVtabErrMsg(p, u.ck.pVtab);
6926369316
if( SQLITE_OK==rc ){
6926469317
/* Initialize sqlite3_vtab_cursor base class */
69265
- u.ch.pVtabCursor->pVtab = u.ch.pVtab;
69318
+ u.ck.pVtabCursor->pVtab = u.ck.pVtab;
6926669319
6926769320
/* Initialise vdbe cursor object */
69268
- u.ch.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
69269
- if( u.ch.pCur ){
69270
- u.ch.pCur->pVtabCursor = u.ch.pVtabCursor;
69271
- u.ch.pCur->pModule = u.ch.pVtabCursor->pVtab->pModule;
69321
+ u.ck.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
69322
+ if( u.ck.pCur ){
69323
+ u.ck.pCur->pVtabCursor = u.ck.pVtabCursor;
69324
+ u.ck.pCur->pModule = u.ck.pVtabCursor->pVtab->pModule;
6927269325
}else{
6927369326
db->mallocFailed = 1;
69274
- u.ch.pModule->xClose(u.ch.pVtabCursor);
69327
+ u.ck.pModule->xClose(u.ck.pVtabCursor);
6927569328
}
6927669329
}
6927769330
break;
6927869331
}
6927969332
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69296,11 +69349,11 @@
6929669349
** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
6929769350
**
6929869351
** A jump is made to P2 if the result set after filtering would be empty.
6929969352
*/
6930069353
case OP_VFilter: { /* jump */
69301
-#if 0 /* local variables moved into u.ci */
69354
+#if 0 /* local variables moved into u.cl */
6930269355
int nArg;
6930369356
int iQuery;
6930469357
const sqlite3_module *pModule;
6930569358
Mem *pQuery;
6930669359
Mem *pArgc;
@@ -69308,49 +69361,49 @@
6930869361
sqlite3_vtab *pVtab;
6930969362
VdbeCursor *pCur;
6931069363
int res;
6931169364
int i;
6931269365
Mem **apArg;
69313
-#endif /* local variables moved into u.ci */
69314
-
69315
- u.ci.pQuery = &aMem[pOp->p3];
69316
- u.ci.pArgc = &u.ci.pQuery[1];
69317
- u.ci.pCur = p->apCsr[pOp->p1];
69318
- assert( memIsValid(u.ci.pQuery) );
69319
- REGISTER_TRACE(pOp->p3, u.ci.pQuery);
69320
- assert( u.ci.pCur->pVtabCursor );
69321
- u.ci.pVtabCursor = u.ci.pCur->pVtabCursor;
69322
- u.ci.pVtab = u.ci.pVtabCursor->pVtab;
69323
- u.ci.pModule = u.ci.pVtab->pModule;
69366
+#endif /* local variables moved into u.cl */
69367
+
69368
+ u.cl.pQuery = &aMem[pOp->p3];
69369
+ u.cl.pArgc = &u.cl.pQuery[1];
69370
+ u.cl.pCur = p->apCsr[pOp->p1];
69371
+ assert( memIsValid(u.cl.pQuery) );
69372
+ REGISTER_TRACE(pOp->p3, u.cl.pQuery);
69373
+ assert( u.cl.pCur->pVtabCursor );
69374
+ u.cl.pVtabCursor = u.cl.pCur->pVtabCursor;
69375
+ u.cl.pVtab = u.cl.pVtabCursor->pVtab;
69376
+ u.cl.pModule = u.cl.pVtab->pModule;
6932469377
6932569378
/* Grab the index number and argc parameters */
69326
- assert( (u.ci.pQuery->flags&MEM_Int)!=0 && u.ci.pArgc->flags==MEM_Int );
69327
- u.ci.nArg = (int)u.ci.pArgc->u.i;
69328
- u.ci.iQuery = (int)u.ci.pQuery->u.i;
69379
+ assert( (u.cl.pQuery->flags&MEM_Int)!=0 && u.cl.pArgc->flags==MEM_Int );
69380
+ u.cl.nArg = (int)u.cl.pArgc->u.i;
69381
+ u.cl.iQuery = (int)u.cl.pQuery->u.i;
6932969382
6933069383
/* Invoke the xFilter method */
6933169384
{
69332
- u.ci.res = 0;
69333
- u.ci.apArg = p->apArg;
69334
- for(u.ci.i = 0; u.ci.i<u.ci.nArg; u.ci.i++){
69335
- u.ci.apArg[u.ci.i] = &u.ci.pArgc[u.ci.i+1];
69336
- sqlite3VdbeMemStoreType(u.ci.apArg[u.ci.i]);
69385
+ u.cl.res = 0;
69386
+ u.cl.apArg = p->apArg;
69387
+ for(u.cl.i = 0; u.cl.i<u.cl.nArg; u.cl.i++){
69388
+ u.cl.apArg[u.cl.i] = &u.cl.pArgc[u.cl.i+1];
69389
+ sqlite3VdbeMemStoreType(u.cl.apArg[u.cl.i]);
6933769390
}
6933869391
6933969392
p->inVtabMethod = 1;
69340
- rc = u.ci.pModule->xFilter(u.ci.pVtabCursor, u.ci.iQuery, pOp->p4.z, u.ci.nArg, u.ci.apArg);
69393
+ rc = u.cl.pModule->xFilter(u.cl.pVtabCursor, u.cl.iQuery, pOp->p4.z, u.cl.nArg, u.cl.apArg);
6934169394
p->inVtabMethod = 0;
69342
- importVtabErrMsg(p, u.ci.pVtab);
69395
+ importVtabErrMsg(p, u.cl.pVtab);
6934369396
if( rc==SQLITE_OK ){
69344
- u.ci.res = u.ci.pModule->xEof(u.ci.pVtabCursor);
69397
+ u.cl.res = u.cl.pModule->xEof(u.cl.pVtabCursor);
6934569398
}
6934669399
69347
- if( u.ci.res ){
69400
+ if( u.cl.res ){
6934869401
pc = pOp->p2 - 1;
6934969402
}
6935069403
}
69351
- u.ci.pCur->nullRow = 0;
69404
+ u.cl.pCur->nullRow = 0;
6935269405
6935369406
break;
6935469407
}
6935569408
#endif /* SQLITE_OMIT_VIRTUALTABLE */
6935669409
@@ -69360,55 +69413,55 @@
6936069413
** Store the value of the P2-th column of
6936169414
** the row of the virtual-table that the
6936269415
** P1 cursor is pointing to into register P3.
6936369416
*/
6936469417
case OP_VColumn: {
69365
-#if 0 /* local variables moved into u.cj */
69418
+#if 0 /* local variables moved into u.cm */
6936669419
sqlite3_vtab *pVtab;
6936769420
const sqlite3_module *pModule;
6936869421
Mem *pDest;
6936969422
sqlite3_context sContext;
69370
-#endif /* local variables moved into u.cj */
69423
+#endif /* local variables moved into u.cm */
6937169424
6937269425
VdbeCursor *pCur = p->apCsr[pOp->p1];
6937369426
assert( pCur->pVtabCursor );
6937469427
assert( pOp->p3>0 && pOp->p3<=p->nMem );
69375
- u.cj.pDest = &aMem[pOp->p3];
69376
- memAboutToChange(p, u.cj.pDest);
69428
+ u.cm.pDest = &aMem[pOp->p3];
69429
+ memAboutToChange(p, u.cm.pDest);
6937769430
if( pCur->nullRow ){
69378
- sqlite3VdbeMemSetNull(u.cj.pDest);
69431
+ sqlite3VdbeMemSetNull(u.cm.pDest);
6937969432
break;
6938069433
}
69381
- u.cj.pVtab = pCur->pVtabCursor->pVtab;
69382
- u.cj.pModule = u.cj.pVtab->pModule;
69383
- assert( u.cj.pModule->xColumn );
69384
- memset(&u.cj.sContext, 0, sizeof(u.cj.sContext));
69434
+ u.cm.pVtab = pCur->pVtabCursor->pVtab;
69435
+ u.cm.pModule = u.cm.pVtab->pModule;
69436
+ assert( u.cm.pModule->xColumn );
69437
+ memset(&u.cm.sContext, 0, sizeof(u.cm.sContext));
6938569438
6938669439
/* The output cell may already have a buffer allocated. Move
69387
- ** the current contents to u.cj.sContext.s so in case the user-function
69440
+ ** the current contents to u.cm.sContext.s so in case the user-function
6938869441
** can use the already allocated buffer instead of allocating a
6938969442
** new one.
6939069443
*/
69391
- sqlite3VdbeMemMove(&u.cj.sContext.s, u.cj.pDest);
69392
- MemSetTypeFlag(&u.cj.sContext.s, MEM_Null);
69444
+ sqlite3VdbeMemMove(&u.cm.sContext.s, u.cm.pDest);
69445
+ MemSetTypeFlag(&u.cm.sContext.s, MEM_Null);
6939369446
69394
- rc = u.cj.pModule->xColumn(pCur->pVtabCursor, &u.cj.sContext, pOp->p2);
69395
- importVtabErrMsg(p, u.cj.pVtab);
69396
- if( u.cj.sContext.isError ){
69397
- rc = u.cj.sContext.isError;
69447
+ rc = u.cm.pModule->xColumn(pCur->pVtabCursor, &u.cm.sContext, pOp->p2);
69448
+ importVtabErrMsg(p, u.cm.pVtab);
69449
+ if( u.cm.sContext.isError ){
69450
+ rc = u.cm.sContext.isError;
6939869451
}
6939969452
6940069453
/* Copy the result of the function to the P3 register. We
6940169454
** do this regardless of whether or not an error occurred to ensure any
69402
- ** dynamic allocation in u.cj.sContext.s (a Mem struct) is released.
69455
+ ** dynamic allocation in u.cm.sContext.s (a Mem struct) is released.
6940369456
*/
69404
- sqlite3VdbeChangeEncoding(&u.cj.sContext.s, encoding);
69405
- sqlite3VdbeMemMove(u.cj.pDest, &u.cj.sContext.s);
69406
- REGISTER_TRACE(pOp->p3, u.cj.pDest);
69407
- UPDATE_MAX_BLOBSIZE(u.cj.pDest);
69457
+ sqlite3VdbeChangeEncoding(&u.cm.sContext.s, encoding);
69458
+ sqlite3VdbeMemMove(u.cm.pDest, &u.cm.sContext.s);
69459
+ REGISTER_TRACE(pOp->p3, u.cm.pDest);
69460
+ UPDATE_MAX_BLOBSIZE(u.cm.pDest);
6940869461
69409
- if( sqlite3VdbeMemTooBig(u.cj.pDest) ){
69462
+ if( sqlite3VdbeMemTooBig(u.cm.pDest) ){
6941069463
goto too_big;
6941169464
}
6941269465
break;
6941369466
}
6941469467
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69419,42 +69472,42 @@
6941969472
** Advance virtual table P1 to the next row in its result set and
6942069473
** jump to instruction P2. Or, if the virtual table has reached
6942169474
** the end of its result set, then fall through to the next instruction.
6942269475
*/
6942369476
case OP_VNext: { /* jump */
69424
-#if 0 /* local variables moved into u.ck */
69477
+#if 0 /* local variables moved into u.cn */
6942569478
sqlite3_vtab *pVtab;
6942669479
const sqlite3_module *pModule;
6942769480
int res;
6942869481
VdbeCursor *pCur;
69429
-#endif /* local variables moved into u.ck */
69482
+#endif /* local variables moved into u.cn */
6943069483
69431
- u.ck.res = 0;
69432
- u.ck.pCur = p->apCsr[pOp->p1];
69433
- assert( u.ck.pCur->pVtabCursor );
69434
- if( u.ck.pCur->nullRow ){
69484
+ u.cn.res = 0;
69485
+ u.cn.pCur = p->apCsr[pOp->p1];
69486
+ assert( u.cn.pCur->pVtabCursor );
69487
+ if( u.cn.pCur->nullRow ){
6943569488
break;
6943669489
}
69437
- u.ck.pVtab = u.ck.pCur->pVtabCursor->pVtab;
69438
- u.ck.pModule = u.ck.pVtab->pModule;
69439
- assert( u.ck.pModule->xNext );
69490
+ u.cn.pVtab = u.cn.pCur->pVtabCursor->pVtab;
69491
+ u.cn.pModule = u.cn.pVtab->pModule;
69492
+ assert( u.cn.pModule->xNext );
6944069493
6944169494
/* Invoke the xNext() method of the module. There is no way for the
6944269495
** underlying implementation to return an error if one occurs during
6944369496
** xNext(). Instead, if an error occurs, true is returned (indicating that
6944469497
** data is available) and the error code returned when xColumn or
6944569498
** some other method is next invoked on the save virtual table cursor.
6944669499
*/
6944769500
p->inVtabMethod = 1;
69448
- rc = u.ck.pModule->xNext(u.ck.pCur->pVtabCursor);
69501
+ rc = u.cn.pModule->xNext(u.cn.pCur->pVtabCursor);
6944969502
p->inVtabMethod = 0;
69450
- importVtabErrMsg(p, u.ck.pVtab);
69503
+ importVtabErrMsg(p, u.cn.pVtab);
6945169504
if( rc==SQLITE_OK ){
69452
- u.ck.res = u.ck.pModule->xEof(u.ck.pCur->pVtabCursor);
69505
+ u.cn.res = u.cn.pModule->xEof(u.cn.pCur->pVtabCursor);
6945369506
}
6945469507
69455
- if( !u.ck.res ){
69508
+ if( !u.cn.res ){
6945669509
/* If there is data, jump to P2 */
6945769510
pc = pOp->p2 - 1;
6945869511
}
6945969512
break;
6946069513
}
@@ -69466,23 +69519,23 @@
6946669519
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
6946769520
** This opcode invokes the corresponding xRename method. The value
6946869521
** in register P1 is passed as the zName argument to the xRename method.
6946969522
*/
6947069523
case OP_VRename: {
69471
-#if 0 /* local variables moved into u.cl */
69524
+#if 0 /* local variables moved into u.co */
6947269525
sqlite3_vtab *pVtab;
6947369526
Mem *pName;
69474
-#endif /* local variables moved into u.cl */
69475
-
69476
- u.cl.pVtab = pOp->p4.pVtab->pVtab;
69477
- u.cl.pName = &aMem[pOp->p1];
69478
- assert( u.cl.pVtab->pModule->xRename );
69479
- assert( memIsValid(u.cl.pName) );
69480
- REGISTER_TRACE(pOp->p1, u.cl.pName);
69481
- assert( u.cl.pName->flags & MEM_Str );
69482
- rc = u.cl.pVtab->pModule->xRename(u.cl.pVtab, u.cl.pName->z);
69483
- importVtabErrMsg(p, u.cl.pVtab);
69527
+#endif /* local variables moved into u.co */
69528
+
69529
+ u.co.pVtab = pOp->p4.pVtab->pVtab;
69530
+ u.co.pName = &aMem[pOp->p1];
69531
+ assert( u.co.pVtab->pModule->xRename );
69532
+ assert( memIsValid(u.co.pName) );
69533
+ REGISTER_TRACE(pOp->p1, u.co.pName);
69534
+ assert( u.co.pName->flags & MEM_Str );
69535
+ rc = u.co.pVtab->pModule->xRename(u.co.pVtab, u.co.pName->z);
69536
+ importVtabErrMsg(p, u.co.pVtab);
6948469537
p->expired = 0;
6948569538
6948669539
break;
6948769540
}
6948869541
#endif
@@ -69510,45 +69563,45 @@
6951069563
** P1 is a boolean flag. If it is set to true and the xUpdate call
6951169564
** is successful, then the value returned by sqlite3_last_insert_rowid()
6951269565
** is set to the value of the rowid for the row just inserted.
6951369566
*/
6951469567
case OP_VUpdate: {
69515
-#if 0 /* local variables moved into u.cm */
69568
+#if 0 /* local variables moved into u.cp */
6951669569
sqlite3_vtab *pVtab;
6951769570
sqlite3_module *pModule;
6951869571
int nArg;
6951969572
int i;
6952069573
sqlite_int64 rowid;
6952169574
Mem **apArg;
6952269575
Mem *pX;
69523
-#endif /* local variables moved into u.cm */
69576
+#endif /* local variables moved into u.cp */
6952469577
6952569578
assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
6952669579
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
6952769580
);
69528
- u.cm.pVtab = pOp->p4.pVtab->pVtab;
69529
- u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
69530
- u.cm.nArg = pOp->p2;
69581
+ u.cp.pVtab = pOp->p4.pVtab->pVtab;
69582
+ u.cp.pModule = (sqlite3_module *)u.cp.pVtab->pModule;
69583
+ u.cp.nArg = pOp->p2;
6953169584
assert( pOp->p4type==P4_VTAB );
69532
- if( ALWAYS(u.cm.pModule->xUpdate) ){
69585
+ if( ALWAYS(u.cp.pModule->xUpdate) ){
6953369586
u8 vtabOnConflict = db->vtabOnConflict;
69534
- u.cm.apArg = p->apArg;
69535
- u.cm.pX = &aMem[pOp->p3];
69536
- for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
69537
- assert( memIsValid(u.cm.pX) );
69538
- memAboutToChange(p, u.cm.pX);
69539
- sqlite3VdbeMemStoreType(u.cm.pX);
69540
- u.cm.apArg[u.cm.i] = u.cm.pX;
69541
- u.cm.pX++;
69587
+ u.cp.apArg = p->apArg;
69588
+ u.cp.pX = &aMem[pOp->p3];
69589
+ for(u.cp.i=0; u.cp.i<u.cp.nArg; u.cp.i++){
69590
+ assert( memIsValid(u.cp.pX) );
69591
+ memAboutToChange(p, u.cp.pX);
69592
+ sqlite3VdbeMemStoreType(u.cp.pX);
69593
+ u.cp.apArg[u.cp.i] = u.cp.pX;
69594
+ u.cp.pX++;
6954269595
}
6954369596
db->vtabOnConflict = pOp->p5;
69544
- rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
69597
+ rc = u.cp.pModule->xUpdate(u.cp.pVtab, u.cp.nArg, u.cp.apArg, &u.cp.rowid);
6954569598
db->vtabOnConflict = vtabOnConflict;
69546
- importVtabErrMsg(p, u.cm.pVtab);
69599
+ importVtabErrMsg(p, u.cp.pVtab);
6954769600
if( rc==SQLITE_OK && pOp->p1 ){
69548
- assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
69549
- db->lastRowid = lastRowid = u.cm.rowid;
69601
+ assert( u.cp.nArg>1 && u.cp.apArg[0] && (u.cp.apArg[0]->flags&MEM_Null) );
69602
+ db->lastRowid = lastRowid = u.cp.rowid;
6955069603
}
6955169604
if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
6955269605
if( pOp->p5==OE_Ignore ){
6955369606
rc = SQLITE_OK;
6955469607
}else{
@@ -69604,25 +69657,25 @@
6960469657
**
6960569658
** If tracing is enabled (by the sqlite3_trace()) interface, then
6960669659
** the UTF-8 string contained in P4 is emitted on the trace callback.
6960769660
*/
6960869661
case OP_Trace: {
69609
-#if 0 /* local variables moved into u.cn */
69662
+#if 0 /* local variables moved into u.cq */
6961069663
char *zTrace;
6961169664
char *z;
69612
-#endif /* local variables moved into u.cn */
69665
+#endif /* local variables moved into u.cq */
6961369666
69614
- if( db->xTrace && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
69615
- u.cn.z = sqlite3VdbeExpandSql(p, u.cn.zTrace);
69616
- db->xTrace(db->pTraceArg, u.cn.z);
69617
- sqlite3DbFree(db, u.cn.z);
69667
+ if( db->xTrace && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
69668
+ u.cq.z = sqlite3VdbeExpandSql(p, u.cq.zTrace);
69669
+ db->xTrace(db->pTraceArg, u.cq.z);
69670
+ sqlite3DbFree(db, u.cq.z);
6961869671
}
6961969672
#ifdef SQLITE_DEBUG
6962069673
if( (db->flags & SQLITE_SqlTrace)!=0
69621
- && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
69674
+ && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
6962269675
){
69623
- sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace);
69676
+ sqlite3DebugPrintf("SQL-trace: %s\n", u.cq.zTrace);
6962469677
}
6962569678
#endif /* SQLITE_DEBUG */
6962669679
break;
6962769680
}
6962869681
#endif
@@ -70021,21 +70074,21 @@
7002170074
/* Make sure a mutex is held on the table to be accessed */
7002270075
sqlite3VdbeUsesBtree(v, iDb);
7002370076
7002470077
/* Configure the OP_TableLock instruction */
7002570078
#ifdef SQLITE_OMIT_SHARED_CACHE
70026
- sqlite3VdbeChangeToNoop(v, 2, 1);
70079
+ sqlite3VdbeChangeToNoop(v, 2);
7002770080
#else
7002870081
sqlite3VdbeChangeP1(v, 2, iDb);
7002970082
sqlite3VdbeChangeP2(v, 2, pTab->tnum);
7003070083
sqlite3VdbeChangeP3(v, 2, flags);
7003170084
sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
7003270085
#endif
7003370086
7003470087
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
7003570088
** parameter of the other to pTab->tnum. */
70036
- sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
70089
+ sqlite3VdbeChangeToNoop(v, 4 - flags);
7003770090
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
7003870091
sqlite3VdbeChangeP3(v, 3 + flags, iDb);
7003970092
7004070093
/* Configure the number of columns. Configure the cursor to
7004170094
** think that the table has one more column than it really
@@ -70239,10 +70292,11 @@
7023970292
7024070293
7024170294
#ifndef SQLITE_OMIT_MERGE_SORT
7024270295
7024370296
typedef struct VdbeSorterIter VdbeSorterIter;
70297
+typedef struct SorterRecord SorterRecord;
7024470298
7024570299
/*
7024670300
** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
7024770301
**
7024870302
** As keys are added to the sorter, they are written to disk in a series
@@ -70310,19 +70364,22 @@
7031070364
** In other words, each time we advance to the next sorter element, log2(N)
7031170365
** key comparison operations are required, where N is the number of segments
7031270366
** being merged (rounded up to the next power of 2).
7031370367
*/
7031470368
struct VdbeSorter {
70315
- int nWorking; /* Start a new b-tree after this many pages */
70316
- int nBtree; /* Current size of b-tree contents as PMA */
70369
+ int nInMemory; /* Current size of pRecord list as PMA */
7031770370
int nTree; /* Used size of aTree/aIter (power of 2) */
7031870371
VdbeSorterIter *aIter; /* Array of iterators to merge */
7031970372
int *aTree; /* Current state of incremental merge */
7032070373
i64 iWriteOff; /* Current write offset within file pTemp1 */
7032170374
i64 iReadOff; /* Current read offset within file pTemp1 */
7032270375
sqlite3_file *pTemp1; /* PMA file 1 */
7032370376
int nPMA; /* Number of PMAs stored in pTemp1 */
70377
+ SorterRecord *pRecord; /* Head of in-memory record list */
70378
+ int mnPmaSize; /* Minimum PMA size, in bytes */
70379
+ int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */
70380
+ UnpackedRecord *pUnpacked; /* Used to unpack keys */
7032470381
};
7032570382
7032670383
/*
7032770384
** The following type is an iterator for a PMA. It caches the current key in
7032870385
** variables nKey/aKey. If the iterator is at EOF, pFile==0.
@@ -70334,10 +70391,21 @@
7033470391
int nAlloc; /* Bytes of space at aAlloc */
7033570392
u8 *aAlloc; /* Allocated space */
7033670393
int nKey; /* Number of bytes in key */
7033770394
u8 *aKey; /* Pointer to current key */
7033870395
};
70396
+
70397
+/*
70398
+** A structure to store a single record. All in-memory records are connected
70399
+** together into a linked list headed at VdbeSorter.pRecord using the
70400
+** SorterRecord.pNext pointer.
70401
+*/
70402
+struct SorterRecord {
70403
+ void *pVal;
70404
+ int nVal;
70405
+ SorterRecord *pNext;
70406
+};
7033970407
7034070408
/* Minimum allowable value for the VdbeSorter.nWorking variable */
7034170409
#define SORTER_MIN_WORKING 10
7034270410
7034370411
/* Maximum number of segments to merge in a single pass. */
@@ -70360,41 +70428,46 @@
7036070428
sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */
7036170429
VdbeSorterIter *pIter /* Iterator to advance */
7036270430
){
7036370431
int rc; /* Return Code */
7036470432
int nRead; /* Number of bytes read */
70365
- int nRec; /* Size of record in bytes */
70366
- int iOff; /* Size of serialized size varint in bytes */
70433
+ int nRec = 0; /* Size of record in bytes */
70434
+ int iOff = 0; /* Size of serialized size varint in bytes */
7036770435
70368
- nRead = pIter->iEof - pIter->iReadOff;
70369
- if( nRead>5 ) nRead = 5;
70436
+ assert( pIter->iEof>=pIter->iReadOff );
70437
+ if( pIter->iEof-pIter->iReadOff>5 ){
70438
+ nRead = 5;
70439
+ }else{
70440
+ nRead = (int)(pIter->iEof - pIter->iReadOff);
70441
+ }
7037070442
if( nRead<=0 ){
7037170443
/* This is an EOF condition */
7037270444
vdbeSorterIterZero(db, pIter);
7037370445
return SQLITE_OK;
7037470446
}
7037570447
7037670448
rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
70377
- iOff = getVarint32(pIter->aAlloc, nRec);
70378
-
70379
- if( rc==SQLITE_OK && (iOff+nRec)>nRead ){
70380
- int nRead2; /* Number of extra bytes to read */
70381
- if( (iOff+nRec)>pIter->nAlloc ){
70382
- int nNew = pIter->nAlloc*2;
70383
- while( (iOff+nRec)>nNew ) nNew = nNew*2;
70384
- pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
70385
- if( !pIter->aAlloc ) return SQLITE_NOMEM;
70386
- pIter->nAlloc = nNew;
70387
- }
70388
-
70389
- nRead2 = iOff + nRec - nRead;
70390
- rc = sqlite3OsRead(
70391
- pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
70392
- );
70393
- }
70394
-
70395
- assert( nRec>0 || rc!=SQLITE_OK );
70449
+ if( rc==SQLITE_OK ){
70450
+ iOff = getVarint32(pIter->aAlloc, nRec);
70451
+ if( (iOff+nRec)>nRead ){
70452
+ int nRead2; /* Number of extra bytes to read */
70453
+ if( (iOff+nRec)>pIter->nAlloc ){
70454
+ int nNew = pIter->nAlloc*2;
70455
+ while( (iOff+nRec)>nNew ) nNew = nNew*2;
70456
+ pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
70457
+ if( !pIter->aAlloc ) return SQLITE_NOMEM;
70458
+ pIter->nAlloc = nNew;
70459
+ }
70460
+
70461
+ nRead2 = iOff + nRec - nRead;
70462
+ rc = sqlite3OsRead(
70463
+ pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
70464
+ );
70465
+ }
70466
+ }
70467
+
70468
+ assert( rc!=SQLITE_OK || nRec>0 );
7039670469
pIter->iReadOff += iOff+nRec;
7039770470
pIter->nKey = nRec;
7039870471
pIter->aKey = &pIter->aAlloc[iOff];
7039970472
return rc;
7040070473
}
@@ -70434,25 +70507,18 @@
7043470507
** set to the integer value read. If an error occurs, the final values of
7043570508
** both *piOffset and *piVal are undefined.
7043670509
*/
7043770510
static int vdbeSorterReadVarint(
7043870511
sqlite3_file *pFile, /* File to read from */
70439
- i64 iEof, /* Total number of bytes in file */
7044070512
i64 *piOffset, /* IN/OUT: Read offset in pFile */
7044170513
i64 *piVal /* OUT: Value read from file */
7044270514
){
7044370515
u8 aVarint[9]; /* Buffer large enough for a varint */
7044470516
i64 iOff = *piOffset; /* Offset in file to read from */
70445
- int nRead = 9; /* Number of bytes to read from file */
7044670517
int rc; /* Return code */
7044770518
70448
- assert( iEof>iOff );
70449
- if( (iEof-iOff)<nRead ){
70450
- nRead = iEof-iOff;
70451
- }
70452
-
70453
- rc = sqlite3OsRead(pFile, aVarint, nRead, iOff);
70519
+ rc = sqlite3OsRead(pFile, aVarint, 9, iOff);
7045470520
if( rc==SQLITE_OK ){
7045570521
*piOffset += getVarint(aVarint, (u64 *)piVal);
7045670522
}
7045770523
7045870524
return rc;
@@ -70480,22 +70546,68 @@
7048070546
pIter->nAlloc = 128;
7048170547
pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
7048270548
if( !pIter->aAlloc ){
7048370549
rc = SQLITE_NOMEM;
7048470550
}else{
70485
- i64 iEof = pSorter->iWriteOff; /* EOF of file pSorter->pTemp1 */
7048670551
i64 nByte; /* Total size of PMA in bytes */
70487
- rc = vdbeSorterReadVarint(pSorter->pTemp1, iEof, &pIter->iReadOff, &nByte);
70552
+ rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte);
7048870553
*pnByte += nByte;
7048970554
pIter->iEof = pIter->iReadOff + nByte;
7049070555
}
7049170556
if( rc==SQLITE_OK ){
7049270557
rc = vdbeSorterIterNext(db, pIter);
7049370558
}
7049470559
return rc;
7049570560
}
7049670561
70562
+
70563
+/*
70564
+** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
70565
+** size nKey2 bytes). Argument pKeyInfo supplies the collation functions
70566
+** used by the comparison. If an error occurs, return an SQLite error code.
70567
+** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive
70568
+** value, depending on whether key1 is smaller, equal to or larger than key2.
70569
+**
70570
+** If the bOmitRowid argument is non-zero, assume both keys end in a rowid
70571
+** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid
70572
+** is true and key1 contains even a single NULL value, it is considered to
70573
+** be less than key2. Even if key2 also contains NULL values.
70574
+**
70575
+** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
70576
+** has been allocated and contains an unpacked record that is used as key2.
70577
+*/
70578
+static void vdbeSorterCompare(
70579
+ VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
70580
+ int bOmitRowid, /* Ignore rowid field at end of keys */
70581
+ void *pKey1, int nKey1, /* Left side of comparison */
70582
+ void *pKey2, int nKey2, /* Right side of comparison */
70583
+ int *pRes /* OUT: Result of comparison */
70584
+){
70585
+ KeyInfo *pKeyInfo = pCsr->pKeyInfo;
70586
+ VdbeSorter *pSorter = pCsr->pSorter;
70587
+ UnpackedRecord *r2 = pSorter->pUnpacked;
70588
+ int i;
70589
+
70590
+ if( pKey2 ){
70591
+ sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
70592
+ }
70593
+
70594
+ if( bOmitRowid ){
70595
+ r2->nField = pKeyInfo->nField;
70596
+ assert( r2->nField>0 );
70597
+ for(i=0; i<r2->nField; i++){
70598
+ if( r2->aMem[i].flags & MEM_Null ){
70599
+ *pRes = -1;
70600
+ return;
70601
+ }
70602
+ }
70603
+ r2->flags |= UNPACKED_PREFIX_MATCH;
70604
+ }
70605
+
70606
+ *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
70607
+}
70608
+
7049770609
/*
7049870610
** This function is called to compare two iterator keys when merging
7049970611
** multiple b-tree segments. Parameter iOut is the index of the aTree[]
7050070612
** value to recalculate.
7050170613
*/
@@ -70523,24 +70635,20 @@
7052370635
if( p1->pFile==0 ){
7052470636
iRes = i2;
7052570637
}else if( p2->pFile==0 ){
7052670638
iRes = i1;
7052770639
}else{
70528
- char aSpace[150];
70529
- UnpackedRecord *r1;
70530
-
70531
- r1 = sqlite3VdbeRecordUnpack(
70532
- pCsr->pKeyInfo, p1->nKey, p1->aKey, aSpace, sizeof(aSpace)
70640
+ int res;
70641
+ assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */
70642
+ vdbeSorterCompare(
70643
+ pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
7053370644
);
70534
- if( r1==0 ) return SQLITE_NOMEM;
70535
-
70536
- if( sqlite3VdbeRecordCompare(p2->nKey, p2->aKey, r1)>=0 ){
70645
+ if( res<=0 ){
7053770646
iRes = i1;
7053870647
}else{
7053970648
iRes = i2;
7054070649
}
70541
- sqlite3VdbeDeleteUnpackedRecord(r1);
7054270650
}
7054370651
7054470652
pSorter->aTree[iOut] = iRes;
7054570653
return SQLITE_OK;
7054670654
}
@@ -70547,13 +70655,46 @@
7054770655
7054870656
/*
7054970657
** Initialize the temporary index cursor just opened as a sorter cursor.
7055070658
*/
7055170659
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
70552
- assert( pCsr->pKeyInfo && pCsr->pBt );
70553
- pCsr->pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
70554
- return (pCsr->pSorter ? SQLITE_OK : SQLITE_NOMEM);
70660
+ int pgsz; /* Page size of main database */
70661
+ int mxCache; /* Cache size */
70662
+ VdbeSorter *pSorter; /* The new sorter */
70663
+ char *d; /* Dummy */
70664
+
70665
+ assert( pCsr->pKeyInfo && pCsr->pBt==0 );
70666
+ pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
70667
+ if( pSorter==0 ){
70668
+ return SQLITE_NOMEM;
70669
+ }
70670
+
70671
+ pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d);
70672
+ if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM;
70673
+ assert( pSorter->pUnpacked==(UnpackedRecord *)d );
70674
+
70675
+ if( !sqlite3TempInMemory(db) ){
70676
+ pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
70677
+ pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
70678
+ mxCache = db->aDb[0].pSchema->cache_size;
70679
+ if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
70680
+ pSorter->mxPmaSize = mxCache * pgsz;
70681
+ }
70682
+
70683
+ return SQLITE_OK;
70684
+}
70685
+
70686
+/*
70687
+** Free the list of sorted records starting at pRecord.
70688
+*/
70689
+static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
70690
+ SorterRecord *p;
70691
+ SorterRecord *pNext;
70692
+ for(p=pRecord; p; p=pNext){
70693
+ pNext = p->pNext;
70694
+ sqlite3DbFree(db, p);
70695
+ }
7055570696
}
7055670697
7055770698
/*
7055870699
** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
7055970700
*/
@@ -70568,10 +70709,12 @@
7056870709
sqlite3DbFree(db, pSorter->aIter);
7056970710
}
7057070711
if( pSorter->pTemp1 ){
7057170712
sqlite3OsCloseFree(pSorter->pTemp1);
7057270713
}
70714
+ vdbeSorterRecordFree(db, pSorter->pRecord);
70715
+ sqlite3DbFree(db, pSorter->pUnpacked);
7057370716
sqlite3DbFree(db, pSorter);
7057470717
pCsr->pSorter = 0;
7057570718
}
7057670719
}
7057770720
@@ -70587,14 +70730,86 @@
7058770730
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
7058870731
SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy
7058970732
);
7059070733
}
7059170734
70735
+/*
70736
+** Merge the two sorted lists p1 and p2 into a single list.
70737
+** Set *ppOut to the head of the new list.
70738
+*/
70739
+static void vdbeSorterMerge(
70740
+ VdbeCursor *pCsr, /* For pKeyInfo */
70741
+ SorterRecord *p1, /* First list to merge */
70742
+ SorterRecord *p2, /* Second list to merge */
70743
+ SorterRecord **ppOut /* OUT: Head of merged list */
70744
+){
70745
+ SorterRecord *pFinal = 0;
70746
+ SorterRecord **pp = &pFinal;
70747
+ void *pVal2 = p2 ? p2->pVal : 0;
70748
+
70749
+ while( p1 && p2 ){
70750
+ int res;
70751
+ vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
70752
+ if( res<=0 ){
70753
+ *pp = p1;
70754
+ pp = &p1->pNext;
70755
+ p1 = p1->pNext;
70756
+ pVal2 = 0;
70757
+ }else{
70758
+ *pp = p2;
70759
+ pp = &p2->pNext;
70760
+ p2 = p2->pNext;
70761
+ if( p2==0 ) break;
70762
+ pVal2 = p2->pVal;
70763
+ }
70764
+ }
70765
+ *pp = p1 ? p1 : p2;
70766
+ *ppOut = pFinal;
70767
+}
7059270768
7059370769
/*
70594
-** Write the current contents of the b-tree to a PMA. Return SQLITE_OK
70595
-** if successful, or an SQLite error code otherwise.
70770
+** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK
70771
+** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
70772
+** occurs.
70773
+*/
70774
+static int vdbeSorterSort(VdbeCursor *pCsr){
70775
+ int i;
70776
+ SorterRecord **aSlot;
70777
+ SorterRecord *p;
70778
+ VdbeSorter *pSorter = pCsr->pSorter;
70779
+
70780
+ aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
70781
+ if( !aSlot ){
70782
+ return SQLITE_NOMEM;
70783
+ }
70784
+
70785
+ p = pSorter->pRecord;
70786
+ while( p ){
70787
+ SorterRecord *pNext = p->pNext;
70788
+ p->pNext = 0;
70789
+ for(i=0; aSlot[i]; i++){
70790
+ vdbeSorterMerge(pCsr, p, aSlot[i], &p);
70791
+ aSlot[i] = 0;
70792
+ }
70793
+ aSlot[i] = p;
70794
+ p = pNext;
70795
+ }
70796
+
70797
+ p = 0;
70798
+ for(i=0; i<64; i++){
70799
+ vdbeSorterMerge(pCsr, p, aSlot[i], &p);
70800
+ }
70801
+ pSorter->pRecord = p;
70802
+
70803
+ sqlite3_free(aSlot);
70804
+ return SQLITE_OK;
70805
+}
70806
+
70807
+
70808
+/*
70809
+** Write the current contents of the in-memory linked-list to a PMA. Return
70810
+** SQLITE_OK if successful, or an SQLite error code otherwise.
7059670811
**
7059770812
** The format of a PMA is:
7059870813
**
7059970814
** * A varint. This varint contains the total number of bytes of content
7060070815
** in the PMA (not including the varint itself).
@@ -70601,153 +70816,111 @@
7060170816
**
7060270817
** * One or more records packed end-to-end in order of ascending keys.
7060370818
** Each record consists of a varint followed by a blob of data (the
7060470819
** key). The varint is the number of bytes in the blob of data.
7060570820
*/
70606
-static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){
70821
+static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
7060770822
int rc = SQLITE_OK; /* Return code */
7060870823
VdbeSorter *pSorter = pCsr->pSorter;
70609
- int res = 0;
7061070824
70611
- /* sqlite3BtreeFirst() cannot fail because sorter btrees are always held
70612
- ** in memory and so an I/O error is not possible. */
70613
- rc = sqlite3BtreeFirst(pCsr->pCursor, &res);
70614
- if( NEVER(rc!=SQLITE_OK) || res ) return rc;
70615
- assert( pSorter->nBtree>0 );
70825
+ if( pSorter->nInMemory==0 ){
70826
+ assert( pSorter->pRecord==0 );
70827
+ return rc;
70828
+ }
70829
+
70830
+ rc = vdbeSorterSort(pCsr);
7061670831
7061770832
/* If the first temporary PMA file has not been opened, open it now. */
70618
- if( pSorter->pTemp1==0 ){
70833
+ if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
7061970834
rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
7062070835
assert( rc!=SQLITE_OK || pSorter->pTemp1 );
7062170836
assert( pSorter->iWriteOff==0 );
7062270837
assert( pSorter->nPMA==0 );
7062370838
}
7062470839
7062570840
if( rc==SQLITE_OK ){
70626
- i64 iWriteOff = pSorter->iWriteOff;
70627
- void *aMalloc = 0; /* Array used to hold a single record */
70628
- int nMalloc = 0; /* Allocated size of aMalloc[] in bytes */
70841
+ i64 iOff = pSorter->iWriteOff;
70842
+ SorterRecord *p;
70843
+ SorterRecord *pNext = 0;
70844
+ static const char eightZeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
7062970845
7063070846
pSorter->nPMA++;
70631
- for(
70632
- rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nBtree, &iWriteOff);
70633
- rc==SQLITE_OK && res==0;
70634
- rc = sqlite3BtreeNext(pCsr->pCursor, &res)
70635
- ){
70636
- i64 nKey; /* Size of this key in bytes */
70637
-
70638
- /* Write the size of the record in bytes to the output file */
70639
- (void)sqlite3BtreeKeySize(pCsr->pCursor, &nKey);
70640
- rc = vdbeSorterWriteVarint(pSorter->pTemp1, nKey, &iWriteOff);
70641
-
70642
- /* Make sure the aMalloc[] buffer is large enough for the record */
70643
- if( rc==SQLITE_OK && nKey>nMalloc ){
70644
- aMalloc = sqlite3DbReallocOrFree(db, aMalloc, nKey);
70645
- if( !aMalloc ){
70646
- rc = SQLITE_NOMEM;
70647
- }else{
70648
- nMalloc = nKey;
70649
- }
70650
- }
70651
-
70652
- /* Write the record itself to the output file */
70847
+ rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nInMemory, &iOff);
70848
+ for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){
70849
+ pNext = p->pNext;
70850
+ rc = vdbeSorterWriteVarint(pSorter->pTemp1, p->nVal, &iOff);
70851
+
7065370852
if( rc==SQLITE_OK ){
70654
- /* sqlite3BtreeKey() cannot fail because sorter btrees held in memory */
70655
- rc = sqlite3BtreeKey(pCsr->pCursor, 0, nKey, aMalloc);
70656
- if( ALWAYS(rc==SQLITE_OK) ){
70657
- rc = sqlite3OsWrite(pSorter->pTemp1, aMalloc, nKey, iWriteOff);
70658
- iWriteOff += nKey;
70659
- }
70853
+ rc = sqlite3OsWrite(pSorter->pTemp1, p->pVal, p->nVal, iOff);
70854
+ iOff += p->nVal;
7066070855
}
7066170856
70662
- if( rc!=SQLITE_OK ) break;
70857
+ sqlite3DbFree(db, p);
7066370858
}
7066470859
7066570860
/* This assert verifies that unless an error has occurred, the size of
7066670861
** the PMA on disk is the same as the expected size stored in
70667
- ** pSorter->nBtree. */
70668
- assert( rc!=SQLITE_OK || pSorter->nBtree==(
70669
- iWriteOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nBtree)
70862
+ ** pSorter->nInMemory. */
70863
+ assert( rc!=SQLITE_OK || pSorter->nInMemory==(
70864
+ iOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nInMemory)
7067070865
));
7067170866
70672
- pSorter->iWriteOff = iWriteOff;
70673
- sqlite3DbFree(db, aMalloc);
70867
+ pSorter->iWriteOff = iOff;
70868
+ if( rc==SQLITE_OK ){
70869
+ /* Terminate each file with 8 extra bytes so that from any offset
70870
+ ** in the file we can always read 9 bytes without a SHORT_READ error */
70871
+ rc = sqlite3OsWrite(pSorter->pTemp1, eightZeros, 8, iOff);
70872
+ }
70873
+ pSorter->pRecord = p;
7067470874
}
7067570875
70676
- pSorter->nBtree = 0;
7067770876
return rc;
7067870877
}
7067970878
7068070879
/*
70681
-** This function is called on a sorter cursor by the VDBE before each row
70682
-** is inserted into VdbeCursor.pCsr. Argument nKey is the size of the key, in
70683
-** bytes, about to be inserted.
70684
-**
70685
-** If it is determined that the temporary b-tree accessed via VdbeCursor.pCsr
70686
-** is large enough, its contents are written to a sorted PMA on disk and the
70687
-** tree emptied. This prevents the b-tree (which must be small enough to
70688
-** fit entirely in the cache in order to support efficient inserts) from
70689
-** growing too large.
70690
-**
70691
-** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK.
70880
+** Add a record to the sorter.
7069270881
*/
70693
-SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *db, VdbeCursor *pCsr, int nKey){
70694
- int rc = SQLITE_OK; /* Return code */
70882
+SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
70883
+ sqlite3 *db, /* Database handle */
70884
+ VdbeCursor *pCsr, /* Sorter cursor */
70885
+ Mem *pVal /* Memory cell containing record */
70886
+){
7069570887
VdbeSorter *pSorter = pCsr->pSorter;
70696
- if( pSorter ){
70697
- Pager *pPager = sqlite3BtreePager(pCsr->pBt);
70698
- int nPage; /* Current size of temporary file in pages */
70699
-
70700
- /* Sorters never spill to disk */
70701
- assert( sqlite3PagerFile(pPager)->pMethods==0 );
70702
-
70703
- /* Determine how many pages the temporary b-tree has grown to */
70704
- sqlite3PagerPagecount(pPager, &nPage);
70705
-
70706
- /* If pSorter->nWorking is still zero, but the temporary file has been
70707
- ** created in the file-system, then the most recent insert into the
70708
- ** current b-tree segment probably caused the cache to overflow (it is
70709
- ** also possible that sqlite3_release_memory() was called). So set the
70710
- ** size of the working set to a little less than the current size of the
70711
- ** file in pages. */
70712
- if( pSorter->nWorking==0 && sqlite3PagerUnderStress(pPager) ){
70713
- pSorter->nWorking = nPage-5;
70714
- if( pSorter->nWorking<SORTER_MIN_WORKING ){
70715
- pSorter->nWorking = SORTER_MIN_WORKING;
70716
- }
70717
- }
70718
-
70719
- /* If the number of pages used by the current b-tree segment is greater
70720
- ** than the size of the working set (VdbeSorter.nWorking), start a new
70721
- ** segment b-tree. */
70722
- if( pSorter->nWorking && nPage>=pSorter->nWorking ){
70723
- BtCursor *p = pCsr->pCursor;/* Cursor structure to close and reopen */
70724
- int iRoot; /* Root page of new tree */
70725
-
70726
- /* Copy the current contents of the b-tree into a PMA in sorted order.
70727
- ** Close the currently open b-tree cursor. */
70728
- rc = vdbeSorterBtreeToPMA(db, pCsr);
70729
- sqlite3BtreeCloseCursor(p);
70730
-
70731
- if( rc==SQLITE_OK ){
70732
- rc = sqlite3BtreeDropTable(pCsr->pBt, 2, 0);
70733
-#ifdef SQLITE_DEBUG
70734
- sqlite3PagerPagecount(pPager, &nPage);
70735
- assert( rc!=SQLITE_OK || nPage==1 );
70736
-#endif
70737
- }
70738
- if( rc==SQLITE_OK ){
70739
- rc = sqlite3BtreeCreateTable(pCsr->pBt, &iRoot, BTREE_BLOBKEY);
70740
- }
70741
- if( rc==SQLITE_OK ){
70742
- assert( iRoot==2 );
70743
- rc = sqlite3BtreeCursor(pCsr->pBt, iRoot, 1, pCsr->pKeyInfo, p);
70744
- }
70745
- }
70746
-
70747
- pSorter->nBtree += sqlite3VarintLen(nKey) + nKey;
70748
- }
70888
+ int rc = SQLITE_OK; /* Return Code */
70889
+ SorterRecord *pNew; /* New list element */
70890
+
70891
+ assert( pSorter );
70892
+ pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n;
70893
+
70894
+ pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord));
70895
+ if( pNew==0 ){
70896
+ rc = SQLITE_NOMEM;
70897
+ }else{
70898
+ pNew->pVal = (void *)&pNew[1];
70899
+ memcpy(pNew->pVal, pVal->z, pVal->n);
70900
+ pNew->nVal = pVal->n;
70901
+ pNew->pNext = pSorter->pRecord;
70902
+ pSorter->pRecord = pNew;
70903
+ }
70904
+
70905
+ /* See if the contents of the sorter should now be written out. They
70906
+ ** are written out when either of the following are true:
70907
+ **
70908
+ ** * The total memory allocated for the in-memory list is greater
70909
+ ** than (page-size * cache-size), or
70910
+ **
70911
+ ** * The total memory allocated for the in-memory list is greater
70912
+ ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
70913
+ */
70914
+ if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
70915
+ (pSorter->nInMemory>pSorter->mxPmaSize)
70916
+ || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
70917
+ )){
70918
+ rc = vdbeSorterListToPMA(db, pCsr);
70919
+ pSorter->nInMemory = 0;
70920
+ }
70921
+
7074970922
return rc;
7075070923
}
7075170924
7075270925
/*
7075370926
** Helper function for sqlite3VdbeSorterRewind().
@@ -70761,16 +70934,16 @@
7076170934
int rc = SQLITE_OK; /* Return code */
7076270935
int i; /* Used to iterator through aIter[] */
7076370936
i64 nByte = 0; /* Total bytes in all opened PMAs */
7076470937
7076570938
/* Initialize the iterators. */
70766
- for(i=0; rc==SQLITE_OK && i<SORTER_MAX_MERGE_COUNT; i++){
70939
+ for(i=0; i<SORTER_MAX_MERGE_COUNT; i++){
7076770940
VdbeSorterIter *pIter = &pSorter->aIter[i];
7076870941
rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
7076970942
pSorter->iReadOff = pIter->iEof;
70770
- assert( pSorter->iReadOff<=pSorter->iWriteOff || rc!=SQLITE_OK );
70771
- if( pSorter->iReadOff>=pSorter->iWriteOff ) break;
70943
+ assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff );
70944
+ if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break;
7077270945
}
7077370946
7077470947
/* Initialize the aTree[] array. */
7077570948
for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
7077670949
rc = vdbeSorterDoCompare(pCsr, i);
@@ -70793,18 +70966,22 @@
7079370966
int nByte; /* Bytes of space required for aIter/aTree */
7079470967
int N = 2; /* Power of 2 >= nIter */
7079570968
7079670969
assert( pSorter );
7079770970
70798
- /* Write the current b-tree to a PMA. Close the b-tree cursor. */
70799
- rc = vdbeSorterBtreeToPMA(db, pCsr);
70800
- sqlite3BtreeCloseCursor(pCsr->pCursor);
70801
- if( rc!=SQLITE_OK ) return rc;
70971
+ /* If no data has been written to disk, then do not do so now. Instead,
70972
+ ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
70973
+ ** from the in-memory list. */
7080270974
if( pSorter->nPMA==0 ){
70803
- *pbEof = 1;
70804
- return SQLITE_OK;
70975
+ *pbEof = !pSorter->pRecord;
70976
+ assert( pSorter->aTree==0 );
70977
+ return vdbeSorterSort(pCsr);
7080570978
}
70979
+
70980
+ /* Write the current b-tree to a PMA. Close the b-tree cursor. */
70981
+ rc = vdbeSorterListToPMA(db, pCsr);
70982
+ if( rc!=SQLITE_OK ) return rc;
7080670983
7080770984
/* Allocate space for aIter[] and aTree[]. */
7080870985
nIter = pSorter->nPMA;
7080970986
if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
7081070987
assert( nIter>0 );
@@ -70888,47 +71065,94 @@
7088871065
/*
7088971066
** Advance to the next element in the sorter.
7089071067
*/
7089171068
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
7089271069
VdbeSorter *pSorter = pCsr->pSorter;
70893
- int iPrev = pSorter->aTree[1]; /* Index of iterator to advance */
70894
- int i; /* Index of aTree[] to recalculate */
7089571070
int rc; /* Return code */
7089671071
70897
- rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
70898
- for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
70899
- rc = vdbeSorterDoCompare(pCsr, i);
71072
+ if( pSorter->aTree ){
71073
+ int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
71074
+ int i; /* Index of aTree[] to recalculate */
71075
+
71076
+ rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
71077
+ for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
71078
+ rc = vdbeSorterDoCompare(pCsr, i);
71079
+ }
71080
+
71081
+ *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
71082
+ }else{
71083
+ SorterRecord *pFree = pSorter->pRecord;
71084
+ pSorter->pRecord = pFree->pNext;
71085
+ pFree->pNext = 0;
71086
+ vdbeSorterRecordFree(db, pFree);
71087
+ *pbEof = !pSorter->pRecord;
71088
+ rc = SQLITE_OK;
7090071089
}
71090
+ return rc;
71091
+}
7090171092
70902
- *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
70903
- return rc;
71093
+/*
71094
+** Return a pointer to a buffer owned by the sorter that contains the
71095
+** current key.
71096
+*/
71097
+static void *vdbeSorterRowkey(
71098
+ VdbeSorter *pSorter, /* Sorter object */
71099
+ int *pnKey /* OUT: Size of current key in bytes */
71100
+){
71101
+ void *pKey;
71102
+ if( pSorter->aTree ){
71103
+ VdbeSorterIter *pIter;
71104
+ pIter = &pSorter->aIter[ pSorter->aTree[1] ];
71105
+ *pnKey = pIter->nKey;
71106
+ pKey = pIter->aKey;
71107
+ }else{
71108
+ *pnKey = pSorter->pRecord->nVal;
71109
+ pKey = pSorter->pRecord->pVal;
71110
+ }
71111
+ return pKey;
7090471112
}
7090571113
7090671114
/*
7090771115
** Copy the current sorter key into the memory cell pOut.
7090871116
*/
7090971117
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
7091071118
VdbeSorter *pSorter = pCsr->pSorter;
70911
- VdbeSorterIter *pIter;
70912
-
70913
- pIter = &pSorter->aIter[ pSorter->aTree[1] ];
70914
-
70915
- /* Coverage testing note: As things are currently, this call will always
70916
- ** succeed. This is because the memory cell passed by the VDBE layer
70917
- ** happens to be the same one as was used to assemble the keys before they
70918
- ** were passed to the sorter - meaning it is always large enough for the
70919
- ** largest key. But this could change very easily, so we leave the call
70920
- ** to sqlite3VdbeMemGrow() in. */
70921
- if( NEVER(sqlite3VdbeMemGrow(pOut, pIter->nKey, 0)) ){
71119
+ void *pKey; int nKey; /* Sorter key to copy into pOut */
71120
+
71121
+ pKey = vdbeSorterRowkey(pSorter, &nKey);
71122
+ if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){
7092271123
return SQLITE_NOMEM;
7092371124
}
70924
- pOut->n = pIter->nKey;
71125
+ pOut->n = nKey;
7092571126
MemSetTypeFlag(pOut, MEM_Blob);
70926
- memcpy(pOut->z, pIter->aKey, pIter->nKey);
71127
+ memcpy(pOut->z, pKey, nKey);
7092771128
7092871129
return SQLITE_OK;
7092971130
}
71131
+
71132
+/*
71133
+** Compare the key in memory cell pVal with the key that the sorter cursor
71134
+** passed as the first argument currently points to. For the purposes of
71135
+** the comparison, ignore the rowid field at the end of each record.
71136
+**
71137
+** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
71138
+** Otherwise, set *pRes to a negative, zero or positive value if the
71139
+** key in pVal is smaller than, equal to or larger than the current sorter
71140
+** key.
71141
+*/
71142
+SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
71143
+ VdbeCursor *pCsr, /* Sorter cursor */
71144
+ Mem *pVal, /* Value to compare to current sorter key */
71145
+ int *pRes /* OUT: Result of comparison */
71146
+){
71147
+ VdbeSorter *pSorter = pCsr->pSorter;
71148
+ void *pKey; int nKey; /* Sorter key to compare pVal with */
71149
+
71150
+ pKey = vdbeSorterRowkey(pSorter, &nKey);
71151
+ vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
71152
+ return SQLITE_OK;
71153
+}
7093071154
7093171155
#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
7093271156
7093371157
/************** End of vdbesort.c ********************************************/
7093471158
/************** Begin file journal.c *****************************************/
@@ -73691,11 +73915,12 @@
7369173915
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
7369273916
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
7369373917
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
7369473918
pNewItem->jointype = pOldItem->jointype;
7369573919
pNewItem->iCursor = pOldItem->iCursor;
73696
- pNewItem->isPopulated = pOldItem->isPopulated;
73920
+ pNewItem->addrFillSub = pOldItem->addrFillSub;
73921
+ pNewItem->regReturn = pOldItem->regReturn;
7369773922
pNewItem->isCorrelated = pOldItem->isCorrelated;
7369873923
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
7369973924
pNewItem->notIndexed = pOldItem->notIndexed;
7370073925
pNewItem->pIndex = pOldItem->pIndex;
7370173926
pTab = pNewItem->pTab = pOldItem->pTab;
@@ -74251,12 +74476,11 @@
7425174476
assert(v);
7425274477
if( iCol<0 ){
7425374478
int iMem = ++pParse->nMem;
7425474479
int iAddr;
7425574480
74256
- iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
74257
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
74481
+ iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
7425874482
7425974483
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
7426074484
eType = IN_INDEX_ROWID;
7426174485
7426274486
sqlite3VdbeJumpHere(v, iAddr);
@@ -74283,12 +74507,11 @@
7428374507
int iMem = ++pParse->nMem;
7428474508
int iAddr;
7428574509
char *pKey;
7428674510
7428774511
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
74288
- iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
74289
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
74512
+ iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
7429074513
7429174514
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
7429274515
pKey,P4_KEYINFO_HANDOFF);
7429374516
VdbeComment((v, "%s", pIdx->zName));
7429474517
eType = IN_INDEX_INDEX;
@@ -74365,11 +74588,11 @@
7436574588
Parse *pParse, /* Parsing context */
7436674589
Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
7436774590
int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
7436874591
int isRowid /* If true, LHS of IN operator is a rowid */
7436974592
){
74370
- int testAddr = 0; /* One-time test address */
74593
+ int testAddr = -1; /* One-time test address */
7437174594
int rReg = 0; /* Register storing resulting */
7437274595
Vdbe *v = sqlite3GetVdbe(pParse);
7437374596
if( NEVER(v==0) ) return 0;
7437474597
sqlite3ExprCachePush(pParse);
7437574598
@@ -74383,19 +74606,17 @@
7438374606
** If all of the above are false, then we can run this code just once
7438474607
** save the results, and reuse the same result on subsequent invocations.
7438574608
*/
7438674609
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
7438774610
int mem = ++pParse->nMem;
74388
- sqlite3VdbeAddOp1(v, OP_If, mem);
74389
- testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
74390
- assert( testAddr>0 || pParse->db->mallocFailed );
74611
+ testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
7439174612
}
7439274613
7439374614
#ifndef SQLITE_OMIT_EXPLAIN
7439474615
if( pParse->explain==2 ){
7439574616
char *zMsg = sqlite3MPrintf(
74396
- pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr?"":"CORRELATED ",
74617
+ pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
7439774618
pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
7439874619
);
7439974620
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
7440074621
}
7440174622
#endif
@@ -74483,13 +74704,13 @@
7448374704
/* If the expression is not constant then we will need to
7448474705
** disable the test that was generated above that makes sure
7448574706
** this code only executes once. Because for a non-constant
7448674707
** expression we need to rerun this code each time.
7448774708
*/
74488
- if( testAddr && !sqlite3ExprIsConstant(pE2) ){
74489
- sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
74490
- testAddr = 0;
74709
+ if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
74710
+ sqlite3VdbeChangeToNoop(v, testAddr);
74711
+ testAddr = -1;
7449174712
}
7449274713
7449374714
/* Evaluate the expression and insert it into the temp table */
7449474715
if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
7449574716
sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
@@ -74554,12 +74775,12 @@
7455474775
ExprSetIrreducible(pExpr);
7455574776
break;
7455674777
}
7455774778
}
7455874779
74559
- if( testAddr ){
74560
- sqlite3VdbeJumpHere(v, testAddr-1);
74780
+ if( testAddr>=0 ){
74781
+ sqlite3VdbeJumpHere(v, testAddr);
7456174782
}
7456274783
sqlite3ExprCachePop(pParse, 1);
7456374784
7456474785
return rReg;
7456574786
}
@@ -75077,11 +75298,11 @@
7507775298
if( !pAggInfo->directMode ){
7507875299
assert( pCol->iMem>0 );
7507975300
inReg = pCol->iMem;
7508075301
break;
7508175302
}else if( pAggInfo->useSortingIdx ){
75082
- sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
75303
+ sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
7508375304
pCol->iSorterColumn, target);
7508475305
break;
7508575306
}
7508675307
/* Otherwise, fall thru into the TK_COLUMN case */
7508775308
}
@@ -81235,27 +81456,19 @@
8123581456
Table *pTab = pIndex->pTable; /* The table that is indexed */
8123681457
int iTab = pParse->nTab++; /* Btree cursor used for pTab */
8123781458
int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
8123881459
int iSorter = iTab; /* Cursor opened by OpenSorter (if in use) */
8123981460
int addr1; /* Address of top of loop */
81461
+ int addr2; /* Address to jump to for next iteration */
8124081462
int tnum; /* Root page of index */
8124181463
Vdbe *v; /* Generate code into this virtual machine */
8124281464
KeyInfo *pKey; /* KeyInfo for index */
8124381465
int regIdxKey; /* Registers containing the index key */
8124481466
int regRecord; /* Register holding assemblied index record */
8124581467
sqlite3 *db = pParse->db; /* The database connection */
8124681468
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
8124781469
81248
- /* Set bUseSorter to use OP_OpenSorter, or clear it to insert directly
81249
- ** into the index. The sorter is used unless either OMIT_MERGE_SORT is
81250
- ** defined or the system is configured to store temp files in-memory. */
81251
-#ifdef SQLITE_OMIT_MERGE_SORT
81252
- static const int bUseSorter = 0;
81253
-#else
81254
- const int bUseSorter = !sqlite3TempInMemory(pParse->db);
81255
-#endif
81256
-
8125781470
#ifndef SQLITE_OMIT_AUTHORIZATION
8125881471
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
8125981472
db->aDb[iDb].zName ) ){
8126081473
return;
8126181474
}
@@ -81277,32 +81490,44 @@
8127781490
(char *)pKey, P4_KEYINFO_HANDOFF);
8127881491
if( memRootPage>=0 ){
8127981492
sqlite3VdbeChangeP5(v, 1);
8128081493
}
8128181494
81495
+#ifndef SQLITE_OMIT_MERGE_SORT
8128281496
/* Open the sorter cursor if we are to use one. */
81283
- if( bUseSorter ){
81284
- iSorter = pParse->nTab++;
81285
- sqlite3VdbeAddOp4(v, OP_OpenSorter, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
81286
- sqlite3VdbeChangeP5(v, BTREE_SORTER);
81287
- }
81497
+ iSorter = pParse->nTab++;
81498
+ sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
81499
+#endif
8128881500
8128981501
/* Open the table. Loop through all rows of the table, inserting index
8129081502
** records into the sorter. */
8129181503
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
8129281504
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
81505
+ addr2 = addr1 + 1;
8129381506
regRecord = sqlite3GetTempReg(pParse);
8129481507
regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
8129581508
81296
- if( bUseSorter ){
81297
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iSorter, regRecord);
81298
- sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
81299
- sqlite3VdbeJumpHere(v, addr1);
81300
- addr1 = sqlite3VdbeAddOp2(v, OP_Sort, iSorter, 0);
81301
- sqlite3VdbeAddOp2(v, OP_RowKey, iSorter, regRecord);
81302
- }
81303
-
81509
+#ifndef SQLITE_OMIT_MERGE_SORT
81510
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
81511
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
81512
+ sqlite3VdbeJumpHere(v, addr1);
81513
+ addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
81514
+ if( pIndex->onError!=OE_None ){
81515
+ int j2 = sqlite3VdbeCurrentAddr(v) + 3;
81516
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
81517
+ addr2 = sqlite3VdbeCurrentAddr(v);
81518
+ sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
81519
+ sqlite3HaltConstraint(
81520
+ pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
81521
+ );
81522
+ }else{
81523
+ addr2 = sqlite3VdbeCurrentAddr(v);
81524
+ }
81525
+ sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
81526
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
81527
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
81528
+#else
8130481529
if( pIndex->onError!=OE_None ){
8130581530
const int regRowid = regIdxKey + pIndex->nColumn;
8130681531
const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
8130781532
void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
8130881533
@@ -81317,14 +81542,15 @@
8131781542
*/
8131881543
sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
8131981544
sqlite3HaltConstraint(
8132081545
pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
8132181546
}
81322
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, bUseSorter);
81547
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
8132381548
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
81549
+#endif
8132481550
sqlite3ReleaseTempReg(pParse, regRecord);
81325
- sqlite3VdbeAddOp2(v, OP_Next, iSorter, addr1+1);
81551
+ sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
8132681552
sqlite3VdbeJumpHere(v, addr1);
8132781553
8132881554
sqlite3VdbeAddOp1(v, OP_Close, iTab);
8132981555
sqlite3VdbeAddOp1(v, OP_Close, iIdx);
8133081556
sqlite3VdbeAddOp1(v, OP_Close, iSorter);
@@ -92204,10 +92430,12 @@
9220492430
pNew->addrOpenEphm[2] = -1;
9220592431
if( db->mallocFailed ) {
9220692432
clearSelect(db, pNew);
9220792433
if( pNew!=&standin ) sqlite3DbFree(db, pNew);
9220892434
pNew = 0;
92435
+ }else{
92436
+ assert( pNew->pSrc!=0 || pParse->nErr>0 );
9220992437
}
9221092438
return pNew;
9221192439
}
9221292440
9221392441
/*
@@ -92534,16 +92762,22 @@
9253492762
){
9253592763
Vdbe *v = pParse->pVdbe;
9253692764
int nExpr = pOrderBy->nExpr;
9253792765
int regBase = sqlite3GetTempRange(pParse, nExpr+2);
9253892766
int regRecord = sqlite3GetTempReg(pParse);
92767
+ int op;
9253992768
sqlite3ExprCacheClear(pParse);
9254092769
sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
9254192770
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
9254292771
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
9254392772
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
92544
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
92773
+ if( pSelect->selFlags & SF_UseSorter ){
92774
+ op = OP_SorterInsert;
92775
+ }else{
92776
+ op = OP_IdxInsert;
92777
+ }
92778
+ sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
9254592779
sqlite3ReleaseTempReg(pParse, regRecord);
9254692780
sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
9254792781
if( pSelect->iLimit ){
9254892782
int addr1, addr2;
9254992783
int iLimit;
@@ -93008,13 +93242,24 @@
9300893242
sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
9300993243
regRowid = 0;
9301093244
}else{
9301193245
regRowid = sqlite3GetTempReg(pParse);
9301293246
}
93013
- addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
93014
- codeOffset(v, p, addrContinue);
93015
- sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
93247
+ if( p->selFlags & SF_UseSorter ){
93248
+ int regSortOut = ++pParse->nMem;
93249
+ int ptab2 = pParse->nTab++;
93250
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
93251
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
93252
+ codeOffset(v, p, addrContinue);
93253
+ sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
93254
+ sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
93255
+ sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
93256
+ }else{
93257
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
93258
+ codeOffset(v, p, addrContinue);
93259
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
93260
+ }
9301693261
switch( eDest ){
9301793262
case SRT_Table:
9301893263
case SRT_EphemTab: {
9301993264
testcase( eDest==SRT_Table );
9302093265
testcase( eDest==SRT_EphemTab );
@@ -93063,11 +93308,15 @@
9306393308
sqlite3ReleaseTempReg(pParse, regRowid);
9306493309
9306593310
/* The bottom of the loop
9306693311
*/
9306793312
sqlite3VdbeResolveLabel(v, addrContinue);
93068
- sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
93313
+ if( p->selFlags & SF_UseSorter ){
93314
+ sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr);
93315
+ }else{
93316
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
93317
+ }
9306993318
sqlite3VdbeResolveLabel(v, addrBreak);
9307093319
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
9307193320
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
9307293321
}
9307393322
}
@@ -95895,11 +96144,15 @@
9589596144
struct SrcList_item *pItem = &pTabList->a[i];
9589696145
SelectDest dest;
9589796146
Select *pSub = pItem->pSelect;
9589896147
int isAggSub;
9589996148
95900
- if( pSub==0 || pItem->isPopulated ) continue;
96149
+ if( pSub==0 ) continue;
96150
+ if( pItem->addrFillSub ){
96151
+ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
96152
+ continue;
96153
+ }
9590196154
9590296155
/* Increment Parse.nHeight by the height of the largest expression
9590396156
** tree refered to by this, the parent select. The child select
9590496157
** may contain expression trees of at most
9590596158
** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
@@ -95906,25 +96159,48 @@
9590696159
** more conservative than necessary, but much easier than enforcing
9590796160
** an exact limit.
9590896161
*/
9590996162
pParse->nHeight += sqlite3SelectExprHeight(p);
9591096163
95911
- /* Check to see if the subquery can be absorbed into the parent. */
9591296164
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
9591396165
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
96166
+ /* This subquery can be absorbed into its parent. */
9591496167
if( isAggSub ){
9591596168
isAgg = 1;
9591696169
p->selFlags |= SF_Aggregate;
9591796170
}
9591896171
i = -1;
9591996172
}else{
96173
+ /* Generate a subroutine that will fill an ephemeral table with
96174
+ ** the content of this subquery. pItem->addrFillSub will point
96175
+ ** to the address of the generated subroutine. pItem->regReturn
96176
+ ** is a register allocated to hold the subroutine return address
96177
+ */
96178
+ int topAddr;
96179
+ int onceAddr = 0;
96180
+ int retAddr;
96181
+ assert( pItem->addrFillSub==0 );
96182
+ pItem->regReturn = ++pParse->nMem;
96183
+ topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
96184
+ pItem->addrFillSub = topAddr+1;
96185
+ VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
96186
+ if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
96187
+ /* If the subquery is no correlated and if we are not inside of
96188
+ ** a trigger, then we only need to compute the value of the subquery
96189
+ ** once. */
96190
+ int regOnce = ++pParse->nMem;
96191
+ onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
96192
+ }
9592096193
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
95921
- assert( pItem->isPopulated==0 );
9592296194
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
9592396195
sqlite3Select(pParse, pSub, &dest);
95924
- pItem->isPopulated = 1;
9592596196
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
96197
+ if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
96198
+ retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
96199
+ VdbeComment((v, "end %s", pItem->pTab->zName));
96200
+ sqlite3VdbeChangeP1(v, topAddr, retAddr);
96201
+
9592696202
}
9592796203
if( /*pParse->nErr ||*/ db->mallocFailed ){
9592896204
goto select_end;
9592996205
}
9593096206
pParse->nHeight -= sqlite3SelectExprHeight(p);
@@ -96029,10 +96305,14 @@
9602996305
/* Set the limiter.
9603096306
*/
9603196307
iEnd = sqlite3VdbeMakeLabel(v);
9603296308
p->nSelectRow = (double)LARGEST_INT64;
9603396309
computeLimitRegisters(pParse, p, iEnd);
96310
+ if( p->iLimit==0 && addrSortIndex>=0 ){
96311
+ sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
96312
+ p->selFlags |= SF_UseSorter;
96313
+ }
9603496314
9603596315
/* Open a virtual index to use for the distinct set.
9603696316
*/
9603796317
if( p->selFlags & SF_Distinct ){
9603896318
KeyInfo *pKeyInfo;
@@ -96057,18 +96337,18 @@
9605796337
/* If sorting index that was created by a prior OP_OpenEphemeral
9605896338
** instruction ended up not being needed, then change the OP_OpenEphemeral
9605996339
** into an OP_Noop.
9606096340
*/
9606196341
if( addrSortIndex>=0 && pOrderBy==0 ){
96062
- sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
96342
+ sqlite3VdbeChangeToNoop(v, addrSortIndex);
9606396343
p->addrOpenEphm[2] = -1;
9606496344
}
9606596345
9606696346
if( pWInfo->eDistinct ){
9606796347
VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
9606896348
96069
- assert( addrDistinctIndex>0 );
96349
+ assert( addrDistinctIndex>=0 );
9607096350
pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
9607196351
9607296352
assert( isDistinct );
9607396353
assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
9607496354
|| pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
@@ -96123,10 +96403,12 @@
9612396403
** one row of the input to the aggregator has been
9612496404
** processed */
9612596405
int iAbortFlag; /* Mem address which causes query abort if positive */
9612696406
int groupBySort; /* Rows come from source in GROUP BY order */
9612796407
int addrEnd; /* End of processing for this SELECT */
96408
+ int sortPTab = 0; /* Pseudotable used to decode sorting results */
96409
+ int sortOut = 0; /* Output register from the sorter */
9612896410
9612996411
/* Remove any and all aliases between the result set and the
9613096412
** GROUP BY clause.
9613196413
*/
9613296414
if( pGroupBy ){
@@ -96184,16 +96466,16 @@
9618496466
int addrReset; /* Subroutine for resetting the accumulator */
9618596467
int regReset; /* Return address register for reset subroutine */
9618696468
9618796469
/* If there is a GROUP BY clause we might need a sorting index to
9618896470
** implement it. Allocate that sorting index now. If it turns out
96189
- ** that we do not need it after all, the OpenEphemeral instruction
96471
+ ** that we do not need it after all, the OP_SorterOpen instruction
9619096472
** will be converted into a Noop.
9619196473
*/
9619296474
sAggInfo.sortingIdx = pParse->nTab++;
9619396475
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
96194
- addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
96476
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
9619596477
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
9619696478
0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
9619796479
9619896480
/* Initialize memory locations used by GROUP BY aggregate processing
9619996481
*/
@@ -96270,15 +96552,18 @@
9627096552
j++;
9627196553
}
9627296554
}
9627396555
regRecord = sqlite3GetTempReg(pParse);
9627496556
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
96275
- sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
96557
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
9627696558
sqlite3ReleaseTempReg(pParse, regRecord);
9627796559
sqlite3ReleaseTempRange(pParse, regBase, nCol);
9627896560
sqlite3WhereEnd(pWInfo);
96279
- sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
96561
+ sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
96562
+ sortOut = sqlite3GetTempReg(pParse);
96563
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
96564
+ sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
9628096565
VdbeComment((v, "GROUP BY sort"));
9628196566
sAggInfo.useSortingIdx = 1;
9628296567
sqlite3ExprCacheClear(pParse);
9628396568
}
9628496569
@@ -96287,13 +96572,17 @@
9628796572
** Then compare the current GROUP BY terms against the GROUP BY terms
9628896573
** from the previous row currently stored in a0, a1, a2...
9628996574
*/
9629096575
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
9629196576
sqlite3ExprCacheClear(pParse);
96577
+ if( groupBySort ){
96578
+ sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
96579
+ }
9629296580
for(j=0; j<pGroupBy->nExpr; j++){
9629396581
if( groupBySort ){
96294
- sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j);
96582
+ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
96583
+ if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
9629596584
}else{
9629696585
sAggInfo.directMode = 1;
9629796586
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
9629896587
}
9629996588
}
@@ -96328,14 +96617,14 @@
9632896617
VdbeComment((v, "indicate data in accumulator"));
9632996618
9633096619
/* End of the loop
9633196620
*/
9633296621
if( groupBySort ){
96333
- sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop);
96622
+ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
9633496623
}else{
9633596624
sqlite3WhereEnd(pWInfo);
96336
- sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
96625
+ sqlite3VdbeChangeToNoop(v, addrSortingIdx);
9633796626
}
9633896627
9633996628
/* Output the final row of result
9634096629
*/
9634196630
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
@@ -100517,15 +100806,23 @@
100517100806
return mask;
100518100807
}
100519100808
static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
100520100809
Bitmask mask = 0;
100521100810
while( pS ){
100811
+ SrcList *pSrc = pS->pSrc;
100522100812
mask |= exprListTableUsage(pMaskSet, pS->pEList);
100523100813
mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
100524100814
mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
100525100815
mask |= exprTableUsage(pMaskSet, pS->pWhere);
100526100816
mask |= exprTableUsage(pMaskSet, pS->pHaving);
100817
+ if( ALWAYS(pSrc!=0) ){
100818
+ int i;
100819
+ for(i=0; i<pSrc->nSrc; i++){
100820
+ mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
100821
+ mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
100822
+ }
100823
+ }
100527100824
pS = pS->pPrior;
100528100825
}
100529100826
return mask;
100530100827
}
100531100828
@@ -102044,12 +102341,11 @@
102044102341
/* Generate code to skip over the creation and initialization of the
102045102342
** transient index on 2nd and subsequent iterations of the loop. */
102046102343
v = pParse->pVdbe;
102047102344
assert( v!=0 );
102048102345
regIsInit = ++pParse->nMem;
102049
- addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
102050
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
102346
+ addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
102051102347
102052102348
/* Count the number of columns that will be added to the index
102053102349
** and used to match WHERE clause constraints */
102054102350
nColumn = 0;
102055102351
pTable = pSrc->pTab;
@@ -115981,11 +116277,41 @@
115981116277
char *aOut;
115982116278
int bFirstOut = 0;
115983116279
115984116280
*paOut = 0;
115985116281
*pnOut = 0;
115986
- aOut = sqlite3_malloc(n1+n2);
116282
+
116283
+ /* Allocate space for the output. Both the input and output doclists
116284
+ ** are delta encoded. If they are in ascending order (bDescDoclist==0),
116285
+ ** then the first docid in each list is simply encoded as a varint. For
116286
+ ** each subsequent docid, the varint stored is the difference between the
116287
+ ** current and previous docid (a positive number - since the list is in
116288
+ ** ascending order).
116289
+ **
116290
+ ** The first docid written to the output is therefore encoded using the
116291
+ ** same number of bytes as it is in whichever of the input lists it is
116292
+ ** read from. And each subsequent docid read from the same input list
116293
+ ** consumes either the same or less bytes as it did in the input (since
116294
+ ** the difference between it and the previous value in the output must
116295
+ ** be a positive value less than or equal to the delta value read from
116296
+ ** the input list). The same argument applies to all but the first docid
116297
+ ** read from the 'other' list. And to the contents of all position lists
116298
+ ** that will be copied and merged from the input to the output.
116299
+ **
116300
+ ** However, if the first docid copied to the output is a negative number,
116301
+ ** then the encoding of the first docid from the 'other' input list may
116302
+ ** be larger in the output than it was in the input (since the delta value
116303
+ ** may be a larger positive integer than the actual docid).
116304
+ **
116305
+ ** The space required to store the output is therefore the sum of the
116306
+ ** sizes of the two inputs, plus enough space for exactly one of the input
116307
+ ** docids to grow.
116308
+ **
116309
+ ** A symetric argument may be made if the doclists are in descending
116310
+ ** order.
116311
+ */
116312
+ aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
115987116313
if( !aOut ) return SQLITE_NOMEM;
115988116314
115989116315
p = aOut;
115990116316
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
115991116317
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
@@ -116008,10 +116334,11 @@
116008116334
}
116009116335
}
116010116336
116011116337
*paOut = aOut;
116012116338
*pnOut = (p-aOut);
116339
+ assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
116013116340
return SQLITE_OK;
116014116341
}
116015116342
116016116343
/*
116017116344
** This function does a "phrase" merge of two doclists. In a phrase merge,
116018116345
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -656,11 +656,11 @@
656 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657 ** [sqlite_version()] and [sqlite_source_id()].
658 */
659 #define SQLITE_VERSION "3.7.8"
660 #define SQLITE_VERSION_NUMBER 3007008
661 #define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
662
663 /*
664 ** CAPI3REF: Run-Time Library Version Numbers
665 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
666 **
@@ -7632,18 +7632,10 @@
7632 */
7633 #ifndef SQLITE_TEMP_STORE
7634 # define SQLITE_TEMP_STORE 1
7635 #endif
7636
7637 /*
7638 ** If all temporary storage is in-memory, then omit the external merge-sort
7639 ** logic since it is superfluous.
7640 */
7641 #if SQLITE_TEMP_STORE==3 && !defined(SQLITE_OMIT_MERGE_SORT)
7642 # define SQLITE_OMIT_MERGE_SORT
7643 #endif
7644
7645 /*
7646 ** GCC does not define the offsetof() macro so we'll have to do it
7647 ** ourselves.
7648 */
7649 #ifndef offsetof
@@ -7982,11 +7974,10 @@
7982 #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
7983 #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
7984 #define BTREE_MEMORY 4 /* This is an in-memory DB */
7985 #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
7986 #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
7987 #define BTREE_SORTER 32 /* Used as accumulator in external merge sort */
7988
7989 SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
7990 SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
7991 SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
7992 SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
@@ -8383,106 +8374,109 @@
8383 #define OP_Jump 25
8384 #define OP_And 69 /* same as TK_AND */
8385 #define OP_Or 68 /* same as TK_OR */
8386 #define OP_Not 19 /* same as TK_NOT */
8387 #define OP_BitNot 93 /* same as TK_BITNOT */
8388 #define OP_If 26
8389 #define OP_IfNot 27
 
8390 #define OP_IsNull 73 /* same as TK_ISNULL */
8391 #define OP_NotNull 74 /* same as TK_NOTNULL */
8392 #define OP_Column 28
8393 #define OP_Affinity 29
8394 #define OP_MakeRecord 30
8395 #define OP_Count 31
8396 #define OP_Savepoint 32
8397 #define OP_AutoCommit 33
8398 #define OP_Transaction 34
8399 #define OP_ReadCookie 35
8400 #define OP_SetCookie 36
8401 #define OP_VerifyCookie 37
8402 #define OP_OpenRead 38
8403 #define OP_OpenWrite 39
8404 #define OP_OpenSorter 40
8405 #define OP_OpenAutoindex 41
8406 #define OP_OpenEphemeral 42
8407 #define OP_OpenPseudo 43
8408 #define OP_Close 44
8409 #define OP_SeekLt 45
8410 #define OP_SeekLe 46
8411 #define OP_SeekGe 47
8412 #define OP_SeekGt 48
8413 #define OP_Seek 49
8414 #define OP_NotFound 50
8415 #define OP_Found 51
8416 #define OP_IsUnique 52
8417 #define OP_NotExists 53
8418 #define OP_Sequence 54
8419 #define OP_NewRowid 55
8420 #define OP_Insert 56
8421 #define OP_InsertInt 57
8422 #define OP_Delete 58
8423 #define OP_ResetCount 59
8424 #define OP_RowKey 60
8425 #define OP_RowData 61
8426 #define OP_Rowid 62
8427 #define OP_NullRow 63
8428 #define OP_Last 64
8429 #define OP_Sort 65
8430 #define OP_Rewind 66
8431 #define OP_Prev 67
8432 #define OP_Next 70
8433 #define OP_IdxInsert 71
8434 #define OP_IdxDelete 72
8435 #define OP_IdxRowid 81
8436 #define OP_IdxLT 92
8437 #define OP_IdxGE 95
8438 #define OP_Destroy 96
8439 #define OP_Clear 97
8440 #define OP_CreateIndex 98
8441 #define OP_CreateTable 99
8442 #define OP_ParseSchema 100
8443 #define OP_LoadAnalysis 101
8444 #define OP_DropTable 102
8445 #define OP_DropIndex 103
8446 #define OP_DropTrigger 104
8447 #define OP_IntegrityCk 105
8448 #define OP_RowSetAdd 106
8449 #define OP_RowSetRead 107
8450 #define OP_RowSetTest 108
8451 #define OP_Program 109
8452 #define OP_Param 110
8453 #define OP_FkCounter 111
8454 #define OP_FkIfZero 112
8455 #define OP_MemMax 113
8456 #define OP_IfPos 114
8457 #define OP_IfNeg 115
8458 #define OP_IfZero 116
8459 #define OP_AggStep 117
8460 #define OP_AggFinal 118
8461 #define OP_Checkpoint 119
8462 #define OP_JournalMode 120
8463 #define OP_Vacuum 121
8464 #define OP_IncrVacuum 122
8465 #define OP_Expire 123
8466 #define OP_TableLock 124
8467 #define OP_VBegin 125
8468 #define OP_VCreate 126
8469 #define OP_VDestroy 127
8470 #define OP_VOpen 128
8471 #define OP_VFilter 129
8472 #define OP_VColumn 131
8473 #define OP_VNext 132
8474 #define OP_VRename 133
8475 #define OP_VUpdate 134
8476 #define OP_Pagecount 135
8477 #define OP_MaxPgcnt 136
8478 #define OP_Trace 137
8479 #define OP_Noop 138
8480 #define OP_Explain 139
8481
8482 /* The following opcode values are never used */
8483 #define OP_NotUsed_140 140
 
 
 
8484
8485
8486 /* Properties such as "out2" or "jump" that are specified in
8487 ** comments following the "case" for each opcode in the vdbe.c
8488 ** are encoded into bitvectors as follows:
@@ -8496,26 +8490,26 @@
8496 #define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
8497 #define OPFLG_INITIALIZER {\
8498 /* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
8499 /* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
8500 /* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
8501 /* 24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
8502 /* 32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
8503 /* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,\
8504 /* 48 */ 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02,\
8505 /* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,\
8506 /* 64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x01, 0x08,\
8507 /* 72 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8508 /* 80 */ 0x15, 0x02, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
8509 /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
8510 /* 96 */ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\
8511 /* 104 */ 0x00, 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00,\
8512 /* 112 */ 0x01, 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
8513 /* 120 */ 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\
8514 /* 128 */ 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x02,\
8515 /* 136 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
8516 /* 144 */ 0x04, 0x04,}
8517
8518 /************** End of opcodes.h *********************************************/
8519 /************** Continuing where we left off in vdbe.h ***********************/
8520
8521 /*
@@ -8534,11 +8528,11 @@
8534 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
8535 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
8536 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
8537 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
8538 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
8539 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
8540 SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
8541 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
8542 SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
8543 SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
8544 SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
@@ -8566,13 +8560,13 @@
8566 SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
8567 #ifndef SQLITE_OMIT_TRACE
8568 SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
8569 #endif
8570
8571 SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int);
8572 SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
8573 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
 
8574
8575 #ifndef SQLITE_OMIT_TRIGGER
8576 SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
8577 #endif
8578
@@ -8653,11 +8647,10 @@
8653 ** NOTE: These values must match the corresponding BTREE_ values in btree.h.
8654 */
8655 #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
8656 #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
8657 #define PAGER_MEMORY 0x0004 /* In-memory database */
8658 #define PAGER_SORTER 0x0020 /* Accumulator in external merge sort */
8659
8660 /*
8661 ** Valid values for the second argument to sqlite3PagerLockingMode().
8662 */
8663 #define PAGER_LOCKINGMODE_QUERY -1
@@ -8749,13 +8742,10 @@
8749 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
8750 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
8751 SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
8752 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
8753 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
8754 #ifndef SQLITE_OMIT_MERGE_SORT
8755 SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager*);
8756 #endif
8757
8758 /* Functions used to truncate the database file. */
8759 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
8760
8761 #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
@@ -10186,10 +10176,11 @@
10186 u8 directMode; /* Direct rendering mode means take data directly
10187 ** from source tables rather than from accumulators */
10188 u8 useSortingIdx; /* In direct mode, reference the sorting index rather
10189 ** than the source table */
10190 int sortingIdx; /* Cursor number of the sorting index */
 
10191 ExprList *pGroupBy; /* The group by clause */
10192 int nSortingColumn; /* Number of columns in the sorting index */
10193 struct AggInfo_col { /* For each column used in source tables */
10194 Table *pTab; /* Source table */
10195 int iTable; /* Cursor number of the source table */
@@ -10495,11 +10486,12 @@
10495 char *zDatabase; /* Name of database holding this table */
10496 char *zName; /* Name of the table */
10497 char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
10498 Table *pTab; /* An SQL table corresponding to zName */
10499 Select *pSelect; /* A SELECT statement used in place of a table name */
10500 u8 isPopulated; /* Temporary table associated with SELECT is populated */
 
10501 u8 jointype; /* Type of join between this able and the previous */
10502 u8 notIndexed; /* True if there is a NOT INDEXED clause */
10503 u8 isCorrelated; /* True if sub-query is correlated */
10504 #ifndef SQLITE_OMIT_EXPLAIN
10505 u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
@@ -10718,10 +10710,11 @@
10718 #define SF_Resolved 0x0002 /* Identifiers have been resolved */
10719 #define SF_Aggregate 0x0004 /* Contains aggregate functions */
10720 #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
10721 #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
10722 #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
 
10723
10724
10725 /*
10726 ** The results of a select can be distributed in several ways. The
10727 ** "SRT" prefix means "SELECT Result Type".
@@ -12044,11 +12037,11 @@
12044 SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
12045 1, /* bCoreMutex */
12046 SQLITE_THREADSAFE==1, /* bFullMutex */
12047 SQLITE_USE_URI, /* bOpenUri */
12048 0x7ffffffe, /* mxStrlen */
12049 100, /* szLookaside */
12050 500, /* nLookaside */
12051 {0,0,0,0,0,0,0,0}, /* m */
12052 {0,0,0,0,0,0,0,0,0}, /* mutex */
12053 {0,0,0,0,0,0,0,0,0,0,0}, /* pcache */
12054 (void*)0, /* pHeap */
@@ -12267,10 +12260,13 @@
12267 "INT64_TYPE",
12268 #endif
12269 #ifdef SQLITE_LOCK_TRACE
12270 "LOCK_TRACE",
12271 #endif
 
 
 
12272 #ifdef SQLITE_MEMDEBUG
12273 "MEMDEBUG",
12274 #endif
12275 #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
12276 "MIXED_ENDIAN_64BIT_FLOAT",
@@ -12601,16 +12597,17 @@
12601 Bool nullRow; /* True if pointing to a row with no data */
12602 Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
12603 Bool isTable; /* True if a table requiring integer keys */
12604 Bool isIndex; /* True if an index containing keys only - no data */
12605 Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
 
12606 sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
12607 const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
12608 i64 seqCount; /* Sequence counter */
12609 i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
12610 i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
12611 VdbeSorter *pSorter; /* Sorter object for OP_OpenSorter cursors */
12612
12613 /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
12614 ** OP_IsUnique opcode on this cursor. */
12615 int seekResult;
12616
@@ -12944,17 +12941,19 @@
12944 # define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
12945 # define sqlite3VdbeSorterClose(Y,Z)
12946 # define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
12947 # define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
12948 # define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
 
12949 #else
12950 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
12951 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, int);
12952 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
12953 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
12954 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
12955 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
 
 
 
12956 #endif
12957
12958 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
12959 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
12960 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
@@ -14537,11 +14536,11 @@
14537 int flags,
14538 int *pOutFlags
14539 ){
14540 int rc = SQLITE_NOMEM;
14541 sqlite3_file *pFile;
14542 pFile = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile);
14543 if( pFile ){
14544 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
14545 if( rc!=SQLITE_OK ){
14546 sqlite3_free(pFile);
14547 }else{
@@ -22100,66 +22099,66 @@
22100 /* 21 */ "MustBeInt",
22101 /* 22 */ "RealAffinity",
22102 /* 23 */ "Permutation",
22103 /* 24 */ "Compare",
22104 /* 25 */ "Jump",
22105 /* 26 */ "If",
22106 /* 27 */ "IfNot",
22107 /* 28 */ "Column",
22108 /* 29 */ "Affinity",
22109 /* 30 */ "MakeRecord",
22110 /* 31 */ "Count",
22111 /* 32 */ "Savepoint",
22112 /* 33 */ "AutoCommit",
22113 /* 34 */ "Transaction",
22114 /* 35 */ "ReadCookie",
22115 /* 36 */ "SetCookie",
22116 /* 37 */ "VerifyCookie",
22117 /* 38 */ "OpenRead",
22118 /* 39 */ "OpenWrite",
22119 /* 40 */ "OpenSorter",
22120 /* 41 */ "OpenAutoindex",
22121 /* 42 */ "OpenEphemeral",
22122 /* 43 */ "OpenPseudo",
22123 /* 44 */ "Close",
22124 /* 45 */ "SeekLt",
22125 /* 46 */ "SeekLe",
22126 /* 47 */ "SeekGe",
22127 /* 48 */ "SeekGt",
22128 /* 49 */ "Seek",
22129 /* 50 */ "NotFound",
22130 /* 51 */ "Found",
22131 /* 52 */ "IsUnique",
22132 /* 53 */ "NotExists",
22133 /* 54 */ "Sequence",
22134 /* 55 */ "NewRowid",
22135 /* 56 */ "Insert",
22136 /* 57 */ "InsertInt",
22137 /* 58 */ "Delete",
22138 /* 59 */ "ResetCount",
22139 /* 60 */ "RowKey",
22140 /* 61 */ "RowData",
22141 /* 62 */ "Rowid",
22142 /* 63 */ "NullRow",
22143 /* 64 */ "Last",
22144 /* 65 */ "Sort",
22145 /* 66 */ "Rewind",
22146 /* 67 */ "Prev",
22147 /* 68 */ "Or",
22148 /* 69 */ "And",
22149 /* 70 */ "Next",
22150 /* 71 */ "IdxInsert",
22151 /* 72 */ "IdxDelete",
22152 /* 73 */ "IsNull",
22153 /* 74 */ "NotNull",
22154 /* 75 */ "Ne",
22155 /* 76 */ "Eq",
22156 /* 77 */ "Gt",
22157 /* 78 */ "Le",
22158 /* 79 */ "Lt",
22159 /* 80 */ "Ge",
22160 /* 81 */ "IdxRowid",
22161 /* 82 */ "BitAnd",
22162 /* 83 */ "BitOr",
22163 /* 84 */ "ShiftLeft",
22164 /* 85 */ "ShiftRight",
22165 /* 86 */ "Add",
@@ -22166,64 +22165,69 @@
22166 /* 87 */ "Subtract",
22167 /* 88 */ "Multiply",
22168 /* 89 */ "Divide",
22169 /* 90 */ "Remainder",
22170 /* 91 */ "Concat",
22171 /* 92 */ "IdxLT",
22172 /* 93 */ "BitNot",
22173 /* 94 */ "String8",
22174 /* 95 */ "IdxGE",
22175 /* 96 */ "Destroy",
22176 /* 97 */ "Clear",
22177 /* 98 */ "CreateIndex",
22178 /* 99 */ "CreateTable",
22179 /* 100 */ "ParseSchema",
22180 /* 101 */ "LoadAnalysis",
22181 /* 102 */ "DropTable",
22182 /* 103 */ "DropIndex",
22183 /* 104 */ "DropTrigger",
22184 /* 105 */ "IntegrityCk",
22185 /* 106 */ "RowSetAdd",
22186 /* 107 */ "RowSetRead",
22187 /* 108 */ "RowSetTest",
22188 /* 109 */ "Program",
22189 /* 110 */ "Param",
22190 /* 111 */ "FkCounter",
22191 /* 112 */ "FkIfZero",
22192 /* 113 */ "MemMax",
22193 /* 114 */ "IfPos",
22194 /* 115 */ "IfNeg",
22195 /* 116 */ "IfZero",
22196 /* 117 */ "AggStep",
22197 /* 118 */ "AggFinal",
22198 /* 119 */ "Checkpoint",
22199 /* 120 */ "JournalMode",
22200 /* 121 */ "Vacuum",
22201 /* 122 */ "IncrVacuum",
22202 /* 123 */ "Expire",
22203 /* 124 */ "TableLock",
22204 /* 125 */ "VBegin",
22205 /* 126 */ "VCreate",
22206 /* 127 */ "VDestroy",
22207 /* 128 */ "VOpen",
22208 /* 129 */ "VFilter",
22209 /* 130 */ "Real",
22210 /* 131 */ "VColumn",
22211 /* 132 */ "VNext",
22212 /* 133 */ "VRename",
22213 /* 134 */ "VUpdate",
22214 /* 135 */ "Pagecount",
22215 /* 136 */ "MaxPgcnt",
22216 /* 137 */ "Trace",
22217 /* 138 */ "Noop",
22218 /* 139 */ "Explain",
22219 /* 140 */ "NotUsed_140",
22220 /* 141 */ "ToText",
22221 /* 142 */ "ToBlob",
22222 /* 143 */ "ToNumeric",
22223 /* 144 */ "ToInt",
22224 /* 145 */ "ToReal",
 
 
 
 
 
22225 };
22226 return azName[i];
22227 }
22228 #endif
22229
@@ -22314,11 +22318,11 @@
22314 */
22315 #ifdef MEMORY_DEBUG
22316 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
22317 #endif
22318
22319 #ifdef SQLITE_DEBUG
22320 # ifndef SQLITE_DEBUG_OS_TRACE
22321 # define SQLITE_DEBUG_OS_TRACE 0
22322 # endif
22323 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
22324 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -24656,11 +24660,11 @@
24656 */
24657 #ifdef MEMORY_DEBUG
24658 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
24659 #endif
24660
24661 #ifdef SQLITE_DEBUG
24662 # ifndef SQLITE_DEBUG_OS_TRACE
24663 # define SQLITE_DEBUG_OS_TRACE 0
24664 # endif
24665 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
24666 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -27716,15 +27720,15 @@
27716 SQLITE_API int sqlite3_fullsync_count = 0;
27717 #endif
27718
27719 /*
27720 ** We do not trust systems to provide a working fdatasync(). Some do.
27721 ** Others do no. To be safe, we will stick with the (slower) fsync().
27722 ** If you know that your system does support fdatasync() correctly,
27723 ** then simply compile with -Dfdatasync=fdatasync
27724 */
27725 #if !defined(fdatasync) && !defined(__linux__)
27726 # define fdatasync fsync
27727 #endif
27728
27729 /*
27730 ** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
@@ -28015,11 +28019,11 @@
28015 ** file-control operation. Enlarge the database to nBytes in size
28016 ** (rounded up to the next chunk-size). If the database is already
28017 ** nBytes or larger, this routine is a no-op.
28018 */
28019 static int fcntlSizeHint(unixFile *pFile, i64 nByte){
28020 if( pFile->szChunk ){
28021 i64 nSize; /* Required file size */
28022 struct stat buf; /* Used to hold return values of fstat() */
28023
28024 if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
28025
@@ -28210,15 +28214,13 @@
28210 */
28211 struct unixShm {
28212 unixShmNode *pShmNode; /* The underlying unixShmNode object */
28213 unixShm *pNext; /* Next unixShm with the same unixShmNode */
28214 u8 hasMutex; /* True if holding the unixShmNode mutex */
 
28215 u16 sharedMask; /* Mask of shared locks held */
28216 u16 exclMask; /* Mask of exclusive locks held */
28217 #ifdef SQLITE_DEBUG
28218 u8 id; /* Id of this connection within its unixShmNode */
28219 #endif
28220 };
28221
28222 /*
28223 ** Constants used for locking
28224 */
@@ -31435,11 +31437,11 @@
31435 */
31436 #ifdef MEMORY_DEBUG
31437 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
31438 #endif
31439
31440 #ifdef SQLITE_DEBUG
31441 # ifndef SQLITE_DEBUG_OS_TRACE
31442 # define SQLITE_DEBUG_OS_TRACE 0
31443 # endif
31444 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
31445 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -32768,11 +32770,11 @@
32768 /* If the user has configured a chunk-size for this file, truncate the
32769 ** file so that it consists of an integer number of chunks (i.e. the
32770 ** actual file size after the operation may be larger than the requested
32771 ** size).
32772 */
32773 if( pFile->szChunk ){
32774 nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
32775 }
32776
32777 /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
32778 if( seekWinFile(pFile, nByte) ){
@@ -32797,13 +32799,23 @@
32797
32798 /*
32799 ** Make sure all writes to a particular file are committed to disk.
32800 */
32801 static int winSync(sqlite3_file *id, int flags){
32802 #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
32803 winFile *pFile = (winFile*)id;
 
 
32804 BOOL rc;
 
 
 
 
 
 
 
 
32805 #else
32806 UNUSED_PARAMETER(id);
32807 #endif
32808
32809 assert( pFile );
@@ -33155,22 +33167,24 @@
33155 case SQLITE_FCNTL_CHUNK_SIZE: {
33156 pFile->szChunk = *(int *)pArg;
33157 return SQLITE_OK;
33158 }
33159 case SQLITE_FCNTL_SIZE_HINT: {
33160 winFile *pFile = (winFile*)id;
33161 sqlite3_int64 oldSz;
33162 int rc = winFileSize(id, &oldSz);
33163 if( rc==SQLITE_OK ){
33164 sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
33165 if( newSz>oldSz ){
33166 SimulateIOErrorBenign(1);
33167 rc = winTruncate(id, newSz);
33168 SimulateIOErrorBenign(0);
33169 }
33170 }
33171 return rc;
 
 
33172 }
33173 case SQLITE_FCNTL_PERSIST_WAL: {
33174 int bPersist = *(int*)pArg;
33175 if( bPersist<0 ){
33176 *(int*)pArg = pFile->bPersistWal;
@@ -38136,12 +38150,10 @@
38136 u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
38137 u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
38138 u8 tempFile; /* zFilename is a temporary file */
38139 u8 readOnly; /* True for a read-only database */
38140 u8 memDb; /* True to inhibit all file I/O */
38141 u8 hasSeenStress; /* pagerStress() called one or more times */
38142 u8 isSorter; /* True for a PAGER_SORTER */
38143
38144 /**************************************************************************
38145 ** The following block contains those class members that change during
38146 ** routine opertion. Class members not in this block are either fixed
38147 ** when the pager is first created or else only change when there is a
@@ -38361,19 +38373,10 @@
38361 );
38362 assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
38363 assert( pagerUseWal(p)==0 );
38364 }
38365
38366 /* A sorter is a temp file that never spills to disk and always has
38367 ** the doNotSpill flag set
38368 */
38369 if( p->isSorter ){
38370 assert( p->tempFile );
38371 assert( p->doNotSpill );
38372 assert( p->fd->pMethods==0 );
38373 }
38374
38375 /* If changeCountDone is set, a RESERVED lock or greater must be held
38376 ** on the file.
38377 */
38378 assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
38379 assert( p->eLock!=PENDING_LOCK );
@@ -41701,11 +41704,10 @@
41701 ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1
41702 ** while in the error state, hence it is impossible for this routine to
41703 ** be called in the error state. Nevertheless, we include a NEVER()
41704 ** test for the error state as a safeguard against future changes.
41705 */
41706 pPager->hasSeenStress = 1;
41707 if( NEVER(pPager->errCode) ) return SQLITE_OK;
41708 if( pPager->doNotSpill ) return SQLITE_OK;
41709 if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
41710 return SQLITE_OK;
41711 }
@@ -42073,16 +42075,10 @@
42073 }
42074 /* pPager->xBusyHandler = 0; */
42075 /* pPager->pBusyHandlerArg = 0; */
42076 pPager->xReiniter = xReinit;
42077 /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
42078 #ifndef SQLITE_OMIT_MERGE_SORT
42079 if( flags & PAGER_SORTER ){
42080 pPager->doNotSpill = 1;
42081 pPager->isSorter = 1;
42082 }
42083 #endif
42084
42085 *ppPager = pPager;
42086 return SQLITE_OK;
42087 }
42088
@@ -43623,21 +43619,10 @@
43623 */
43624 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
43625 return MEMDB;
43626 }
43627
43628 #ifndef SQLITE_OMIT_MERGE_SORT
43629 /*
43630 ** Return true if the pager has seen a pagerStress callback.
43631 */
43632 SQLITE_PRIVATE int sqlite3PagerUnderStress(Pager *pPager){
43633 assert( pPager->isSorter );
43634 assert( pPager->doNotSpill );
43635 return pPager->hasSeenStress;
43636 }
43637 #endif
43638
43639 /*
43640 ** Check that there are at least nSavepoint savepoints open. If there are
43641 ** currently less than nSavepoints open, then open one or more savepoints
43642 ** to make up the difference. If the number of savepoints is already
43643 ** equal to nSavepoint, then this function is a no-op.
@@ -48924,22 +48909,25 @@
48924 int *pRes /* Write search results here */
48925 ){
48926 int rc; /* Status code */
48927 UnpackedRecord *pIdxKey; /* Unpacked index key */
48928 char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */
 
48929
48930 if( pKey ){
48931 assert( nKey==(i64)(int)nKey );
48932 pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey,
48933 aSpace, sizeof(aSpace));
 
48934 if( pIdxKey==0 ) return SQLITE_NOMEM;
 
48935 }else{
48936 pIdxKey = 0;
48937 }
48938 rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
48939 if( pKey ){
48940 sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
48941 }
48942 return rc;
48943 }
48944
48945 /*
@@ -50002,26 +49990,15 @@
50002 assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
50003
50004 /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
50005 assert( (flags & BTREE_SINGLE)==0 || isTempDb );
50006
50007 /* The BTREE_SORTER flag is only used if SQLITE_OMIT_MERGE_SORT is undef */
50008 #ifdef SQLITE_OMIT_MERGE_SORT
50009 assert( (flags & BTREE_SORTER)==0 );
50010 #endif
50011
50012 /* BTREE_SORTER is always on a BTREE_SINGLE, BTREE_OMIT_JOURNAL */
50013 assert( (flags & BTREE_SORTER)==0 ||
50014 (flags & (BTREE_SINGLE|BTREE_OMIT_JOURNAL))
50015 ==(BTREE_SINGLE|BTREE_OMIT_JOURNAL) );
50016
50017 if( db->flags & SQLITE_NoReadlock ){
50018 flags |= BTREE_NO_READLOCK;
50019 }
50020 if( isMemdb ){
50021 flags |= BTREE_MEMORY;
50022 flags &= ~BTREE_SORTER;
50023 }
50024 if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
50025 vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
50026 }
50027 p = sqlite3MallocZero(sizeof(Btree));
@@ -51022,15 +50999,16 @@
51022 for(i=0; i<nCell; i++){
51023 u8 *pCell = findCell(pPage, i);
51024 if( eType==PTRMAP_OVERFLOW1 ){
51025 CellInfo info;
51026 btreeParseCellPtr(pPage, pCell, &info);
51027 if( info.iOverflow ){
51028 if( iFrom==get4byte(&pCell[info.iOverflow]) ){
51029 put4byte(&pCell[info.iOverflow], iTo);
51030 break;
51031 }
 
51032 }
51033 }else{
51034 if( get4byte(pCell)==iFrom ){
51035 put4byte(pCell, iTo);
51036 break;
@@ -53458,10 +53436,13 @@
53458 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
53459 btreeParseCellPtr(pPage, pCell, &info);
53460 if( info.iOverflow==0 ){
53461 return SQLITE_OK; /* No overflow pages. Return without doing anything */
53462 }
 
 
 
53463 ovflPgno = get4byte(&pCell[info.iOverflow]);
53464 assert( pBt->usableSize > 4 );
53465 ovflPageSize = pBt->usableSize - 4;
53466 nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
53467 assert( ovflPgno==0 || nOvfl>0 );
@@ -55560,20 +55541,13 @@
55560 releasePage(pPage);
55561 }
55562 return rc;
55563 }
55564 SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
55565 BtShared *pBt = p->pBt;
55566 int rc;
55567 sqlite3BtreeEnter(p);
55568 if( (pBt->openFlags&BTREE_SINGLE) ){
55569 pBt->nPage = 0;
55570 sqlite3PagerTruncateImage(pBt->pPager, 1);
55571 rc = newDatabase(pBt);
55572 }else{
55573 rc = btreeDropTable(p, iTable, piMoved);
55574 }
55575 sqlite3BtreeLeave(p);
55576 return rc;
55577 }
55578
55579
@@ -58758,11 +58732,11 @@
58758 assert( p->nOp - i >= 3 );
58759 assert( pOp[-1].opcode==OP_Integer );
58760 n = pOp[-1].p1;
58761 if( n>nMaxArgs ) nMaxArgs = n;
58762 #endif
58763 }else if( opcode==OP_Next ){
58764 pOp->p4.xAdvance = sqlite3BtreeNext;
58765 pOp->p4type = P4_ADVANCE;
58766 }else if( opcode==OP_Prev ){
58767 pOp->p4.xAdvance = sqlite3BtreePrevious;
58768 pOp->p4type = P4_ADVANCE;
@@ -58995,22 +58969,19 @@
58995 p->pNext = pVdbe->pProgram;
58996 pVdbe->pProgram = p;
58997 }
58998
58999 /*
59000 ** Change N opcodes starting at addr to No-ops.
59001 */
59002 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
59003 if( p->aOp ){
59004 VdbeOp *pOp = &p->aOp[addr];
59005 sqlite3 *db = p->db;
59006 while( N-- ){
59007 freeP4(db, pOp->p4type, pOp->p4.p);
59008 memset(pOp, 0, sizeof(pOp[0]));
59009 pOp->opcode = OP_Noop;
59010 pOp++;
59011 }
59012 }
59013 }
59014
59015 /*
59016 ** Change the value of the P4 operand for a specific instruction.
@@ -59162,11 +59133,11 @@
59162 ** check the value of p->nOp-1 before continuing.
59163 */
59164 SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
59165 /* C89 specifies that the constant "dummy" will be initialized to all
59166 ** zeros, which is correct. MSVC generates a warning, nevertheless. */
59167 static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
59168 assert( p->magic==VDBE_MAGIC_INIT );
59169 if( addr<0 ){
59170 #ifdef SQLITE_OMIT_TRACE
59171 if( p->nOp==0 ) return (VdbeOp*)&dummy;
59172 #endif
@@ -61155,61 +61126,74 @@
61155 }
61156 }
61157 return 0;
61158 }
61159
61160
61161 /*
61162 ** Given the nKey-byte encoding of a record in pKey[], parse the
61163 ** record into a UnpackedRecord structure. Return a pointer to
61164 ** that structure.
61165 **
61166 ** The calling function might provide szSpace bytes of memory
61167 ** space at pSpace. This space can be used to hold the returned
61168 ** VDbeParsedRecord structure if it is large enough. If it is
61169 ** not big enough, space is obtained from sqlite3_malloc().
61170 **
61171 ** The returned structure should be closed by a call to
61172 ** sqlite3VdbeDeleteUnpackedRecord().
61173 */
61174 SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
61175 KeyInfo *pKeyInfo, /* Information about the record format */
61176 int nKey, /* Size of the binary record */
61177 const void *pKey, /* The binary record */
61178 char *pSpace, /* Unaligned space available to hold the object */
61179 int szSpace /* Size of pSpace[] in bytes */
61180 ){
61181 const unsigned char *aKey = (const unsigned char *)pKey;
61182 UnpackedRecord *p; /* The unpacked record that we will return */
61183 int nByte; /* Memory space needed to hold p, in bytes */
61184 int d;
61185 u32 idx;
61186 u16 u; /* Unsigned loop counter */
61187 u32 szHdr;
61188 Mem *pMem;
61189 int nOff; /* Increase pSpace by this much to 8-byte align it */
61190
61191 /*
61192 ** We want to shift the pointer pSpace up such that it is 8-byte aligned.
61193 ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
61194 ** it by. If pSpace is already 8-byte aligned, nOff should be zero.
61195 */
61196 nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
61197 pSpace += nOff;
61198 szSpace -= nOff;
61199 nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
61200 if( nByte>szSpace ){
61201 p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
61202 if( p==0 ) return 0;
61203 p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
61204 }else{
61205 p = (UnpackedRecord*)pSpace;
61206 p->flags = UNPACKED_NEED_DESTROY;
61207 }
 
 
61208 p->pKeyInfo = pKeyInfo;
61209 p->nField = pKeyInfo->nField + 1;
61210 p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61211 assert( EIGHT_BYTE_ALIGNMENT(pMem) );
61212 idx = getVarint32(aKey, szHdr);
61213 d = szHdr;
61214 u = 0;
61215 while( idx<szHdr && u<p->nField && d<=nKey ){
@@ -61224,35 +61208,10 @@
61224 pMem++;
61225 u++;
61226 }
61227 assert( u<=pKeyInfo->nField + 1 );
61228 p->nField = u;
61229 return (void*)p;
61230 }
61231
61232 /*
61233 ** This routine destroys a UnpackedRecord object.
61234 */
61235 SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
61236 #ifdef SQLITE_DEBUG
61237 int i;
61238 Mem *pMem;
61239
61240 assert( p!=0 );
61241 assert( p->flags & UNPACKED_NEED_DESTROY );
61242 for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
61243 /* The unpacked record is always constructed by the
61244 ** sqlite3VdbeUnpackRecord() function above, which makes all
61245 ** strings and blobs static. And none of the elements are
61246 ** ever transformed, so there is never anything to delete.
61247 */
61248 if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem);
61249 }
61250 #endif
61251 if( p->flags & UNPACKED_NEED_FREE ){
61252 sqlite3DbFree(p->pKeyInfo->db, p);
61253 }
61254 }
61255
61256 /*
61257 ** This function compares the two table rows or index records
61258 ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
@@ -63871,55 +63830,59 @@
63871 Db *pDb;
63872 } aw;
63873 struct OP_OpenEphemeral_stack_vars {
63874 VdbeCursor *pCx;
63875 } ax;
63876 struct OP_OpenPseudo_stack_vars {
63877 VdbeCursor *pCx;
63878 } ay;
 
 
 
63879 struct OP_SeekGt_stack_vars {
63880 int res;
63881 int oc;
63882 VdbeCursor *pC;
63883 UnpackedRecord r;
63884 int nField;
63885 i64 iKey; /* The rowid we are to seek to */
63886 } az;
63887 struct OP_Seek_stack_vars {
63888 VdbeCursor *pC;
63889 } ba;
63890 struct OP_Found_stack_vars {
63891 int alreadyExists;
63892 VdbeCursor *pC;
63893 int res;
 
63894 UnpackedRecord *pIdxKey;
63895 UnpackedRecord r;
63896 char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
63897 } bb;
63898 struct OP_IsUnique_stack_vars {
63899 u16 ii;
63900 VdbeCursor *pCx;
63901 BtCursor *pCrsr;
63902 u16 nField;
63903 Mem *aMx;
63904 UnpackedRecord r; /* B-Tree index search key */
63905 i64 R; /* Rowid stored in register P3 */
63906 } bc;
63907 struct OP_NotExists_stack_vars {
63908 VdbeCursor *pC;
63909 BtCursor *pCrsr;
63910 int res;
63911 u64 iKey;
63912 } bd;
63913 struct OP_NewRowid_stack_vars {
63914 i64 v; /* The new rowid */
63915 VdbeCursor *pC; /* Cursor of table to get the new rowid */
63916 int res; /* Result of an sqlite3BtreeLast() */
63917 int cnt; /* Counter to limit the number of searches */
63918 Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
63919 VdbeFrame *pFrame; /* Root frame of VDBE */
63920 } be;
63921 struct OP_InsertInt_stack_vars {
63922 Mem *pData; /* MEM cell holding data for the record to be inserted */
63923 Mem *pKey; /* MEM cell holding key for the record */
63924 i64 iKey; /* The integer ROWID or key for the record to be inserted */
63925 VdbeCursor *pC; /* Cursor to table into which insert is written */
@@ -63926,154 +63889,161 @@
63926 int nZero; /* Number of zero-bytes to append */
63927 int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
63928 const char *zDb; /* database name - used by the update hook */
63929 const char *zTbl; /* Table name - used by the opdate hook */
63930 int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
63931 } bf;
63932 struct OP_Delete_stack_vars {
63933 i64 iKey;
63934 VdbeCursor *pC;
63935 } bg;
 
 
 
 
 
 
 
63936 struct OP_RowData_stack_vars {
63937 VdbeCursor *pC;
63938 BtCursor *pCrsr;
63939 u32 n;
63940 i64 n64;
63941 } bh;
63942 struct OP_Rowid_stack_vars {
63943 VdbeCursor *pC;
63944 i64 v;
63945 sqlite3_vtab *pVtab;
63946 const sqlite3_module *pModule;
63947 } bi;
63948 struct OP_NullRow_stack_vars {
63949 VdbeCursor *pC;
63950 } bj;
63951 struct OP_Last_stack_vars {
63952 VdbeCursor *pC;
63953 BtCursor *pCrsr;
63954 int res;
63955 } bk;
63956 struct OP_Rewind_stack_vars {
63957 VdbeCursor *pC;
63958 BtCursor *pCrsr;
63959 int res;
63960 } bl;
63961 struct OP_Next_stack_vars {
63962 VdbeCursor *pC;
63963 int res;
63964 } bm;
63965 struct OP_IdxInsert_stack_vars {
63966 VdbeCursor *pC;
63967 BtCursor *pCrsr;
63968 int nKey;
63969 const char *zKey;
63970 } bn;
63971 struct OP_IdxDelete_stack_vars {
63972 VdbeCursor *pC;
63973 BtCursor *pCrsr;
63974 int res;
63975 UnpackedRecord r;
63976 } bo;
63977 struct OP_IdxRowid_stack_vars {
63978 BtCursor *pCrsr;
63979 VdbeCursor *pC;
63980 i64 rowid;
63981 } bp;
63982 struct OP_IdxGE_stack_vars {
63983 VdbeCursor *pC;
63984 int res;
63985 UnpackedRecord r;
63986 } bq;
63987 struct OP_Destroy_stack_vars {
63988 int iMoved;
63989 int iCnt;
63990 Vdbe *pVdbe;
63991 int iDb;
63992 } br;
63993 struct OP_Clear_stack_vars {
63994 int nChange;
63995 } bs;
63996 struct OP_CreateTable_stack_vars {
63997 int pgno;
63998 int flags;
63999 Db *pDb;
64000 } bt;
64001 struct OP_ParseSchema_stack_vars {
64002 int iDb;
64003 const char *zMaster;
64004 char *zSql;
64005 InitData initData;
64006 } bu;
64007 struct OP_IntegrityCk_stack_vars {
64008 int nRoot; /* Number of tables to check. (Number of root pages.) */
64009 int *aRoot; /* Array of rootpage numbers for tables to be checked */
64010 int j; /* Loop counter */
64011 int nErr; /* Number of errors reported */
64012 char *z; /* Text of the error report */
64013 Mem *pnErr; /* Register keeping track of errors remaining */
64014 } bv;
64015 struct OP_RowSetRead_stack_vars {
64016 i64 val;
64017 } bw;
64018 struct OP_RowSetTest_stack_vars {
64019 int iSet;
64020 int exists;
64021 } bx;
64022 struct OP_Program_stack_vars {
64023 int nMem; /* Number of memory registers for sub-program */
64024 int nByte; /* Bytes of runtime space required for sub-program */
64025 Mem *pRt; /* Register to allocate runtime space */
64026 Mem *pMem; /* Used to iterate through memory cells */
64027 Mem *pEnd; /* Last memory cell in new array */
64028 VdbeFrame *pFrame; /* New vdbe frame to execute in */
64029 SubProgram *pProgram; /* Sub-program to execute */
64030 void *t; /* Token identifying trigger */
64031 } by;
64032 struct OP_Param_stack_vars {
64033 VdbeFrame *pFrame;
64034 Mem *pIn;
64035 } bz;
64036 struct OP_MemMax_stack_vars {
64037 Mem *pIn1;
64038 VdbeFrame *pFrame;
64039 } ca;
64040 struct OP_AggStep_stack_vars {
64041 int n;
64042 int i;
64043 Mem *pMem;
64044 Mem *pRec;
64045 sqlite3_context ctx;
64046 sqlite3_value **apVal;
64047 } cb;
64048 struct OP_AggFinal_stack_vars {
64049 Mem *pMem;
64050 } cc;
64051 struct OP_Checkpoint_stack_vars {
64052 int i; /* Loop counter */
64053 int aRes[3]; /* Results */
64054 Mem *pMem; /* Write results here */
64055 } cd;
64056 struct OP_JournalMode_stack_vars {
64057 Btree *pBt; /* Btree to change journal mode of */
64058 Pager *pPager; /* Pager associated with pBt */
64059 int eNew; /* New journal mode */
64060 int eOld; /* The old journal mode */
64061 const char *zFilename; /* Name of database file for pPager */
64062 } ce;
64063 struct OP_IncrVacuum_stack_vars {
64064 Btree *pBt;
64065 } cf;
64066 struct OP_VBegin_stack_vars {
64067 VTable *pVTab;
64068 } cg;
64069 struct OP_VOpen_stack_vars {
64070 VdbeCursor *pCur;
64071 sqlite3_vtab_cursor *pVtabCursor;
64072 sqlite3_vtab *pVtab;
64073 sqlite3_module *pModule;
64074 } ch;
64075 struct OP_VFilter_stack_vars {
64076 int nArg;
64077 int iQuery;
64078 const sqlite3_module *pModule;
64079 Mem *pQuery;
@@ -64082,40 +64052,40 @@
64082 sqlite3_vtab *pVtab;
64083 VdbeCursor *pCur;
64084 int res;
64085 int i;
64086 Mem **apArg;
64087 } ci;
64088 struct OP_VColumn_stack_vars {
64089 sqlite3_vtab *pVtab;
64090 const sqlite3_module *pModule;
64091 Mem *pDest;
64092 sqlite3_context sContext;
64093 } cj;
64094 struct OP_VNext_stack_vars {
64095 sqlite3_vtab *pVtab;
64096 const sqlite3_module *pModule;
64097 int res;
64098 VdbeCursor *pCur;
64099 } ck;
64100 struct OP_VRename_stack_vars {
64101 sqlite3_vtab *pVtab;
64102 Mem *pName;
64103 } cl;
64104 struct OP_VUpdate_stack_vars {
64105 sqlite3_vtab *pVtab;
64106 sqlite3_module *pModule;
64107 int nArg;
64108 int i;
64109 sqlite_int64 rowid;
64110 Mem **apArg;
64111 Mem *pX;
64112 } cm;
64113 struct OP_Trace_stack_vars {
64114 char *zTrace;
64115 char *z;
64116 } cn;
64117 } u;
64118 /* End automatically generated code
64119 ********************************************************************/
64120
64121 assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
@@ -65581,10 +65551,20 @@
65581 sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
65582 }
65583 break;
65584 }
65585
 
 
 
 
 
 
 
 
 
 
65586 /* Opcode: If P1 P2 P3 * *
65587 **
65588 ** Jump to P2 if the value in register P1 is true. The value
65589 ** is considered true if it is numeric and non-zero. If the value
65590 ** in P1 is NULL then take the jump if P3 is true.
@@ -65593,10 +65573,11 @@
65593 **
65594 ** Jump to P2 if the value in register P1 is False. The value
65595 ** is considered true if it has a numeric value of zero. If the value
65596 ** in P1 is NULL then take the jump if P3 is true.
65597 */
 
65598 case OP_If: /* jump, in1 */
65599 case OP_IfNot: { /* jump, in1 */
65600 #if 0 /* local variables moved into u.al */
65601 int c;
65602 #endif /* local variables moved into u.al */
@@ -65611,10 +65592,16 @@
65611 #endif
65612 if( pOp->opcode==OP_IfNot ) u.al.c = !u.al.c;
65613 }
65614 if( u.al.c ){
65615 pc = pOp->p2-1;
 
 
 
 
 
 
65616 }
65617 break;
65618 }
65619
65620 /* Opcode: IsNull P1 P2 * * *
@@ -66746,17 +66733,10 @@
66746 ** This opcode works the same as OP_OpenEphemeral. It has a
66747 ** different name to distinguish its use. Tables created using
66748 ** by this opcode will be used for automatically created transient
66749 ** indices in joins.
66750 */
66751 /* Opcode: OpenSorter P1 P2 * P4 *
66752 **
66753 ** This opcode works like OP_OpenEphemeral except that it opens
66754 ** a transient index that is specifically designed to sort large
66755 ** tables using an external merge-sort algorithm.
66756 */
66757 case OP_OpenSorter:
66758 case OP_OpenAutoindex:
66759 case OP_OpenEphemeral: {
66760 #if 0 /* local variables moved into u.ax */
66761 VdbeCursor *pCx;
66762 #endif /* local variables moved into u.ax */
@@ -66766,11 +66746,10 @@
66766 SQLITE_OPEN_EXCLUSIVE |
66767 SQLITE_OPEN_DELETEONCLOSE |
66768 SQLITE_OPEN_TRANSIENT_DB;
66769
66770 assert( pOp->p1>=0 );
66771 assert( (pOp->opcode==OP_OpenSorter)==((pOp->p5 & BTREE_SORTER)!=0) );
66772 u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
66773 if( u.ax.pCx==0 ) goto no_mem;
66774 u.ax.pCx->nullRow = 1;
66775 rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
66776 BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
@@ -66800,14 +66779,33 @@
66800 u.ax.pCx->isTable = 1;
66801 }
66802 }
66803 u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
66804 u.ax.pCx->isIndex = !u.ax.pCx->isTable;
 
 
 
 
 
 
 
 
 
 
 
 
 
66805 #ifndef SQLITE_OMIT_MERGE_SORT
66806 if( rc==SQLITE_OK && pOp->opcode==OP_OpenSorter ){
66807 rc = sqlite3VdbeSorterInit(db, u.ax.pCx);
66808 }
 
 
 
 
 
 
66809 #endif
66810 break;
66811 }
66812
66813 /* Opcode: OpenPseudo P1 P2 P3 * *
@@ -66824,21 +66822,21 @@
66824 **
66825 ** P3 is the number of fields in the records that will be stored by
66826 ** the pseudo-table.
66827 */
66828 case OP_OpenPseudo: {
66829 #if 0 /* local variables moved into u.ay */
66830 VdbeCursor *pCx;
66831 #endif /* local variables moved into u.ay */
66832
66833 assert( pOp->p1>=0 );
66834 u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
66835 if( u.ay.pCx==0 ) goto no_mem;
66836 u.ay.pCx->nullRow = 1;
66837 u.ay.pCx->pseudoTableReg = pOp->p2;
66838 u.ay.pCx->isTable = 1;
66839 u.ay.pCx->isIndex = 0;
66840 break;
66841 }
66842
66843 /* Opcode: Close P1 * * * *
66844 **
@@ -66906,39 +66904,39 @@
66906 */
66907 case OP_SeekLt: /* jump, in3 */
66908 case OP_SeekLe: /* jump, in3 */
66909 case OP_SeekGe: /* jump, in3 */
66910 case OP_SeekGt: { /* jump, in3 */
66911 #if 0 /* local variables moved into u.az */
66912 int res;
66913 int oc;
66914 VdbeCursor *pC;
66915 UnpackedRecord r;
66916 int nField;
66917 i64 iKey; /* The rowid we are to seek to */
66918 #endif /* local variables moved into u.az */
66919
66920 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
66921 assert( pOp->p2!=0 );
66922 u.az.pC = p->apCsr[pOp->p1];
66923 assert( u.az.pC!=0 );
66924 assert( u.az.pC->pseudoTableReg==0 );
66925 assert( OP_SeekLe == OP_SeekLt+1 );
66926 assert( OP_SeekGe == OP_SeekLt+2 );
66927 assert( OP_SeekGt == OP_SeekLt+3 );
66928 assert( u.az.pC->isOrdered );
66929 if( ALWAYS(u.az.pC->pCursor!=0) ){
66930 u.az.oc = pOp->opcode;
66931 u.az.pC->nullRow = 0;
66932 if( u.az.pC->isTable ){
66933 /* The input value in P3 might be of any type: integer, real, string,
66934 ** blob, or NULL. But it needs to be an integer before we can do
66935 ** the seek, so covert it. */
66936 pIn3 = &aMem[pOp->p3];
66937 applyNumericAffinity(pIn3);
66938 u.az.iKey = sqlite3VdbeIntValue(pIn3);
66939 u.az.pC->rowidIsValid = 0;
66940
66941 /* If the P3 value could not be converted into an integer without
66942 ** loss of information, then special processing is required... */
66943 if( (pIn3->flags & MEM_Int)==0 ){
66944 if( (pIn3->flags & MEM_Real)==0 ){
@@ -66949,105 +66947,105 @@
66949 }
66950 /* If we reach this point, then the P3 value must be a floating
66951 ** point number. */
66952 assert( (pIn3->flags & MEM_Real)!=0 );
66953
66954 if( u.az.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.az.iKey || pIn3->r>0) ){
66955 /* The P3 value is too large in magnitude to be expressed as an
66956 ** integer. */
66957 u.az.res = 1;
66958 if( pIn3->r<0 ){
66959 if( u.az.oc>=OP_SeekGe ){ assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
66960 rc = sqlite3BtreeFirst(u.az.pC->pCursor, &u.az.res);
66961 if( rc!=SQLITE_OK ) goto abort_due_to_error;
66962 }
66963 }else{
66964 if( u.az.oc<=OP_SeekLe ){ assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
66965 rc = sqlite3BtreeLast(u.az.pC->pCursor, &u.az.res);
66966 if( rc!=SQLITE_OK ) goto abort_due_to_error;
66967 }
66968 }
66969 if( u.az.res ){
66970 pc = pOp->p2 - 1;
66971 }
66972 break;
66973 }else if( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekGe ){
66974 /* Use the ceiling() function to convert real->int */
66975 if( pIn3->r > (double)u.az.iKey ) u.az.iKey++;
66976 }else{
66977 /* Use the floor() function to convert real->int */
66978 assert( u.az.oc==OP_SeekLe || u.az.oc==OP_SeekGt );
66979 if( pIn3->r < (double)u.az.iKey ) u.az.iKey--;
66980 }
66981 }
66982 rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, 0, (u64)u.az.iKey, 0, &u.az.res);
66983 if( rc!=SQLITE_OK ){
66984 goto abort_due_to_error;
66985 }
66986 if( u.az.res==0 ){
66987 u.az.pC->rowidIsValid = 1;
66988 u.az.pC->lastRowid = u.az.iKey;
66989 }
66990 }else{
66991 u.az.nField = pOp->p4.i;
66992 assert( pOp->p4type==P4_INT32 );
66993 assert( u.az.nField>0 );
66994 u.az.r.pKeyInfo = u.az.pC->pKeyInfo;
66995 u.az.r.nField = (u16)u.az.nField;
66996
66997 /* The next line of code computes as follows, only faster:
66998 ** if( u.az.oc==OP_SeekGt || u.az.oc==OP_SeekLe ){
66999 ** u.az.r.flags = UNPACKED_INCRKEY;
67000 ** }else{
67001 ** u.az.r.flags = 0;
67002 ** }
67003 */
67004 u.az.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt)));
67005 assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY );
67006 assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY );
67007 assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 );
67008 assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 );
67009
67010 u.az.r.aMem = &aMem[pOp->p3];
67011 #ifdef SQLITE_DEBUG
67012 { int i; for(i=0; i<u.az.r.nField; i++) assert( memIsValid(&u.az.r.aMem[i]) ); }
67013 #endif
67014 ExpandBlob(u.az.r.aMem);
67015 rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, &u.az.r, 0, 0, &u.az.res);
67016 if( rc!=SQLITE_OK ){
67017 goto abort_due_to_error;
67018 }
67019 u.az.pC->rowidIsValid = 0;
67020 }
67021 u.az.pC->deferredMoveto = 0;
67022 u.az.pC->cacheStatus = CACHE_STALE;
67023 #ifdef SQLITE_TEST
67024 sqlite3_search_count++;
67025 #endif
67026 if( u.az.oc>=OP_SeekGe ){ assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
67027 if( u.az.res<0 || (u.az.res==0 && u.az.oc==OP_SeekGt) ){
67028 rc = sqlite3BtreeNext(u.az.pC->pCursor, &u.az.res);
67029 if( rc!=SQLITE_OK ) goto abort_due_to_error;
67030 u.az.pC->rowidIsValid = 0;
67031 }else{
67032 u.az.res = 0;
67033 }
67034 }else{
67035 assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
67036 if( u.az.res>0 || (u.az.res==0 && u.az.oc==OP_SeekLt) ){
67037 rc = sqlite3BtreePrevious(u.az.pC->pCursor, &u.az.res);
67038 if( rc!=SQLITE_OK ) goto abort_due_to_error;
67039 u.az.pC->rowidIsValid = 0;
67040 }else{
67041 /* u.az.res might be negative because the table is empty. Check to
67042 ** see if this is the case.
67043 */
67044 u.az.res = sqlite3BtreeEof(u.az.pC->pCursor);
67045 }
67046 }
67047 assert( pOp->p2>0 );
67048 if( u.az.res ){
67049 pc = pOp->p2 - 1;
67050 }
67051 }else{
67052 /* This happens when attempting to open the sqlite3_master table
67053 ** for read access returns SQLITE_EMPTY. In this case always
@@ -67066,24 +67064,24 @@
67066 ** This is actually a deferred seek. Nothing actually happens until
67067 ** the cursor is used to read a record. That way, if no reads
67068 ** occur, no unnecessary I/O happens.
67069 */
67070 case OP_Seek: { /* in2 */
67071 #if 0 /* local variables moved into u.ba */
67072 VdbeCursor *pC;
67073 #endif /* local variables moved into u.ba */
67074
67075 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67076 u.ba.pC = p->apCsr[pOp->p1];
67077 assert( u.ba.pC!=0 );
67078 if( ALWAYS(u.ba.pC->pCursor!=0) ){
67079 assert( u.ba.pC->isTable );
67080 u.ba.pC->nullRow = 0;
67081 pIn2 = &aMem[pOp->p2];
67082 u.ba.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
67083 u.ba.pC->rowidIsValid = 0;
67084 u.ba.pC->deferredMoveto = 1;
67085 }
67086 break;
67087 }
67088
67089
@@ -67111,66 +67109,67 @@
67111 **
67112 ** See also: Found, NotExists, IsUnique
67113 */
67114 case OP_NotFound: /* jump, in3 */
67115 case OP_Found: { /* jump, in3 */
67116 #if 0 /* local variables moved into u.bb */
67117 int alreadyExists;
67118 VdbeCursor *pC;
67119 int res;
 
67120 UnpackedRecord *pIdxKey;
67121 UnpackedRecord r;
67122 char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
67123 #endif /* local variables moved into u.bb */
67124
67125 #ifdef SQLITE_TEST
67126 sqlite3_found_count++;
67127 #endif
67128
67129 u.bb.alreadyExists = 0;
67130 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67131 assert( pOp->p4type==P4_INT32 );
67132 u.bb.pC = p->apCsr[pOp->p1];
67133 assert( u.bb.pC!=0 );
67134 pIn3 = &aMem[pOp->p3];
67135 if( ALWAYS(u.bb.pC->pCursor!=0) ){
67136
67137 assert( u.bb.pC->isTable==0 );
67138 if( pOp->p4.i>0 ){
67139 u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo;
67140 u.bb.r.nField = (u16)pOp->p4.i;
67141 u.bb.r.aMem = pIn3;
67142 #ifdef SQLITE_DEBUG
67143 { int i; for(i=0; i<u.bb.r.nField; i++) assert( memIsValid(&u.bb.r.aMem[i]) ); }
67144 #endif
67145 u.bb.r.flags = UNPACKED_PREFIX_MATCH;
67146 u.bb.pIdxKey = &u.bb.r;
67147 }else{
 
 
 
 
67148 assert( pIn3->flags & MEM_Blob );
67149 assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
67150 u.bb.pIdxKey = sqlite3VdbeRecordUnpack(u.bb.pC->pKeyInfo, pIn3->n, pIn3->z,
67151 u.bb.aTempRec, sizeof(u.bb.aTempRec));
67152 if( u.bb.pIdxKey==0 ){
67153 goto no_mem;
67154 }
67155 u.bb.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
67156 }
67157 rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, u.bb.pIdxKey, 0, 0, &u.bb.res);
67158 if( pOp->p4.i==0 ){
67159 sqlite3VdbeDeleteUnpackedRecord(u.bb.pIdxKey);
67160 }
67161 if( rc!=SQLITE_OK ){
67162 break;
67163 }
67164 u.bb.alreadyExists = (u.bb.res==0);
67165 u.bb.pC->deferredMoveto = 0;
67166 u.bb.pC->cacheStatus = CACHE_STALE;
67167 }
67168 if( pOp->opcode==OP_Found ){
67169 if( u.bb.alreadyExists ) pc = pOp->p2 - 1;
67170 }else{
67171 if( !u.bb.alreadyExists ) pc = pOp->p2 - 1;
67172 }
67173 break;
67174 }
67175
67176 /* Opcode: IsUnique P1 P2 P3 P4 *
@@ -67198,67 +67197,67 @@
67198 ** instruction.
67199 **
67200 ** See also: NotFound, NotExists, Found
67201 */
67202 case OP_IsUnique: { /* jump, in3 */
67203 #if 0 /* local variables moved into u.bc */
67204 u16 ii;
67205 VdbeCursor *pCx;
67206 BtCursor *pCrsr;
67207 u16 nField;
67208 Mem *aMx;
67209 UnpackedRecord r; /* B-Tree index search key */
67210 i64 R; /* Rowid stored in register P3 */
67211 #endif /* local variables moved into u.bc */
67212
67213 pIn3 = &aMem[pOp->p3];
67214 u.bc.aMx = &aMem[pOp->p4.i];
67215 /* Assert that the values of parameters P1 and P4 are in range. */
67216 assert( pOp->p4type==P4_INT32 );
67217 assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
67218 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67219
67220 /* Find the index cursor. */
67221 u.bc.pCx = p->apCsr[pOp->p1];
67222 assert( u.bc.pCx->deferredMoveto==0 );
67223 u.bc.pCx->seekResult = 0;
67224 u.bc.pCx->cacheStatus = CACHE_STALE;
67225 u.bc.pCrsr = u.bc.pCx->pCursor;
67226
67227 /* If any of the values are NULL, take the jump. */
67228 u.bc.nField = u.bc.pCx->pKeyInfo->nField;
67229 for(u.bc.ii=0; u.bc.ii<u.bc.nField; u.bc.ii++){
67230 if( u.bc.aMx[u.bc.ii].flags & MEM_Null ){
67231 pc = pOp->p2 - 1;
67232 u.bc.pCrsr = 0;
67233 break;
67234 }
67235 }
67236 assert( (u.bc.aMx[u.bc.nField].flags & MEM_Null)==0 );
67237
67238 if( u.bc.pCrsr!=0 ){
67239 /* Populate the index search key. */
67240 u.bc.r.pKeyInfo = u.bc.pCx->pKeyInfo;
67241 u.bc.r.nField = u.bc.nField + 1;
67242 u.bc.r.flags = UNPACKED_PREFIX_SEARCH;
67243 u.bc.r.aMem = u.bc.aMx;
67244 #ifdef SQLITE_DEBUG
67245 { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
67246 #endif
67247
67248 /* Extract the value of u.bc.R from register P3. */
67249 sqlite3VdbeMemIntegerify(pIn3);
67250 u.bc.R = pIn3->u.i;
67251
67252 /* Search the B-Tree index. If no conflicting record is found, jump
67253 ** to P2. Otherwise, copy the rowid of the conflicting record to
67254 ** register P3 and fall through to the next instruction. */
67255 rc = sqlite3BtreeMovetoUnpacked(u.bc.pCrsr, &u.bc.r, 0, 0, &u.bc.pCx->seekResult);
67256 if( (u.bc.r.flags & UNPACKED_PREFIX_SEARCH) || u.bc.r.rowid==u.bc.R ){
67257 pc = pOp->p2 - 1;
67258 }else{
67259 pIn3->u.i = u.bc.r.rowid;
67260 }
67261 }
67262 break;
67263 }
67264
@@ -67275,46 +67274,46 @@
67275 ** P1 is an index.
67276 **
67277 ** See also: Found, NotFound, IsUnique
67278 */
67279 case OP_NotExists: { /* jump, in3 */
67280 #if 0 /* local variables moved into u.bd */
67281 VdbeCursor *pC;
67282 BtCursor *pCrsr;
67283 int res;
67284 u64 iKey;
67285 #endif /* local variables moved into u.bd */
67286
67287 pIn3 = &aMem[pOp->p3];
67288 assert( pIn3->flags & MEM_Int );
67289 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67290 u.bd.pC = p->apCsr[pOp->p1];
67291 assert( u.bd.pC!=0 );
67292 assert( u.bd.pC->isTable );
67293 assert( u.bd.pC->pseudoTableReg==0 );
67294 u.bd.pCrsr = u.bd.pC->pCursor;
67295 if( ALWAYS(u.bd.pCrsr!=0) ){
67296 u.bd.res = 0;
67297 u.bd.iKey = pIn3->u.i;
67298 rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res);
67299 u.bd.pC->lastRowid = pIn3->u.i;
67300 u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0;
67301 u.bd.pC->nullRow = 0;
67302 u.bd.pC->cacheStatus = CACHE_STALE;
67303 u.bd.pC->deferredMoveto = 0;
67304 if( u.bd.res!=0 ){
67305 pc = pOp->p2 - 1;
67306 assert( u.bd.pC->rowidIsValid==0 );
67307 }
67308 u.bd.pC->seekResult = u.bd.res;
67309 }else{
67310 /* This happens when an attempt to open a read cursor on the
67311 ** sqlite_master table returns SQLITE_EMPTY.
67312 */
67313 pc = pOp->p2 - 1;
67314 assert( u.bd.pC->rowidIsValid==0 );
67315 u.bd.pC->seekResult = 0;
67316 }
67317 break;
67318 }
67319
67320 /* Opcode: Sequence P1 P2 * * *
@@ -67345,25 +67344,25 @@
67345 ** an SQLITE_FULL error is generated. The P3 register is updated with the '
67346 ** generated record number. This P3 mechanism is used to help implement the
67347 ** AUTOINCREMENT feature.
67348 */
67349 case OP_NewRowid: { /* out2-prerelease */
67350 #if 0 /* local variables moved into u.be */
67351 i64 v; /* The new rowid */
67352 VdbeCursor *pC; /* Cursor of table to get the new rowid */
67353 int res; /* Result of an sqlite3BtreeLast() */
67354 int cnt; /* Counter to limit the number of searches */
67355 Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
67356 VdbeFrame *pFrame; /* Root frame of VDBE */
67357 #endif /* local variables moved into u.be */
67358
67359 u.be.v = 0;
67360 u.be.res = 0;
67361 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67362 u.be.pC = p->apCsr[pOp->p1];
67363 assert( u.be.pC!=0 );
67364 if( NEVER(u.be.pC->pCursor==0) ){
67365 /* The zero initialization above is all that is needed */
67366 }else{
67367 /* The next rowid or record number (different terms for the same
67368 ** thing) is obtained in a two-step algorithm.
67369 **
@@ -67375,11 +67374,11 @@
67375 ** The second algorithm is to select a rowid at random and see if
67376 ** it already exists in the table. If it does not exist, we have
67377 ** succeeded. If the random rowid does exist, we select a new one
67378 ** and try again, up to 100 times.
67379 */
67380 assert( u.be.pC->isTable );
67381
67382 #ifdef SQLITE_32BIT_ROWID
67383 # define MAX_ROWID 0x7fffffff
67384 #else
67385 /* Some compilers complain about constants of the form 0x7fffffffffffffff.
@@ -67387,101 +67386,101 @@
67387 ** to provide the constant while making all compilers happy.
67388 */
67389 # define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
67390 #endif
67391
67392 if( !u.be.pC->useRandomRowid ){
67393 u.be.v = sqlite3BtreeGetCachedRowid(u.be.pC->pCursor);
67394 if( u.be.v==0 ){
67395 rc = sqlite3BtreeLast(u.be.pC->pCursor, &u.be.res);
67396 if( rc!=SQLITE_OK ){
67397 goto abort_due_to_error;
67398 }
67399 if( u.be.res ){
67400 u.be.v = 1; /* IMP: R-61914-48074 */
67401 }else{
67402 assert( sqlite3BtreeCursorIsValid(u.be.pC->pCursor) );
67403 rc = sqlite3BtreeKeySize(u.be.pC->pCursor, &u.be.v);
67404 assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
67405 if( u.be.v==MAX_ROWID ){
67406 u.be.pC->useRandomRowid = 1;
67407 }else{
67408 u.be.v++; /* IMP: R-29538-34987 */
67409 }
67410 }
67411 }
67412
67413 #ifndef SQLITE_OMIT_AUTOINCREMENT
67414 if( pOp->p3 ){
67415 /* Assert that P3 is a valid memory cell. */
67416 assert( pOp->p3>0 );
67417 if( p->pFrame ){
67418 for(u.be.pFrame=p->pFrame; u.be.pFrame->pParent; u.be.pFrame=u.be.pFrame->pParent);
67419 /* Assert that P3 is a valid memory cell. */
67420 assert( pOp->p3<=u.be.pFrame->nMem );
67421 u.be.pMem = &u.be.pFrame->aMem[pOp->p3];
67422 }else{
67423 /* Assert that P3 is a valid memory cell. */
67424 assert( pOp->p3<=p->nMem );
67425 u.be.pMem = &aMem[pOp->p3];
67426 memAboutToChange(p, u.be.pMem);
67427 }
67428 assert( memIsValid(u.be.pMem) );
67429
67430 REGISTER_TRACE(pOp->p3, u.be.pMem);
67431 sqlite3VdbeMemIntegerify(u.be.pMem);
67432 assert( (u.be.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
67433 if( u.be.pMem->u.i==MAX_ROWID || u.be.pC->useRandomRowid ){
67434 rc = SQLITE_FULL; /* IMP: R-12275-61338 */
67435 goto abort_due_to_error;
67436 }
67437 if( u.be.v<u.be.pMem->u.i+1 ){
67438 u.be.v = u.be.pMem->u.i + 1;
67439 }
67440 u.be.pMem->u.i = u.be.v;
67441 }
67442 #endif
67443
67444 sqlite3BtreeSetCachedRowid(u.be.pC->pCursor, u.be.v<MAX_ROWID ? u.be.v+1 : 0);
67445 }
67446 if( u.be.pC->useRandomRowid ){
67447 /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
67448 ** largest possible integer (9223372036854775807) then the database
67449 ** engine starts picking positive candidate ROWIDs at random until
67450 ** it finds one that is not previously used. */
67451 assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
67452 ** an AUTOINCREMENT table. */
67453 /* on the first attempt, simply do one more than previous */
67454 u.be.v = lastRowid;
67455 u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
67456 u.be.v++; /* ensure non-zero */
67457 u.be.cnt = 0;
67458 while( ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v,
67459 0, &u.be.res))==SQLITE_OK)
67460 && (u.be.res==0)
67461 && (++u.be.cnt<100)){
67462 /* collision - try another random rowid */
67463 sqlite3_randomness(sizeof(u.be.v), &u.be.v);
67464 if( u.be.cnt<5 ){
67465 /* try "small" random rowids for the initial attempts */
67466 u.be.v &= 0xffffff;
67467 }else{
67468 u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
67469 }
67470 u.be.v++; /* ensure non-zero */
67471 }
67472 if( rc==SQLITE_OK && u.be.res==0 ){
67473 rc = SQLITE_FULL; /* IMP: R-38219-53002 */
67474 goto abort_due_to_error;
67475 }
67476 assert( u.be.v>0 ); /* EV: R-40812-03570 */
67477 }
67478 u.be.pC->rowidIsValid = 0;
67479 u.be.pC->deferredMoveto = 0;
67480 u.be.pC->cacheStatus = CACHE_STALE;
67481 }
67482 pOut->u.i = u.be.v;
67483 break;
67484 }
67485
67486 /* Opcode: Insert P1 P2 P3 P4 P5
67487 **
@@ -67527,74 +67526,74 @@
67527 ** This works exactly like OP_Insert except that the key is the
67528 ** integer value P3, not the value of the integer stored in register P3.
67529 */
67530 case OP_Insert:
67531 case OP_InsertInt: {
67532 #if 0 /* local variables moved into u.bf */
67533 Mem *pData; /* MEM cell holding data for the record to be inserted */
67534 Mem *pKey; /* MEM cell holding key for the record */
67535 i64 iKey; /* The integer ROWID or key for the record to be inserted */
67536 VdbeCursor *pC; /* Cursor to table into which insert is written */
67537 int nZero; /* Number of zero-bytes to append */
67538 int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
67539 const char *zDb; /* database name - used by the update hook */
67540 const char *zTbl; /* Table name - used by the opdate hook */
67541 int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
67542 #endif /* local variables moved into u.bf */
67543
67544 u.bf.pData = &aMem[pOp->p2];
67545 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67546 assert( memIsValid(u.bf.pData) );
67547 u.bf.pC = p->apCsr[pOp->p1];
67548 assert( u.bf.pC!=0 );
67549 assert( u.bf.pC->pCursor!=0 );
67550 assert( u.bf.pC->pseudoTableReg==0 );
67551 assert( u.bf.pC->isTable );
67552 REGISTER_TRACE(pOp->p2, u.bf.pData);
67553
67554 if( pOp->opcode==OP_Insert ){
67555 u.bf.pKey = &aMem[pOp->p3];
67556 assert( u.bf.pKey->flags & MEM_Int );
67557 assert( memIsValid(u.bf.pKey) );
67558 REGISTER_TRACE(pOp->p3, u.bf.pKey);
67559 u.bf.iKey = u.bf.pKey->u.i;
67560 }else{
67561 assert( pOp->opcode==OP_InsertInt );
67562 u.bf.iKey = pOp->p3;
67563 }
67564
67565 if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
67566 if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bf.iKey;
67567 if( u.bf.pData->flags & MEM_Null ){
67568 u.bf.pData->z = 0;
67569 u.bf.pData->n = 0;
67570 }else{
67571 assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) );
67572 }
67573 u.bf.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bf.pC->seekResult : 0);
67574 if( u.bf.pData->flags & MEM_Zero ){
67575 u.bf.nZero = u.bf.pData->u.nZero;
67576 }else{
67577 u.bf.nZero = 0;
67578 }
67579 sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, 0);
67580 rc = sqlite3BtreeInsert(u.bf.pC->pCursor, 0, u.bf.iKey,
67581 u.bf.pData->z, u.bf.pData->n, u.bf.nZero,
67582 pOp->p5 & OPFLAG_APPEND, u.bf.seekResult
67583 );
67584 u.bf.pC->rowidIsValid = 0;
67585 u.bf.pC->deferredMoveto = 0;
67586 u.bf.pC->cacheStatus = CACHE_STALE;
67587
67588 /* Invoke the update-hook if required. */
67589 if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
67590 u.bf.zDb = db->aDb[u.bf.pC->iDb].zName;
67591 u.bf.zTbl = pOp->p4.z;
67592 u.bf.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
67593 assert( u.bf.pC->isTable );
67594 db->xUpdateCallback(db->pUpdateArg, u.bf.op, u.bf.zDb, u.bf.zTbl, u.bf.iKey);
67595 assert( u.bf.pC->iDb>=0 );
67596 }
67597 break;
67598 }
67599
67600 /* Opcode: Delete P1 P2 * P4 *
@@ -67616,51 +67615,51 @@
67616 ** pointing to. The update hook will be invoked, if it exists.
67617 ** If P4 is not NULL then the P1 cursor must have been positioned
67618 ** using OP_NotFound prior to invoking this opcode.
67619 */
67620 case OP_Delete: {
67621 #if 0 /* local variables moved into u.bg */
67622 i64 iKey;
67623 VdbeCursor *pC;
67624 #endif /* local variables moved into u.bg */
67625
67626 u.bg.iKey = 0;
67627 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67628 u.bg.pC = p->apCsr[pOp->p1];
67629 assert( u.bg.pC!=0 );
67630 assert( u.bg.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
67631
67632 /* If the update-hook will be invoked, set u.bg.iKey to the rowid of the
67633 ** row being deleted.
67634 */
67635 if( db->xUpdateCallback && pOp->p4.z ){
67636 assert( u.bg.pC->isTable );
67637 assert( u.bg.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
67638 u.bg.iKey = u.bg.pC->lastRowid;
67639 }
67640
67641 /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
67642 ** OP_Column on the same table without any intervening operations that
67643 ** might move or invalidate the cursor. Hence cursor u.bg.pC is always pointing
67644 ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
67645 ** below is always a no-op and cannot fail. We will run it anyhow, though,
67646 ** to guard against future changes to the code generator.
67647 **/
67648 assert( u.bg.pC->deferredMoveto==0 );
67649 rc = sqlite3VdbeCursorMoveto(u.bg.pC);
67650 if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
67651
67652 sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
67653 rc = sqlite3BtreeDelete(u.bg.pC->pCursor);
67654 u.bg.pC->cacheStatus = CACHE_STALE;
67655
67656 /* Invoke the update-hook if required. */
67657 if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
67658 const char *zDb = db->aDb[u.bg.pC->iDb].zName;
67659 const char *zTbl = pOp->p4.z;
67660 db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bg.iKey);
67661 assert( u.bg.pC->iDb>=0 );
67662 }
67663 if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
67664 break;
67665 }
67666 /* Opcode: ResetCount * * * * *
@@ -67673,10 +67672,53 @@
67673 case OP_ResetCount: {
67674 sqlite3VdbeSetChanges(db, p->nChange);
67675 p->nChange = 0;
67676 break;
67677 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67678
67679 /* Opcode: RowData P1 P2 * * *
67680 **
67681 ** Write into register P2 the complete row data for cursor P1.
67682 ** There is no interpretation of the data.
@@ -67696,72 +67738,67 @@
67696 ** If the P1 cursor must be pointing to a valid row (not a NULL row)
67697 ** of a real table, not a pseudo-table.
67698 */
67699 case OP_RowKey:
67700 case OP_RowData: {
67701 #if 0 /* local variables moved into u.bh */
67702 VdbeCursor *pC;
67703 BtCursor *pCrsr;
67704 u32 n;
67705 i64 n64;
67706 #endif /* local variables moved into u.bh */
67707
67708 pOut = &aMem[pOp->p2];
67709 memAboutToChange(p, pOut);
67710
67711 /* Note that RowKey and RowData are really exactly the same instruction */
67712 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67713 u.bh.pC = p->apCsr[pOp->p1];
67714 assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey );
67715 assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData );
67716 assert( u.bh.pC!=0 );
67717 assert( u.bh.pC->nullRow==0 );
67718 assert( u.bh.pC->pseudoTableReg==0 );
67719
67720 if( isSorter(u.bh.pC) ){
67721 assert( pOp->opcode==OP_RowKey );
67722 rc = sqlite3VdbeSorterRowkey(u.bh.pC, pOut);
67723 break;
67724 }
67725
67726 assert( u.bh.pC->pCursor!=0 );
67727 u.bh.pCrsr = u.bh.pC->pCursor;
67728 assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) );
67729
67730 /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
67731 ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
67732 ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always
67733 ** a no-op and can never fail. But we leave it in place as a safety.
67734 */
67735 assert( u.bh.pC->deferredMoveto==0 );
67736 rc = sqlite3VdbeCursorMoveto(u.bh.pC);
67737 if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
67738
67739 if( u.bh.pC->isIndex ){
67740 assert( !u.bh.pC->isTable );
67741 rc = sqlite3BtreeKeySize(u.bh.pCrsr, &u.bh.n64);
67742 assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
67743 if( u.bh.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
67744 goto too_big;
67745 }
67746 u.bh.n = (u32)u.bh.n64;
67747 }else{
67748 rc = sqlite3BtreeDataSize(u.bh.pCrsr, &u.bh.n);
67749 assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
67750 if( u.bh.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
67751 goto too_big;
67752 }
67753 }
67754 if( sqlite3VdbeMemGrow(pOut, u.bh.n, 0) ){
67755 goto no_mem;
67756 }
67757 pOut->n = u.bh.n;
67758 MemSetTypeFlag(pOut, MEM_Blob);
67759 if( u.bh.pC->isIndex ){
67760 rc = sqlite3BtreeKey(u.bh.pCrsr, 0, u.bh.n, pOut->z);
67761 }else{
67762 rc = sqlite3BtreeData(u.bh.pCrsr, 0, u.bh.n, pOut->z);
67763 }
67764 pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
67765 UPDATE_MAX_BLOBSIZE(pOut);
67766 break;
67767 }
@@ -67774,46 +67811,46 @@
67774 ** P1 can be either an ordinary table or a virtual table. There used to
67775 ** be a separate OP_VRowid opcode for use with virtual tables, but this
67776 ** one opcode now works for both table types.
67777 */
67778 case OP_Rowid: { /* out2-prerelease */
67779 #if 0 /* local variables moved into u.bi */
67780 VdbeCursor *pC;
67781 i64 v;
67782 sqlite3_vtab *pVtab;
67783 const sqlite3_module *pModule;
67784 #endif /* local variables moved into u.bi */
67785
67786 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67787 u.bi.pC = p->apCsr[pOp->p1];
67788 assert( u.bi.pC!=0 );
67789 assert( u.bi.pC->pseudoTableReg==0 );
67790 if( u.bi.pC->nullRow ){
67791 pOut->flags = MEM_Null;
67792 break;
67793 }else if( u.bi.pC->deferredMoveto ){
67794 u.bi.v = u.bi.pC->movetoTarget;
67795 #ifndef SQLITE_OMIT_VIRTUALTABLE
67796 }else if( u.bi.pC->pVtabCursor ){
67797 u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab;
67798 u.bi.pModule = u.bi.pVtab->pModule;
67799 assert( u.bi.pModule->xRowid );
67800 rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v);
67801 importVtabErrMsg(p, u.bi.pVtab);
67802 #endif /* SQLITE_OMIT_VIRTUALTABLE */
67803 }else{
67804 assert( u.bi.pC->pCursor!=0 );
67805 rc = sqlite3VdbeCursorMoveto(u.bi.pC);
67806 if( rc ) goto abort_due_to_error;
67807 if( u.bi.pC->rowidIsValid ){
67808 u.bi.v = u.bi.pC->lastRowid;
67809 }else{
67810 rc = sqlite3BtreeKeySize(u.bi.pC->pCursor, &u.bi.v);
67811 assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */
67812 }
67813 }
67814 pOut->u.i = u.bi.v;
67815 break;
67816 }
67817
67818 /* Opcode: NullRow P1 * * * *
67819 **
@@ -67820,22 +67857,22 @@
67820 ** Move the cursor P1 to a null row. Any OP_Column operations
67821 ** that occur while the cursor is on the null row will always
67822 ** write a NULL.
67823 */
67824 case OP_NullRow: {
67825 #if 0 /* local variables moved into u.bj */
67826 VdbeCursor *pC;
67827 #endif /* local variables moved into u.bj */
67828
67829 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67830 u.bj.pC = p->apCsr[pOp->p1];
67831 assert( u.bj.pC!=0 );
67832 u.bj.pC->nullRow = 1;
67833 u.bj.pC->rowidIsValid = 0;
67834 assert( u.bj.pC->pCursor || u.bj.pC->pVtabCursor );
67835 if( u.bj.pC->pCursor ){
67836 sqlite3BtreeClearCursor(u.bj.pC->pCursor);
67837 }
67838 break;
67839 }
67840
67841 /* Opcode: Last P1 P2 * * *
@@ -67845,30 +67882,30 @@
67845 ** If the table or index is empty and P2>0, then jump immediately to P2.
67846 ** If P2 is 0 or if the table or index is not empty, fall through
67847 ** to the following instruction.
67848 */
67849 case OP_Last: { /* jump */
67850 #if 0 /* local variables moved into u.bk */
67851 VdbeCursor *pC;
67852 BtCursor *pCrsr;
67853 int res;
67854 #endif /* local variables moved into u.bk */
67855
67856 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67857 u.bk.pC = p->apCsr[pOp->p1];
67858 assert( u.bk.pC!=0 );
67859 u.bk.pCrsr = u.bk.pC->pCursor;
67860 if( NEVER(u.bk.pCrsr==0) ){
67861 u.bk.res = 1;
67862 }else{
67863 rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res);
67864 }
67865 u.bk.pC->nullRow = (u8)u.bk.res;
67866 u.bk.pC->deferredMoveto = 0;
67867 u.bk.pC->rowidIsValid = 0;
67868 u.bk.pC->cacheStatus = CACHE_STALE;
67869 if( pOp->p2>0 && u.bk.res ){
67870 pc = pOp->p2 - 1;
67871 }
67872 break;
67873 }
67874
@@ -67883,10 +67920,14 @@
67883 ** end. We use the OP_Sort opcode instead of OP_Rewind to do the
67884 ** rewinding so that the global variable will be incremented and
67885 ** regression tests can determine whether or not the optimizer is
67886 ** correctly optimizing out sorts.
67887 */
 
 
 
 
67888 case OP_Sort: { /* jump */
67889 #ifdef SQLITE_TEST
67890 sqlite3_sort_count++;
67891 sqlite3_search_count--;
67892 #endif
@@ -67900,34 +67941,35 @@
67900 ** If the table or index is empty and P2>0, then jump immediately to P2.
67901 ** If P2 is 0 or if the table or index is not empty, fall through
67902 ** to the following instruction.
67903 */
67904 case OP_Rewind: { /* jump */
67905 #if 0 /* local variables moved into u.bl */
67906 VdbeCursor *pC;
67907 BtCursor *pCrsr;
67908 int res;
67909 #endif /* local variables moved into u.bl */
67910
67911 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67912 u.bl.pC = p->apCsr[pOp->p1];
67913 assert( u.bl.pC!=0 );
67914 u.bl.res = 1;
67915 if( isSorter(u.bl.pC) ){
67916 rc = sqlite3VdbeSorterRewind(db, u.bl.pC, &u.bl.res);
 
67917 }else{
67918 u.bl.pCrsr = u.bl.pC->pCursor;
67919 assert( u.bl.pCrsr );
67920 rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
67921 u.bl.pC->atFirst = u.bl.res==0 ?1:0;
67922 u.bl.pC->deferredMoveto = 0;
67923 u.bl.pC->cacheStatus = CACHE_STALE;
67924 u.bl.pC->rowidIsValid = 0;
67925 }
67926 u.bl.pC->nullRow = (u8)u.bl.res;
67927 assert( pOp->p2>0 && pOp->p2<p->nOp );
67928 if( u.bl.res ){
67929 pc = pOp->p2 - 1;
67930 }
67931 break;
67932 }
67933
@@ -67961,45 +68003,50 @@
67961 ** sqlite3BtreePrevious().
67962 **
67963 ** If P5 is positive and the jump is taken, then event counter
67964 ** number P5-1 in the prepared statement is incremented.
67965 */
 
 
 
 
67966 case OP_Prev: /* jump */
67967 case OP_Next: { /* jump */
67968 #if 0 /* local variables moved into u.bm */
67969 VdbeCursor *pC;
67970 int res;
67971 #endif /* local variables moved into u.bm */
67972
67973 CHECK_FOR_INTERRUPT;
67974 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67975 assert( pOp->p5<=ArraySize(p->aCounter) );
67976 u.bm.pC = p->apCsr[pOp->p1];
67977 if( u.bm.pC==0 ){
67978 break; /* See ticket #2273 */
67979 }
67980 if( isSorter(u.bm.pC) ){
67981 assert( pOp->opcode==OP_Next );
67982 rc = sqlite3VdbeSorterNext(db, u.bm.pC, &u.bm.res);
 
67983 }else{
67984 u.bm.res = 1;
67985 assert( u.bm.pC->deferredMoveto==0 );
67986 assert( u.bm.pC->pCursor );
67987 assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
67988 assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
67989 rc = pOp->p4.xAdvance(u.bm.pC->pCursor, &u.bm.res);
67990 }
67991 u.bm.pC->nullRow = (u8)u.bm.res;
67992 u.bm.pC->cacheStatus = CACHE_STALE;
67993 if( u.bm.res==0 ){
67994 pc = pOp->p2 - 1;
67995 if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
67996 #ifdef SQLITE_TEST
67997 sqlite3_search_count++;
67998 #endif
67999 }
68000 u.bm.pC->rowidIsValid = 0;
68001 break;
68002 }
68003
68004 /* Opcode: IdxInsert P1 P2 P3 * P5
68005 **
@@ -68011,38 +68058,44 @@
68011 ** insert is likely to be an append.
68012 **
68013 ** This instruction only works for indices. The equivalent instruction
68014 ** for tables is OP_Insert.
68015 */
 
 
 
 
68016 case OP_IdxInsert: { /* in2 */
68017 #if 0 /* local variables moved into u.bn */
68018 VdbeCursor *pC;
68019 BtCursor *pCrsr;
68020 int nKey;
68021 const char *zKey;
68022 #endif /* local variables moved into u.bn */
68023
68024 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68025 u.bn.pC = p->apCsr[pOp->p1];
68026 assert( u.bn.pC!=0 );
 
68027 pIn2 = &aMem[pOp->p2];
68028 assert( pIn2->flags & MEM_Blob );
68029 u.bn.pCrsr = u.bn.pC->pCursor;
68030 if( ALWAYS(u.bn.pCrsr!=0) ){
68031 assert( u.bn.pC->isTable==0 );
68032 rc = ExpandBlob(pIn2);
68033 if( rc==SQLITE_OK ){
68034 u.bn.nKey = pIn2->n;
68035 u.bn.zKey = pIn2->z;
68036 rc = sqlite3VdbeSorterWrite(db, u.bn.pC, u.bn.nKey);
68037 if( rc==SQLITE_OK ){
68038 rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
68039 ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
68040 );
68041 assert( u.bn.pC->deferredMoveto==0 );
68042 }
68043 u.bn.pC->cacheStatus = CACHE_STALE;
 
68044 }
68045 }
68046 break;
68047 }
68048
@@ -68051,37 +68104,37 @@
68051 ** The content of P3 registers starting at register P2 form
68052 ** an unpacked index key. This opcode removes that entry from the
68053 ** index opened by cursor P1.
68054 */
68055 case OP_IdxDelete: {
68056 #if 0 /* local variables moved into u.bo */
68057 VdbeCursor *pC;
68058 BtCursor *pCrsr;
68059 int res;
68060 UnpackedRecord r;
68061 #endif /* local variables moved into u.bo */
68062
68063 assert( pOp->p3>0 );
68064 assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
68065 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68066 u.bo.pC = p->apCsr[pOp->p1];
68067 assert( u.bo.pC!=0 );
68068 u.bo.pCrsr = u.bo.pC->pCursor;
68069 if( ALWAYS(u.bo.pCrsr!=0) ){
68070 u.bo.r.pKeyInfo = u.bo.pC->pKeyInfo;
68071 u.bo.r.nField = (u16)pOp->p3;
68072 u.bo.r.flags = 0;
68073 u.bo.r.aMem = &aMem[pOp->p2];
68074 #ifdef SQLITE_DEBUG
68075 { int i; for(i=0; i<u.bo.r.nField; i++) assert( memIsValid(&u.bo.r.aMem[i]) ); }
68076 #endif
68077 rc = sqlite3BtreeMovetoUnpacked(u.bo.pCrsr, &u.bo.r, 0, 0, &u.bo.res);
68078 if( rc==SQLITE_OK && u.bo.res==0 ){
68079 rc = sqlite3BtreeDelete(u.bo.pCrsr);
68080 }
68081 assert( u.bo.pC->deferredMoveto==0 );
68082 u.bo.pC->cacheStatus = CACHE_STALE;
68083 }
68084 break;
68085 }
68086
68087 /* Opcode: IdxRowid P1 P2 * * *
@@ -68091,32 +68144,32 @@
68091 ** the rowid of the table entry to which this index entry points.
68092 **
68093 ** See also: Rowid, MakeRecord.
68094 */
68095 case OP_IdxRowid: { /* out2-prerelease */
68096 #if 0 /* local variables moved into u.bp */
68097 BtCursor *pCrsr;
68098 VdbeCursor *pC;
68099 i64 rowid;
68100 #endif /* local variables moved into u.bp */
68101
68102 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68103 u.bp.pC = p->apCsr[pOp->p1];
68104 assert( u.bp.pC!=0 );
68105 u.bp.pCrsr = u.bp.pC->pCursor;
68106 pOut->flags = MEM_Null;
68107 if( ALWAYS(u.bp.pCrsr!=0) ){
68108 rc = sqlite3VdbeCursorMoveto(u.bp.pC);
68109 if( NEVER(rc) ) goto abort_due_to_error;
68110 assert( u.bp.pC->deferredMoveto==0 );
68111 assert( u.bp.pC->isTable==0 );
68112 if( !u.bp.pC->nullRow ){
68113 rc = sqlite3VdbeIdxRowid(db, u.bp.pCrsr, &u.bp.rowid);
68114 if( rc!=SQLITE_OK ){
68115 goto abort_due_to_error;
68116 }
68117 pOut->u.i = u.bp.rowid;
68118 pOut->flags = MEM_Int;
68119 }
68120 }
68121 break;
68122 }
@@ -68147,43 +68200,43 @@
68147 ** If P5 is non-zero then the key value is increased by an epsilon prior
68148 ** to the comparison. This makes the opcode work like IdxLE.
68149 */
68150 case OP_IdxLT: /* jump */
68151 case OP_IdxGE: { /* jump */
68152 #if 0 /* local variables moved into u.bq */
68153 VdbeCursor *pC;
68154 int res;
68155 UnpackedRecord r;
68156 #endif /* local variables moved into u.bq */
68157
68158 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68159 u.bq.pC = p->apCsr[pOp->p1];
68160 assert( u.bq.pC!=0 );
68161 assert( u.bq.pC->isOrdered );
68162 if( ALWAYS(u.bq.pC->pCursor!=0) ){
68163 assert( u.bq.pC->deferredMoveto==0 );
68164 assert( pOp->p5==0 || pOp->p5==1 );
68165 assert( pOp->p4type==P4_INT32 );
68166 u.bq.r.pKeyInfo = u.bq.pC->pKeyInfo;
68167 u.bq.r.nField = (u16)pOp->p4.i;
68168 if( pOp->p5 ){
68169 u.bq.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
68170 }else{
68171 u.bq.r.flags = UNPACKED_IGNORE_ROWID;
68172 }
68173 u.bq.r.aMem = &aMem[pOp->p3];
68174 #ifdef SQLITE_DEBUG
68175 { int i; for(i=0; i<u.bq.r.nField; i++) assert( memIsValid(&u.bq.r.aMem[i]) ); }
68176 #endif
68177 rc = sqlite3VdbeIdxKeyCompare(u.bq.pC, &u.bq.r, &u.bq.res);
68178 if( pOp->opcode==OP_IdxLT ){
68179 u.bq.res = -u.bq.res;
68180 }else{
68181 assert( pOp->opcode==OP_IdxGE );
68182 u.bq.res++;
68183 }
68184 if( u.bq.res>0 ){
68185 pc = pOp->p2 - 1 ;
68186 }
68187 }
68188 break;
68189 }
@@ -68207,43 +68260,43 @@
68207 ** If AUTOVACUUM is disabled then a zero is stored in register P2.
68208 **
68209 ** See also: Clear
68210 */
68211 case OP_Destroy: { /* out2-prerelease */
68212 #if 0 /* local variables moved into u.br */
68213 int iMoved;
68214 int iCnt;
68215 Vdbe *pVdbe;
68216 int iDb;
68217 #endif /* local variables moved into u.br */
68218 #ifndef SQLITE_OMIT_VIRTUALTABLE
68219 u.br.iCnt = 0;
68220 for(u.br.pVdbe=db->pVdbe; u.br.pVdbe; u.br.pVdbe = u.br.pVdbe->pNext){
68221 if( u.br.pVdbe->magic==VDBE_MAGIC_RUN && u.br.pVdbe->inVtabMethod<2 && u.br.pVdbe->pc>=0 ){
68222 u.br.iCnt++;
68223 }
68224 }
68225 #else
68226 u.br.iCnt = db->activeVdbeCnt;
68227 #endif
68228 pOut->flags = MEM_Null;
68229 if( u.br.iCnt>1 ){
68230 rc = SQLITE_LOCKED;
68231 p->errorAction = OE_Abort;
68232 }else{
68233 u.br.iDb = pOp->p3;
68234 assert( u.br.iCnt==1 );
68235 assert( (p->btreeMask & (((yDbMask)1)<<u.br.iDb))!=0 );
68236 rc = sqlite3BtreeDropTable(db->aDb[u.br.iDb].pBt, pOp->p1, &u.br.iMoved);
68237 pOut->flags = MEM_Int;
68238 pOut->u.i = u.br.iMoved;
68239 #ifndef SQLITE_OMIT_AUTOVACUUM
68240 if( rc==SQLITE_OK && u.br.iMoved!=0 ){
68241 sqlite3RootPageMoved(db, u.br.iDb, u.br.iMoved, pOp->p1);
68242 /* All OP_Destroy operations occur on the same btree */
68243 assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.br.iDb+1 );
68244 resetSchemaOnFault = u.br.iDb+1;
68245 }
68246 #endif
68247 }
68248 break;
68249 }
@@ -68265,25 +68318,25 @@
68265 ** also incremented by the number of rows in the table being cleared.
68266 **
68267 ** See also: Destroy
68268 */
68269 case OP_Clear: {
68270 #if 0 /* local variables moved into u.bs */
68271 int nChange;
68272 #endif /* local variables moved into u.bs */
68273
68274 u.bs.nChange = 0;
68275 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
68276 rc = sqlite3BtreeClearTable(
68277 db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bs.nChange : 0)
68278 );
68279 if( pOp->p3 ){
68280 p->nChange += u.bs.nChange;
68281 if( pOp->p3>0 ){
68282 assert( memIsValid(&aMem[pOp->p3]) );
68283 memAboutToChange(p, &aMem[pOp->p3]);
68284 aMem[pOp->p3].u.i += u.bs.nChange;
68285 }
68286 }
68287 break;
68288 }
68289
@@ -68309,29 +68362,29 @@
68309 **
68310 ** See documentation on OP_CreateTable for additional information.
68311 */
68312 case OP_CreateIndex: /* out2-prerelease */
68313 case OP_CreateTable: { /* out2-prerelease */
68314 #if 0 /* local variables moved into u.bt */
68315 int pgno;
68316 int flags;
68317 Db *pDb;
68318 #endif /* local variables moved into u.bt */
68319
68320 u.bt.pgno = 0;
68321 assert( pOp->p1>=0 && pOp->p1<db->nDb );
68322 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
68323 u.bt.pDb = &db->aDb[pOp->p1];
68324 assert( u.bt.pDb->pBt!=0 );
68325 if( pOp->opcode==OP_CreateTable ){
68326 /* u.bt.flags = BTREE_INTKEY; */
68327 u.bt.flags = BTREE_INTKEY;
68328 }else{
68329 u.bt.flags = BTREE_BLOBKEY;
68330 }
68331 rc = sqlite3BtreeCreateTable(u.bt.pDb->pBt, &u.bt.pgno, u.bt.flags);
68332 pOut->u.i = u.bt.pgno;
68333 break;
68334 }
68335
68336 /* Opcode: ParseSchema P1 * * P4 *
68337 **
@@ -68340,48 +68393,48 @@
68340 **
68341 ** This opcode invokes the parser to create a new virtual machine,
68342 ** then runs the new virtual machine. It is thus a re-entrant opcode.
68343 */
68344 case OP_ParseSchema: {
68345 #if 0 /* local variables moved into u.bu */
68346 int iDb;
68347 const char *zMaster;
68348 char *zSql;
68349 InitData initData;
68350 #endif /* local variables moved into u.bu */
68351
68352 /* Any prepared statement that invokes this opcode will hold mutexes
68353 ** on every btree. This is a prerequisite for invoking
68354 ** sqlite3InitCallback().
68355 */
68356 #ifdef SQLITE_DEBUG
68357 for(u.bu.iDb=0; u.bu.iDb<db->nDb; u.bu.iDb++){
68358 assert( u.bu.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bu.iDb].pBt) );
68359 }
68360 #endif
68361
68362 u.bu.iDb = pOp->p1;
68363 assert( u.bu.iDb>=0 && u.bu.iDb<db->nDb );
68364 assert( DbHasProperty(db, u.bu.iDb, DB_SchemaLoaded) );
68365 /* Used to be a conditional */ {
68366 u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb);
68367 u.bu.initData.db = db;
68368 u.bu.initData.iDb = pOp->p1;
68369 u.bu.initData.pzErrMsg = &p->zErrMsg;
68370 u.bu.zSql = sqlite3MPrintf(db,
68371 "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
68372 db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z);
68373 if( u.bu.zSql==0 ){
68374 rc = SQLITE_NOMEM;
68375 }else{
68376 assert( db->init.busy==0 );
68377 db->init.busy = 1;
68378 u.bu.initData.rc = SQLITE_OK;
68379 assert( !db->mallocFailed );
68380 rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0);
68381 if( rc==SQLITE_OK ) rc = u.bu.initData.rc;
68382 sqlite3DbFree(db, u.bu.zSql);
68383 db->init.busy = 0;
68384 }
68385 }
68386 if( rc==SQLITE_NOMEM ){
68387 goto no_mem;
@@ -68460,45 +68513,45 @@
68460 ** file, not the main database file.
68461 **
68462 ** This opcode is used to implement the integrity_check pragma.
68463 */
68464 case OP_IntegrityCk: {
68465 #if 0 /* local variables moved into u.bv */
68466 int nRoot; /* Number of tables to check. (Number of root pages.) */
68467 int *aRoot; /* Array of rootpage numbers for tables to be checked */
68468 int j; /* Loop counter */
68469 int nErr; /* Number of errors reported */
68470 char *z; /* Text of the error report */
68471 Mem *pnErr; /* Register keeping track of errors remaining */
68472 #endif /* local variables moved into u.bv */
68473
68474 u.bv.nRoot = pOp->p2;
68475 assert( u.bv.nRoot>0 );
68476 u.bv.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bv.nRoot+1) );
68477 if( u.bv.aRoot==0 ) goto no_mem;
68478 assert( pOp->p3>0 && pOp->p3<=p->nMem );
68479 u.bv.pnErr = &aMem[pOp->p3];
68480 assert( (u.bv.pnErr->flags & MEM_Int)!=0 );
68481 assert( (u.bv.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
68482 pIn1 = &aMem[pOp->p1];
68483 for(u.bv.j=0; u.bv.j<u.bv.nRoot; u.bv.j++){
68484 u.bv.aRoot[u.bv.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bv.j]);
68485 }
68486 u.bv.aRoot[u.bv.j] = 0;
68487 assert( pOp->p5<db->nDb );
68488 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
68489 u.bv.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bv.aRoot, u.bv.nRoot,
68490 (int)u.bv.pnErr->u.i, &u.bv.nErr);
68491 sqlite3DbFree(db, u.bv.aRoot);
68492 u.bv.pnErr->u.i -= u.bv.nErr;
68493 sqlite3VdbeMemSetNull(pIn1);
68494 if( u.bv.nErr==0 ){
68495 assert( u.bv.z==0 );
68496 }else if( u.bv.z==0 ){
68497 goto no_mem;
68498 }else{
68499 sqlite3VdbeMemSetStr(pIn1, u.bv.z, -1, SQLITE_UTF8, sqlite3_free);
68500 }
68501 UPDATE_MAX_BLOBSIZE(pIn1);
68502 sqlite3VdbeChangeEncoding(pIn1, encoding);
68503 break;
68504 }
@@ -68528,24 +68581,24 @@
68528 ** Extract the smallest value from boolean index P1 and put that value into
68529 ** register P3. Or, if boolean index P1 is initially empty, leave P3
68530 ** unchanged and jump to instruction P2.
68531 */
68532 case OP_RowSetRead: { /* jump, in1, out3 */
68533 #if 0 /* local variables moved into u.bw */
68534 i64 val;
68535 #endif /* local variables moved into u.bw */
68536 CHECK_FOR_INTERRUPT;
68537 pIn1 = &aMem[pOp->p1];
68538 if( (pIn1->flags & MEM_RowSet)==0
68539 || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bw.val)==0
68540 ){
68541 /* The boolean index is empty */
68542 sqlite3VdbeMemSetNull(pIn1);
68543 pc = pOp->p2 - 1;
68544 }else{
68545 /* A value was pulled from the index */
68546 sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bw.val);
68547 }
68548 break;
68549 }
68550
68551 /* Opcode: RowSetTest P1 P2 P3 P4
@@ -68570,18 +68623,18 @@
68570 ** inserted, there is no need to search to see if the same value was
68571 ** previously inserted as part of set X (only if it was previously
68572 ** inserted as part of some other set).
68573 */
68574 case OP_RowSetTest: { /* jump, in1, in3 */
68575 #if 0 /* local variables moved into u.bx */
68576 int iSet;
68577 int exists;
68578 #endif /* local variables moved into u.bx */
68579
68580 pIn1 = &aMem[pOp->p1];
68581 pIn3 = &aMem[pOp->p3];
68582 u.bx.iSet = pOp->p4.i;
68583 assert( pIn3->flags&MEM_Int );
68584
68585 /* If there is anything other than a rowset object in memory cell P1,
68586 ** delete it now and initialize P1 with an empty rowset
68587 */
@@ -68589,21 +68642,21 @@
68589 sqlite3VdbeMemSetRowSet(pIn1);
68590 if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
68591 }
68592
68593 assert( pOp->p4type==P4_INT32 );
68594 assert( u.bx.iSet==-1 || u.bx.iSet>=0 );
68595 if( u.bx.iSet ){
68596 u.bx.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
68597 (u8)(u.bx.iSet>=0 ? u.bx.iSet & 0xf : 0xff),
68598 pIn3->u.i);
68599 if( u.bx.exists ){
68600 pc = pOp->p2 - 1;
68601 break;
68602 }
68603 }
68604 if( u.bx.iSet>=0 ){
68605 sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
68606 }
68607 break;
68608 }
68609
@@ -68622,25 +68675,25 @@
68622 ** memory required by the sub-vdbe at runtime.
68623 **
68624 ** P4 is a pointer to the VM containing the trigger program.
68625 */
68626 case OP_Program: { /* jump */
68627 #if 0 /* local variables moved into u.by */
68628 int nMem; /* Number of memory registers for sub-program */
68629 int nByte; /* Bytes of runtime space required for sub-program */
68630 Mem *pRt; /* Register to allocate runtime space */
68631 Mem *pMem; /* Used to iterate through memory cells */
68632 Mem *pEnd; /* Last memory cell in new array */
68633 VdbeFrame *pFrame; /* New vdbe frame to execute in */
68634 SubProgram *pProgram; /* Sub-program to execute */
68635 void *t; /* Token identifying trigger */
68636 #endif /* local variables moved into u.by */
68637
68638 u.by.pProgram = pOp->p4.pProgram;
68639 u.by.pRt = &aMem[pOp->p3];
68640 assert( memIsValid(u.by.pRt) );
68641 assert( u.by.pProgram->nOp>0 );
68642
68643 /* If the p5 flag is clear, then recursive invocation of triggers is
68644 ** disabled for backwards compatibility (p5 is set if this sub-program
68645 ** is really a trigger, not a foreign key action, and the flag set
68646 ** and cleared by the "PRAGMA recursive_triggers" command is clear).
@@ -68650,79 +68703,79 @@
68650 ** SubProgram (if the trigger may be executed with more than one different
68651 ** ON CONFLICT algorithm). SubProgram structures associated with a
68652 ** single trigger all have the same value for the SubProgram.token
68653 ** variable. */
68654 if( pOp->p5 ){
68655 u.by.t = u.by.pProgram->token;
68656 for(u.by.pFrame=p->pFrame; u.by.pFrame && u.by.pFrame->token!=u.by.t; u.by.pFrame=u.by.pFrame->pParent);
68657 if( u.by.pFrame ) break;
68658 }
68659
68660 if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
68661 rc = SQLITE_ERROR;
68662 sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
68663 break;
68664 }
68665
68666 /* Register u.by.pRt is used to store the memory required to save the state
68667 ** of the current program, and the memory required at runtime to execute
68668 ** the trigger program. If this trigger has been fired before, then u.by.pRt
68669 ** is already allocated. Otherwise, it must be initialized. */
68670 if( (u.by.pRt->flags&MEM_Frame)==0 ){
68671 /* SubProgram.nMem is set to the number of memory cells used by the
68672 ** program stored in SubProgram.aOp. As well as these, one memory
68673 ** cell is required for each cursor used by the program. Set local
68674 ** variable u.by.nMem (and later, VdbeFrame.nChildMem) to this value.
68675 */
68676 u.by.nMem = u.by.pProgram->nMem + u.by.pProgram->nCsr;
68677 u.by.nByte = ROUND8(sizeof(VdbeFrame))
68678 + u.by.nMem * sizeof(Mem)
68679 + u.by.pProgram->nCsr * sizeof(VdbeCursor *);
68680 u.by.pFrame = sqlite3DbMallocZero(db, u.by.nByte);
68681 if( !u.by.pFrame ){
68682 goto no_mem;
68683 }
68684 sqlite3VdbeMemRelease(u.by.pRt);
68685 u.by.pRt->flags = MEM_Frame;
68686 u.by.pRt->u.pFrame = u.by.pFrame;
68687
68688 u.by.pFrame->v = p;
68689 u.by.pFrame->nChildMem = u.by.nMem;
68690 u.by.pFrame->nChildCsr = u.by.pProgram->nCsr;
68691 u.by.pFrame->pc = pc;
68692 u.by.pFrame->aMem = p->aMem;
68693 u.by.pFrame->nMem = p->nMem;
68694 u.by.pFrame->apCsr = p->apCsr;
68695 u.by.pFrame->nCursor = p->nCursor;
68696 u.by.pFrame->aOp = p->aOp;
68697 u.by.pFrame->nOp = p->nOp;
68698 u.by.pFrame->token = u.by.pProgram->token;
68699
68700 u.by.pEnd = &VdbeFrameMem(u.by.pFrame)[u.by.pFrame->nChildMem];
68701 for(u.by.pMem=VdbeFrameMem(u.by.pFrame); u.by.pMem!=u.by.pEnd; u.by.pMem++){
68702 u.by.pMem->flags = MEM_Null;
68703 u.by.pMem->db = db;
68704 }
68705 }else{
68706 u.by.pFrame = u.by.pRt->u.pFrame;
68707 assert( u.by.pProgram->nMem+u.by.pProgram->nCsr==u.by.pFrame->nChildMem );
68708 assert( u.by.pProgram->nCsr==u.by.pFrame->nChildCsr );
68709 assert( pc==u.by.pFrame->pc );
68710 }
68711
68712 p->nFrame++;
68713 u.by.pFrame->pParent = p->pFrame;
68714 u.by.pFrame->lastRowid = lastRowid;
68715 u.by.pFrame->nChange = p->nChange;
68716 p->nChange = 0;
68717 p->pFrame = u.by.pFrame;
68718 p->aMem = aMem = &VdbeFrameMem(u.by.pFrame)[-1];
68719 p->nMem = u.by.pFrame->nChildMem;
68720 p->nCursor = (u16)u.by.pFrame->nChildCsr;
68721 p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
68722 p->aOp = aOp = u.by.pProgram->aOp;
68723 p->nOp = u.by.pProgram->nOp;
68724 pc = -1;
68725
68726 break;
68727 }
68728
@@ -68737,17 +68790,17 @@
68737 ** The address of the cell in the parent frame is determined by adding
68738 ** the value of the P1 argument to the value of the P1 argument to the
68739 ** calling OP_Program instruction.
68740 */
68741 case OP_Param: { /* out2-prerelease */
68742 #if 0 /* local variables moved into u.bz */
68743 VdbeFrame *pFrame;
68744 Mem *pIn;
68745 #endif /* local variables moved into u.bz */
68746 u.bz.pFrame = p->pFrame;
68747 u.bz.pIn = &u.bz.pFrame->aMem[pOp->p1 + u.bz.pFrame->aOp[u.bz.pFrame->pc].p1];
68748 sqlite3VdbeMemShallowCopy(pOut, u.bz.pIn, MEM_Ephem);
68749 break;
68750 }
68751
68752 #endif /* #ifndef SQLITE_OMIT_TRIGGER */
68753
@@ -68799,26 +68852,26 @@
68799 **
68800 ** This instruction throws an error if the memory cell is not initially
68801 ** an integer.
68802 */
68803 case OP_MemMax: { /* in2 */
68804 #if 0 /* local variables moved into u.ca */
68805 Mem *pIn1;
68806 VdbeFrame *pFrame;
68807 #endif /* local variables moved into u.ca */
68808 if( p->pFrame ){
68809 for(u.ca.pFrame=p->pFrame; u.ca.pFrame->pParent; u.ca.pFrame=u.ca.pFrame->pParent);
68810 u.ca.pIn1 = &u.ca.pFrame->aMem[pOp->p1];
68811 }else{
68812 u.ca.pIn1 = &aMem[pOp->p1];
68813 }
68814 assert( memIsValid(u.ca.pIn1) );
68815 sqlite3VdbeMemIntegerify(u.ca.pIn1);
68816 pIn2 = &aMem[pOp->p2];
68817 sqlite3VdbeMemIntegerify(pIn2);
68818 if( u.ca.pIn1->u.i<pIn2->u.i){
68819 u.ca.pIn1->u.i = pIn2->u.i;
68820 }
68821 break;
68822 }
68823 #endif /* SQLITE_OMIT_AUTOINCREMENT */
68824
@@ -68881,54 +68934,54 @@
68881 **
68882 ** The P5 arguments are taken from register P2 and its
68883 ** successors.
68884 */
68885 case OP_AggStep: {
68886 #if 0 /* local variables moved into u.cb */
68887 int n;
68888 int i;
68889 Mem *pMem;
68890 Mem *pRec;
68891 sqlite3_context ctx;
68892 sqlite3_value **apVal;
68893 #endif /* local variables moved into u.cb */
68894
68895 u.cb.n = pOp->p5;
68896 assert( u.cb.n>=0 );
68897 u.cb.pRec = &aMem[pOp->p2];
68898 u.cb.apVal = p->apArg;
68899 assert( u.cb.apVal || u.cb.n==0 );
68900 for(u.cb.i=0; u.cb.i<u.cb.n; u.cb.i++, u.cb.pRec++){
68901 assert( memIsValid(u.cb.pRec) );
68902 u.cb.apVal[u.cb.i] = u.cb.pRec;
68903 memAboutToChange(p, u.cb.pRec);
68904 sqlite3VdbeMemStoreType(u.cb.pRec);
68905 }
68906 u.cb.ctx.pFunc = pOp->p4.pFunc;
68907 assert( pOp->p3>0 && pOp->p3<=p->nMem );
68908 u.cb.ctx.pMem = u.cb.pMem = &aMem[pOp->p3];
68909 u.cb.pMem->n++;
68910 u.cb.ctx.s.flags = MEM_Null;
68911 u.cb.ctx.s.z = 0;
68912 u.cb.ctx.s.zMalloc = 0;
68913 u.cb.ctx.s.xDel = 0;
68914 u.cb.ctx.s.db = db;
68915 u.cb.ctx.isError = 0;
68916 u.cb.ctx.pColl = 0;
68917 if( u.cb.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
68918 assert( pOp>p->aOp );
68919 assert( pOp[-1].p4type==P4_COLLSEQ );
68920 assert( pOp[-1].opcode==OP_CollSeq );
68921 u.cb.ctx.pColl = pOp[-1].p4.pColl;
68922 }
68923 (u.cb.ctx.pFunc->xStep)(&u.cb.ctx, u.cb.n, u.cb.apVal); /* IMP: R-24505-23230 */
68924 if( u.cb.ctx.isError ){
68925 sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cb.ctx.s));
68926 rc = u.cb.ctx.isError;
68927 }
68928
68929 sqlite3VdbeMemRelease(&u.cb.ctx.s);
68930
68931 break;
68932 }
68933
68934 /* Opcode: AggFinal P1 P2 * P4 *
@@ -68942,23 +68995,23 @@
68942 ** functions that can take varying numbers of arguments. The
68943 ** P4 argument is only needed for the degenerate case where
68944 ** the step function was not previously called.
68945 */
68946 case OP_AggFinal: {
68947 #if 0 /* local variables moved into u.cc */
68948 Mem *pMem;
68949 #endif /* local variables moved into u.cc */
68950 assert( pOp->p1>0 && pOp->p1<=p->nMem );
68951 u.cc.pMem = &aMem[pOp->p1];
68952 assert( (u.cc.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
68953 rc = sqlite3VdbeMemFinalize(u.cc.pMem, pOp->p4.pFunc);
68954 if( rc ){
68955 sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cc.pMem));
68956 }
68957 sqlite3VdbeChangeEncoding(u.cc.pMem, encoding);
68958 UPDATE_MAX_BLOBSIZE(u.cc.pMem);
68959 if( sqlite3VdbeMemTooBig(u.cc.pMem) ){
68960 goto too_big;
68961 }
68962 break;
68963 }
68964
@@ -68973,29 +69026,29 @@
68973 ** in the WAL that have been checkpointed after the checkpoint
68974 ** completes into mem[P3+2]. However on an error, mem[P3+1] and
68975 ** mem[P3+2] are initialized to -1.
68976 */
68977 case OP_Checkpoint: {
68978 #if 0 /* local variables moved into u.cd */
68979 int i; /* Loop counter */
68980 int aRes[3]; /* Results */
68981 Mem *pMem; /* Write results here */
68982 #endif /* local variables moved into u.cd */
68983
68984 u.cd.aRes[0] = 0;
68985 u.cd.aRes[1] = u.cd.aRes[2] = -1;
68986 assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
68987 || pOp->p2==SQLITE_CHECKPOINT_FULL
68988 || pOp->p2==SQLITE_CHECKPOINT_RESTART
68989 );
68990 rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cd.aRes[1], &u.cd.aRes[2]);
68991 if( rc==SQLITE_BUSY ){
68992 rc = SQLITE_OK;
68993 u.cd.aRes[0] = 1;
68994 }
68995 for(u.cd.i=0, u.cd.pMem = &aMem[pOp->p3]; u.cd.i<3; u.cd.i++, u.cd.pMem++){
68996 sqlite3VdbeMemSetInt64(u.cd.pMem, (i64)u.cd.aRes[u.cd.i]);
68997 }
68998 break;
68999 };
69000 #endif
69001
@@ -69010,95 +69063,95 @@
69010 ** If changing into or out of WAL mode the procedure is more complicated.
69011 **
69012 ** Write a string containing the final journal-mode to register P2.
69013 */
69014 case OP_JournalMode: { /* out2-prerelease */
69015 #if 0 /* local variables moved into u.ce */
69016 Btree *pBt; /* Btree to change journal mode of */
69017 Pager *pPager; /* Pager associated with pBt */
69018 int eNew; /* New journal mode */
69019 int eOld; /* The old journal mode */
69020 const char *zFilename; /* Name of database file for pPager */
69021 #endif /* local variables moved into u.ce */
69022
69023 u.ce.eNew = pOp->p3;
69024 assert( u.ce.eNew==PAGER_JOURNALMODE_DELETE
69025 || u.ce.eNew==PAGER_JOURNALMODE_TRUNCATE
69026 || u.ce.eNew==PAGER_JOURNALMODE_PERSIST
69027 || u.ce.eNew==PAGER_JOURNALMODE_OFF
69028 || u.ce.eNew==PAGER_JOURNALMODE_MEMORY
69029 || u.ce.eNew==PAGER_JOURNALMODE_WAL
69030 || u.ce.eNew==PAGER_JOURNALMODE_QUERY
69031 );
69032 assert( pOp->p1>=0 && pOp->p1<db->nDb );
69033
69034 u.ce.pBt = db->aDb[pOp->p1].pBt;
69035 u.ce.pPager = sqlite3BtreePager(u.ce.pBt);
69036 u.ce.eOld = sqlite3PagerGetJournalMode(u.ce.pPager);
69037 if( u.ce.eNew==PAGER_JOURNALMODE_QUERY ) u.ce.eNew = u.ce.eOld;
69038 if( !sqlite3PagerOkToChangeJournalMode(u.ce.pPager) ) u.ce.eNew = u.ce.eOld;
69039
69040 #ifndef SQLITE_OMIT_WAL
69041 u.ce.zFilename = sqlite3PagerFilename(u.ce.pPager);
69042
69043 /* Do not allow a transition to journal_mode=WAL for a database
69044 ** in temporary storage or if the VFS does not support shared memory
69045 */
69046 if( u.ce.eNew==PAGER_JOURNALMODE_WAL
69047 && (u.ce.zFilename[0]==0 /* Temp file */
69048 || !sqlite3PagerWalSupported(u.ce.pPager)) /* No shared-memory support */
69049 ){
69050 u.ce.eNew = u.ce.eOld;
69051 }
69052
69053 if( (u.ce.eNew!=u.ce.eOld)
69054 && (u.ce.eOld==PAGER_JOURNALMODE_WAL || u.ce.eNew==PAGER_JOURNALMODE_WAL)
69055 ){
69056 if( !db->autoCommit || db->activeVdbeCnt>1 ){
69057 rc = SQLITE_ERROR;
69058 sqlite3SetString(&p->zErrMsg, db,
69059 "cannot change %s wal mode from within a transaction",
69060 (u.ce.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
69061 );
69062 break;
69063 }else{
69064
69065 if( u.ce.eOld==PAGER_JOURNALMODE_WAL ){
69066 /* If leaving WAL mode, close the log file. If successful, the call
69067 ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
69068 ** file. An EXCLUSIVE lock may still be held on the database file
69069 ** after a successful return.
69070 */
69071 rc = sqlite3PagerCloseWal(u.ce.pPager);
69072 if( rc==SQLITE_OK ){
69073 sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);
69074 }
69075 }else if( u.ce.eOld==PAGER_JOURNALMODE_MEMORY ){
69076 /* Cannot transition directly from MEMORY to WAL. Use mode OFF
69077 ** as an intermediate */
69078 sqlite3PagerSetJournalMode(u.ce.pPager, PAGER_JOURNALMODE_OFF);
69079 }
69080
69081 /* Open a transaction on the database file. Regardless of the journal
69082 ** mode, this transaction always uses a rollback journal.
69083 */
69084 assert( sqlite3BtreeIsInTrans(u.ce.pBt)==0 );
69085 if( rc==SQLITE_OK ){
69086 rc = sqlite3BtreeSetVersion(u.ce.pBt, (u.ce.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
69087 }
69088 }
69089 }
69090 #endif /* ifndef SQLITE_OMIT_WAL */
69091
69092 if( rc ){
69093 u.ce.eNew = u.ce.eOld;
69094 }
69095 u.ce.eNew = sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);
69096
69097 pOut = &aMem[pOp->p2];
69098 pOut->flags = MEM_Str|MEM_Static|MEM_Term;
69099 pOut->z = (char *)sqlite3JournalModename(u.ce.eNew);
69100 pOut->n = sqlite3Strlen30(pOut->z);
69101 pOut->enc = SQLITE_UTF8;
69102 sqlite3VdbeChangeEncoding(pOut, encoding);
69103 break;
69104 };
@@ -69123,18 +69176,18 @@
69123 ** Perform a single step of the incremental vacuum procedure on
69124 ** the P1 database. If the vacuum has finished, jump to instruction
69125 ** P2. Otherwise, fall through to the next instruction.
69126 */
69127 case OP_IncrVacuum: { /* jump */
69128 #if 0 /* local variables moved into u.cf */
69129 Btree *pBt;
69130 #endif /* local variables moved into u.cf */
69131
69132 assert( pOp->p1>=0 && pOp->p1<db->nDb );
69133 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
69134 u.cf.pBt = db->aDb[pOp->p1].pBt;
69135 rc = sqlite3BtreeIncrVacuum(u.cf.pBt);
69136 if( rc==SQLITE_DONE ){
69137 pc = pOp->p2 - 1;
69138 rc = SQLITE_OK;
69139 }
69140 break;
@@ -69200,16 +69253,16 @@
69200 ** Also, whether or not P4 is set, check that this is not being called from
69201 ** within a callback to a virtual table xSync() method. If it is, the error
69202 ** code will be set to SQLITE_LOCKED.
69203 */
69204 case OP_VBegin: {
69205 #if 0 /* local variables moved into u.cg */
69206 VTable *pVTab;
69207 #endif /* local variables moved into u.cg */
69208 u.cg.pVTab = pOp->p4.pVtab;
69209 rc = sqlite3VtabBegin(db, u.cg.pVTab);
69210 if( u.cg.pVTab ) importVtabErrMsg(p, u.cg.pVTab->pVtab);
69211 break;
69212 }
69213 #endif /* SQLITE_OMIT_VIRTUALTABLE */
69214
69215 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -69244,36 +69297,36 @@
69244 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
69245 ** P1 is a cursor number. This opcode opens a cursor to the virtual
69246 ** table and stores that cursor in P1.
69247 */
69248 case OP_VOpen: {
69249 #if 0 /* local variables moved into u.ch */
69250 VdbeCursor *pCur;
69251 sqlite3_vtab_cursor *pVtabCursor;
69252 sqlite3_vtab *pVtab;
69253 sqlite3_module *pModule;
69254 #endif /* local variables moved into u.ch */
69255
69256 u.ch.pCur = 0;
69257 u.ch.pVtabCursor = 0;
69258 u.ch.pVtab = pOp->p4.pVtab->pVtab;
69259 u.ch.pModule = (sqlite3_module *)u.ch.pVtab->pModule;
69260 assert(u.ch.pVtab && u.ch.pModule);
69261 rc = u.ch.pModule->xOpen(u.ch.pVtab, &u.ch.pVtabCursor);
69262 importVtabErrMsg(p, u.ch.pVtab);
69263 if( SQLITE_OK==rc ){
69264 /* Initialize sqlite3_vtab_cursor base class */
69265 u.ch.pVtabCursor->pVtab = u.ch.pVtab;
69266
69267 /* Initialise vdbe cursor object */
69268 u.ch.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
69269 if( u.ch.pCur ){
69270 u.ch.pCur->pVtabCursor = u.ch.pVtabCursor;
69271 u.ch.pCur->pModule = u.ch.pVtabCursor->pVtab->pModule;
69272 }else{
69273 db->mallocFailed = 1;
69274 u.ch.pModule->xClose(u.ch.pVtabCursor);
69275 }
69276 }
69277 break;
69278 }
69279 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69296,11 +69349,11 @@
69296 ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
69297 **
69298 ** A jump is made to P2 if the result set after filtering would be empty.
69299 */
69300 case OP_VFilter: { /* jump */
69301 #if 0 /* local variables moved into u.ci */
69302 int nArg;
69303 int iQuery;
69304 const sqlite3_module *pModule;
69305 Mem *pQuery;
69306 Mem *pArgc;
@@ -69308,49 +69361,49 @@
69308 sqlite3_vtab *pVtab;
69309 VdbeCursor *pCur;
69310 int res;
69311 int i;
69312 Mem **apArg;
69313 #endif /* local variables moved into u.ci */
69314
69315 u.ci.pQuery = &aMem[pOp->p3];
69316 u.ci.pArgc = &u.ci.pQuery[1];
69317 u.ci.pCur = p->apCsr[pOp->p1];
69318 assert( memIsValid(u.ci.pQuery) );
69319 REGISTER_TRACE(pOp->p3, u.ci.pQuery);
69320 assert( u.ci.pCur->pVtabCursor );
69321 u.ci.pVtabCursor = u.ci.pCur->pVtabCursor;
69322 u.ci.pVtab = u.ci.pVtabCursor->pVtab;
69323 u.ci.pModule = u.ci.pVtab->pModule;
69324
69325 /* Grab the index number and argc parameters */
69326 assert( (u.ci.pQuery->flags&MEM_Int)!=0 && u.ci.pArgc->flags==MEM_Int );
69327 u.ci.nArg = (int)u.ci.pArgc->u.i;
69328 u.ci.iQuery = (int)u.ci.pQuery->u.i;
69329
69330 /* Invoke the xFilter method */
69331 {
69332 u.ci.res = 0;
69333 u.ci.apArg = p->apArg;
69334 for(u.ci.i = 0; u.ci.i<u.ci.nArg; u.ci.i++){
69335 u.ci.apArg[u.ci.i] = &u.ci.pArgc[u.ci.i+1];
69336 sqlite3VdbeMemStoreType(u.ci.apArg[u.ci.i]);
69337 }
69338
69339 p->inVtabMethod = 1;
69340 rc = u.ci.pModule->xFilter(u.ci.pVtabCursor, u.ci.iQuery, pOp->p4.z, u.ci.nArg, u.ci.apArg);
69341 p->inVtabMethod = 0;
69342 importVtabErrMsg(p, u.ci.pVtab);
69343 if( rc==SQLITE_OK ){
69344 u.ci.res = u.ci.pModule->xEof(u.ci.pVtabCursor);
69345 }
69346
69347 if( u.ci.res ){
69348 pc = pOp->p2 - 1;
69349 }
69350 }
69351 u.ci.pCur->nullRow = 0;
69352
69353 break;
69354 }
69355 #endif /* SQLITE_OMIT_VIRTUALTABLE */
69356
@@ -69360,55 +69413,55 @@
69360 ** Store the value of the P2-th column of
69361 ** the row of the virtual-table that the
69362 ** P1 cursor is pointing to into register P3.
69363 */
69364 case OP_VColumn: {
69365 #if 0 /* local variables moved into u.cj */
69366 sqlite3_vtab *pVtab;
69367 const sqlite3_module *pModule;
69368 Mem *pDest;
69369 sqlite3_context sContext;
69370 #endif /* local variables moved into u.cj */
69371
69372 VdbeCursor *pCur = p->apCsr[pOp->p1];
69373 assert( pCur->pVtabCursor );
69374 assert( pOp->p3>0 && pOp->p3<=p->nMem );
69375 u.cj.pDest = &aMem[pOp->p3];
69376 memAboutToChange(p, u.cj.pDest);
69377 if( pCur->nullRow ){
69378 sqlite3VdbeMemSetNull(u.cj.pDest);
69379 break;
69380 }
69381 u.cj.pVtab = pCur->pVtabCursor->pVtab;
69382 u.cj.pModule = u.cj.pVtab->pModule;
69383 assert( u.cj.pModule->xColumn );
69384 memset(&u.cj.sContext, 0, sizeof(u.cj.sContext));
69385
69386 /* The output cell may already have a buffer allocated. Move
69387 ** the current contents to u.cj.sContext.s so in case the user-function
69388 ** can use the already allocated buffer instead of allocating a
69389 ** new one.
69390 */
69391 sqlite3VdbeMemMove(&u.cj.sContext.s, u.cj.pDest);
69392 MemSetTypeFlag(&u.cj.sContext.s, MEM_Null);
69393
69394 rc = u.cj.pModule->xColumn(pCur->pVtabCursor, &u.cj.sContext, pOp->p2);
69395 importVtabErrMsg(p, u.cj.pVtab);
69396 if( u.cj.sContext.isError ){
69397 rc = u.cj.sContext.isError;
69398 }
69399
69400 /* Copy the result of the function to the P3 register. We
69401 ** do this regardless of whether or not an error occurred to ensure any
69402 ** dynamic allocation in u.cj.sContext.s (a Mem struct) is released.
69403 */
69404 sqlite3VdbeChangeEncoding(&u.cj.sContext.s, encoding);
69405 sqlite3VdbeMemMove(u.cj.pDest, &u.cj.sContext.s);
69406 REGISTER_TRACE(pOp->p3, u.cj.pDest);
69407 UPDATE_MAX_BLOBSIZE(u.cj.pDest);
69408
69409 if( sqlite3VdbeMemTooBig(u.cj.pDest) ){
69410 goto too_big;
69411 }
69412 break;
69413 }
69414 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69419,42 +69472,42 @@
69419 ** Advance virtual table P1 to the next row in its result set and
69420 ** jump to instruction P2. Or, if the virtual table has reached
69421 ** the end of its result set, then fall through to the next instruction.
69422 */
69423 case OP_VNext: { /* jump */
69424 #if 0 /* local variables moved into u.ck */
69425 sqlite3_vtab *pVtab;
69426 const sqlite3_module *pModule;
69427 int res;
69428 VdbeCursor *pCur;
69429 #endif /* local variables moved into u.ck */
69430
69431 u.ck.res = 0;
69432 u.ck.pCur = p->apCsr[pOp->p1];
69433 assert( u.ck.pCur->pVtabCursor );
69434 if( u.ck.pCur->nullRow ){
69435 break;
69436 }
69437 u.ck.pVtab = u.ck.pCur->pVtabCursor->pVtab;
69438 u.ck.pModule = u.ck.pVtab->pModule;
69439 assert( u.ck.pModule->xNext );
69440
69441 /* Invoke the xNext() method of the module. There is no way for the
69442 ** underlying implementation to return an error if one occurs during
69443 ** xNext(). Instead, if an error occurs, true is returned (indicating that
69444 ** data is available) and the error code returned when xColumn or
69445 ** some other method is next invoked on the save virtual table cursor.
69446 */
69447 p->inVtabMethod = 1;
69448 rc = u.ck.pModule->xNext(u.ck.pCur->pVtabCursor);
69449 p->inVtabMethod = 0;
69450 importVtabErrMsg(p, u.ck.pVtab);
69451 if( rc==SQLITE_OK ){
69452 u.ck.res = u.ck.pModule->xEof(u.ck.pCur->pVtabCursor);
69453 }
69454
69455 if( !u.ck.res ){
69456 /* If there is data, jump to P2 */
69457 pc = pOp->p2 - 1;
69458 }
69459 break;
69460 }
@@ -69466,23 +69519,23 @@
69466 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
69467 ** This opcode invokes the corresponding xRename method. The value
69468 ** in register P1 is passed as the zName argument to the xRename method.
69469 */
69470 case OP_VRename: {
69471 #if 0 /* local variables moved into u.cl */
69472 sqlite3_vtab *pVtab;
69473 Mem *pName;
69474 #endif /* local variables moved into u.cl */
69475
69476 u.cl.pVtab = pOp->p4.pVtab->pVtab;
69477 u.cl.pName = &aMem[pOp->p1];
69478 assert( u.cl.pVtab->pModule->xRename );
69479 assert( memIsValid(u.cl.pName) );
69480 REGISTER_TRACE(pOp->p1, u.cl.pName);
69481 assert( u.cl.pName->flags & MEM_Str );
69482 rc = u.cl.pVtab->pModule->xRename(u.cl.pVtab, u.cl.pName->z);
69483 importVtabErrMsg(p, u.cl.pVtab);
69484 p->expired = 0;
69485
69486 break;
69487 }
69488 #endif
@@ -69510,45 +69563,45 @@
69510 ** P1 is a boolean flag. If it is set to true and the xUpdate call
69511 ** is successful, then the value returned by sqlite3_last_insert_rowid()
69512 ** is set to the value of the rowid for the row just inserted.
69513 */
69514 case OP_VUpdate: {
69515 #if 0 /* local variables moved into u.cm */
69516 sqlite3_vtab *pVtab;
69517 sqlite3_module *pModule;
69518 int nArg;
69519 int i;
69520 sqlite_int64 rowid;
69521 Mem **apArg;
69522 Mem *pX;
69523 #endif /* local variables moved into u.cm */
69524
69525 assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
69526 || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
69527 );
69528 u.cm.pVtab = pOp->p4.pVtab->pVtab;
69529 u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
69530 u.cm.nArg = pOp->p2;
69531 assert( pOp->p4type==P4_VTAB );
69532 if( ALWAYS(u.cm.pModule->xUpdate) ){
69533 u8 vtabOnConflict = db->vtabOnConflict;
69534 u.cm.apArg = p->apArg;
69535 u.cm.pX = &aMem[pOp->p3];
69536 for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
69537 assert( memIsValid(u.cm.pX) );
69538 memAboutToChange(p, u.cm.pX);
69539 sqlite3VdbeMemStoreType(u.cm.pX);
69540 u.cm.apArg[u.cm.i] = u.cm.pX;
69541 u.cm.pX++;
69542 }
69543 db->vtabOnConflict = pOp->p5;
69544 rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
69545 db->vtabOnConflict = vtabOnConflict;
69546 importVtabErrMsg(p, u.cm.pVtab);
69547 if( rc==SQLITE_OK && pOp->p1 ){
69548 assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
69549 db->lastRowid = lastRowid = u.cm.rowid;
69550 }
69551 if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
69552 if( pOp->p5==OE_Ignore ){
69553 rc = SQLITE_OK;
69554 }else{
@@ -69604,25 +69657,25 @@
69604 **
69605 ** If tracing is enabled (by the sqlite3_trace()) interface, then
69606 ** the UTF-8 string contained in P4 is emitted on the trace callback.
69607 */
69608 case OP_Trace: {
69609 #if 0 /* local variables moved into u.cn */
69610 char *zTrace;
69611 char *z;
69612 #endif /* local variables moved into u.cn */
69613
69614 if( db->xTrace && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
69615 u.cn.z = sqlite3VdbeExpandSql(p, u.cn.zTrace);
69616 db->xTrace(db->pTraceArg, u.cn.z);
69617 sqlite3DbFree(db, u.cn.z);
69618 }
69619 #ifdef SQLITE_DEBUG
69620 if( (db->flags & SQLITE_SqlTrace)!=0
69621 && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
69622 ){
69623 sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace);
69624 }
69625 #endif /* SQLITE_DEBUG */
69626 break;
69627 }
69628 #endif
@@ -70021,21 +70074,21 @@
70021 /* Make sure a mutex is held on the table to be accessed */
70022 sqlite3VdbeUsesBtree(v, iDb);
70023
70024 /* Configure the OP_TableLock instruction */
70025 #ifdef SQLITE_OMIT_SHARED_CACHE
70026 sqlite3VdbeChangeToNoop(v, 2, 1);
70027 #else
70028 sqlite3VdbeChangeP1(v, 2, iDb);
70029 sqlite3VdbeChangeP2(v, 2, pTab->tnum);
70030 sqlite3VdbeChangeP3(v, 2, flags);
70031 sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
70032 #endif
70033
70034 /* Remove either the OP_OpenWrite or OpenRead. Set the P2
70035 ** parameter of the other to pTab->tnum. */
70036 sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
70037 sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
70038 sqlite3VdbeChangeP3(v, 3 + flags, iDb);
70039
70040 /* Configure the number of columns. Configure the cursor to
70041 ** think that the table has one more column than it really
@@ -70239,10 +70292,11 @@
70239
70240
70241 #ifndef SQLITE_OMIT_MERGE_SORT
70242
70243 typedef struct VdbeSorterIter VdbeSorterIter;
 
70244
70245 /*
70246 ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
70247 **
70248 ** As keys are added to the sorter, they are written to disk in a series
@@ -70310,19 +70364,22 @@
70310 ** In other words, each time we advance to the next sorter element, log2(N)
70311 ** key comparison operations are required, where N is the number of segments
70312 ** being merged (rounded up to the next power of 2).
70313 */
70314 struct VdbeSorter {
70315 int nWorking; /* Start a new b-tree after this many pages */
70316 int nBtree; /* Current size of b-tree contents as PMA */
70317 int nTree; /* Used size of aTree/aIter (power of 2) */
70318 VdbeSorterIter *aIter; /* Array of iterators to merge */
70319 int *aTree; /* Current state of incremental merge */
70320 i64 iWriteOff; /* Current write offset within file pTemp1 */
70321 i64 iReadOff; /* Current read offset within file pTemp1 */
70322 sqlite3_file *pTemp1; /* PMA file 1 */
70323 int nPMA; /* Number of PMAs stored in pTemp1 */
 
 
 
 
70324 };
70325
70326 /*
70327 ** The following type is an iterator for a PMA. It caches the current key in
70328 ** variables nKey/aKey. If the iterator is at EOF, pFile==0.
@@ -70334,10 +70391,21 @@
70334 int nAlloc; /* Bytes of space at aAlloc */
70335 u8 *aAlloc; /* Allocated space */
70336 int nKey; /* Number of bytes in key */
70337 u8 *aKey; /* Pointer to current key */
70338 };
 
 
 
 
 
 
 
 
 
 
 
70339
70340 /* Minimum allowable value for the VdbeSorter.nWorking variable */
70341 #define SORTER_MIN_WORKING 10
70342
70343 /* Maximum number of segments to merge in a single pass. */
@@ -70360,41 +70428,46 @@
70360 sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */
70361 VdbeSorterIter *pIter /* Iterator to advance */
70362 ){
70363 int rc; /* Return Code */
70364 int nRead; /* Number of bytes read */
70365 int nRec; /* Size of record in bytes */
70366 int iOff; /* Size of serialized size varint in bytes */
70367
70368 nRead = pIter->iEof - pIter->iReadOff;
70369 if( nRead>5 ) nRead = 5;
 
 
 
 
70370 if( nRead<=0 ){
70371 /* This is an EOF condition */
70372 vdbeSorterIterZero(db, pIter);
70373 return SQLITE_OK;
70374 }
70375
70376 rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
70377 iOff = getVarint32(pIter->aAlloc, nRec);
70378
70379 if( rc==SQLITE_OK && (iOff+nRec)>nRead ){
70380 int nRead2; /* Number of extra bytes to read */
70381 if( (iOff+nRec)>pIter->nAlloc ){
70382 int nNew = pIter->nAlloc*2;
70383 while( (iOff+nRec)>nNew ) nNew = nNew*2;
70384 pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
70385 if( !pIter->aAlloc ) return SQLITE_NOMEM;
70386 pIter->nAlloc = nNew;
70387 }
70388
70389 nRead2 = iOff + nRec - nRead;
70390 rc = sqlite3OsRead(
70391 pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
70392 );
70393 }
70394
70395 assert( nRec>0 || rc!=SQLITE_OK );
 
70396 pIter->iReadOff += iOff+nRec;
70397 pIter->nKey = nRec;
70398 pIter->aKey = &pIter->aAlloc[iOff];
70399 return rc;
70400 }
@@ -70434,25 +70507,18 @@
70434 ** set to the integer value read. If an error occurs, the final values of
70435 ** both *piOffset and *piVal are undefined.
70436 */
70437 static int vdbeSorterReadVarint(
70438 sqlite3_file *pFile, /* File to read from */
70439 i64 iEof, /* Total number of bytes in file */
70440 i64 *piOffset, /* IN/OUT: Read offset in pFile */
70441 i64 *piVal /* OUT: Value read from file */
70442 ){
70443 u8 aVarint[9]; /* Buffer large enough for a varint */
70444 i64 iOff = *piOffset; /* Offset in file to read from */
70445 int nRead = 9; /* Number of bytes to read from file */
70446 int rc; /* Return code */
70447
70448 assert( iEof>iOff );
70449 if( (iEof-iOff)<nRead ){
70450 nRead = iEof-iOff;
70451 }
70452
70453 rc = sqlite3OsRead(pFile, aVarint, nRead, iOff);
70454 if( rc==SQLITE_OK ){
70455 *piOffset += getVarint(aVarint, (u64 *)piVal);
70456 }
70457
70458 return rc;
@@ -70480,22 +70546,68 @@
70480 pIter->nAlloc = 128;
70481 pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
70482 if( !pIter->aAlloc ){
70483 rc = SQLITE_NOMEM;
70484 }else{
70485 i64 iEof = pSorter->iWriteOff; /* EOF of file pSorter->pTemp1 */
70486 i64 nByte; /* Total size of PMA in bytes */
70487 rc = vdbeSorterReadVarint(pSorter->pTemp1, iEof, &pIter->iReadOff, &nByte);
70488 *pnByte += nByte;
70489 pIter->iEof = pIter->iReadOff + nByte;
70490 }
70491 if( rc==SQLITE_OK ){
70492 rc = vdbeSorterIterNext(db, pIter);
70493 }
70494 return rc;
70495 }
70496
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70497 /*
70498 ** This function is called to compare two iterator keys when merging
70499 ** multiple b-tree segments. Parameter iOut is the index of the aTree[]
70500 ** value to recalculate.
70501 */
@@ -70523,24 +70635,20 @@
70523 if( p1->pFile==0 ){
70524 iRes = i2;
70525 }else if( p2->pFile==0 ){
70526 iRes = i1;
70527 }else{
70528 char aSpace[150];
70529 UnpackedRecord *r1;
70530
70531 r1 = sqlite3VdbeRecordUnpack(
70532 pCsr->pKeyInfo, p1->nKey, p1->aKey, aSpace, sizeof(aSpace)
70533 );
70534 if( r1==0 ) return SQLITE_NOMEM;
70535
70536 if( sqlite3VdbeRecordCompare(p2->nKey, p2->aKey, r1)>=0 ){
70537 iRes = i1;
70538 }else{
70539 iRes = i2;
70540 }
70541 sqlite3VdbeDeleteUnpackedRecord(r1);
70542 }
70543
70544 pSorter->aTree[iOut] = iRes;
70545 return SQLITE_OK;
70546 }
@@ -70547,13 +70655,46 @@
70547
70548 /*
70549 ** Initialize the temporary index cursor just opened as a sorter cursor.
70550 */
70551 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
70552 assert( pCsr->pKeyInfo && pCsr->pBt );
70553 pCsr->pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
70554 return (pCsr->pSorter ? SQLITE_OK : SQLITE_NOMEM);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70555 }
70556
70557 /*
70558 ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
70559 */
@@ -70568,10 +70709,12 @@
70568 sqlite3DbFree(db, pSorter->aIter);
70569 }
70570 if( pSorter->pTemp1 ){
70571 sqlite3OsCloseFree(pSorter->pTemp1);
70572 }
 
 
70573 sqlite3DbFree(db, pSorter);
70574 pCsr->pSorter = 0;
70575 }
70576 }
70577
@@ -70587,14 +70730,86 @@
70587 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
70588 SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy
70589 );
70590 }
70591
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70592
70593 /*
70594 ** Write the current contents of the b-tree to a PMA. Return SQLITE_OK
70595 ** if successful, or an SQLite error code otherwise.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70596 **
70597 ** The format of a PMA is:
70598 **
70599 ** * A varint. This varint contains the total number of bytes of content
70600 ** in the PMA (not including the varint itself).
@@ -70601,153 +70816,111 @@
70601 **
70602 ** * One or more records packed end-to-end in order of ascending keys.
70603 ** Each record consists of a varint followed by a blob of data (the
70604 ** key). The varint is the number of bytes in the blob of data.
70605 */
70606 static int vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){
70607 int rc = SQLITE_OK; /* Return code */
70608 VdbeSorter *pSorter = pCsr->pSorter;
70609 int res = 0;
70610
70611 /* sqlite3BtreeFirst() cannot fail because sorter btrees are always held
70612 ** in memory and so an I/O error is not possible. */
70613 rc = sqlite3BtreeFirst(pCsr->pCursor, &res);
70614 if( NEVER(rc!=SQLITE_OK) || res ) return rc;
70615 assert( pSorter->nBtree>0 );
 
70616
70617 /* If the first temporary PMA file has not been opened, open it now. */
70618 if( pSorter->pTemp1==0 ){
70619 rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
70620 assert( rc!=SQLITE_OK || pSorter->pTemp1 );
70621 assert( pSorter->iWriteOff==0 );
70622 assert( pSorter->nPMA==0 );
70623 }
70624
70625 if( rc==SQLITE_OK ){
70626 i64 iWriteOff = pSorter->iWriteOff;
70627 void *aMalloc = 0; /* Array used to hold a single record */
70628 int nMalloc = 0; /* Allocated size of aMalloc[] in bytes */
 
70629
70630 pSorter->nPMA++;
70631 for(
70632 rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nBtree, &iWriteOff);
70633 rc==SQLITE_OK && res==0;
70634 rc = sqlite3BtreeNext(pCsr->pCursor, &res)
70635 ){
70636 i64 nKey; /* Size of this key in bytes */
70637
70638 /* Write the size of the record in bytes to the output file */
70639 (void)sqlite3BtreeKeySize(pCsr->pCursor, &nKey);
70640 rc = vdbeSorterWriteVarint(pSorter->pTemp1, nKey, &iWriteOff);
70641
70642 /* Make sure the aMalloc[] buffer is large enough for the record */
70643 if( rc==SQLITE_OK && nKey>nMalloc ){
70644 aMalloc = sqlite3DbReallocOrFree(db, aMalloc, nKey);
70645 if( !aMalloc ){
70646 rc = SQLITE_NOMEM;
70647 }else{
70648 nMalloc = nKey;
70649 }
70650 }
70651
70652 /* Write the record itself to the output file */
70653 if( rc==SQLITE_OK ){
70654 /* sqlite3BtreeKey() cannot fail because sorter btrees held in memory */
70655 rc = sqlite3BtreeKey(pCsr->pCursor, 0, nKey, aMalloc);
70656 if( ALWAYS(rc==SQLITE_OK) ){
70657 rc = sqlite3OsWrite(pSorter->pTemp1, aMalloc, nKey, iWriteOff);
70658 iWriteOff += nKey;
70659 }
70660 }
70661
70662 if( rc!=SQLITE_OK ) break;
70663 }
70664
70665 /* This assert verifies that unless an error has occurred, the size of
70666 ** the PMA on disk is the same as the expected size stored in
70667 ** pSorter->nBtree. */
70668 assert( rc!=SQLITE_OK || pSorter->nBtree==(
70669 iWriteOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nBtree)
70670 ));
70671
70672 pSorter->iWriteOff = iWriteOff;
70673 sqlite3DbFree(db, aMalloc);
 
 
 
 
 
70674 }
70675
70676 pSorter->nBtree = 0;
70677 return rc;
70678 }
70679
70680 /*
70681 ** This function is called on a sorter cursor by the VDBE before each row
70682 ** is inserted into VdbeCursor.pCsr. Argument nKey is the size of the key, in
70683 ** bytes, about to be inserted.
70684 **
70685 ** If it is determined that the temporary b-tree accessed via VdbeCursor.pCsr
70686 ** is large enough, its contents are written to a sorted PMA on disk and the
70687 ** tree emptied. This prevents the b-tree (which must be small enough to
70688 ** fit entirely in the cache in order to support efficient inserts) from
70689 ** growing too large.
70690 **
70691 ** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK.
70692 */
70693 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *db, VdbeCursor *pCsr, int nKey){
70694 int rc = SQLITE_OK; /* Return code */
 
 
 
70695 VdbeSorter *pSorter = pCsr->pSorter;
70696 if( pSorter ){
70697 Pager *pPager = sqlite3BtreePager(pCsr->pBt);
70698 int nPage; /* Current size of temporary file in pages */
70699
70700 /* Sorters never spill to disk */
70701 assert( sqlite3PagerFile(pPager)->pMethods==0 );
70702
70703 /* Determine how many pages the temporary b-tree has grown to */
70704 sqlite3PagerPagecount(pPager, &nPage);
70705
70706 /* If pSorter->nWorking is still zero, but the temporary file has been
70707 ** created in the file-system, then the most recent insert into the
70708 ** current b-tree segment probably caused the cache to overflow (it is
70709 ** also possible that sqlite3_release_memory() was called). So set the
70710 ** size of the working set to a little less than the current size of the
70711 ** file in pages. */
70712 if( pSorter->nWorking==0 && sqlite3PagerUnderStress(pPager) ){
70713 pSorter->nWorking = nPage-5;
70714 if( pSorter->nWorking<SORTER_MIN_WORKING ){
70715 pSorter->nWorking = SORTER_MIN_WORKING;
70716 }
70717 }
70718
70719 /* If the number of pages used by the current b-tree segment is greater
70720 ** than the size of the working set (VdbeSorter.nWorking), start a new
70721 ** segment b-tree. */
70722 if( pSorter->nWorking && nPage>=pSorter->nWorking ){
70723 BtCursor *p = pCsr->pCursor;/* Cursor structure to close and reopen */
70724 int iRoot; /* Root page of new tree */
70725
70726 /* Copy the current contents of the b-tree into a PMA in sorted order.
70727 ** Close the currently open b-tree cursor. */
70728 rc = vdbeSorterBtreeToPMA(db, pCsr);
70729 sqlite3BtreeCloseCursor(p);
70730
70731 if( rc==SQLITE_OK ){
70732 rc = sqlite3BtreeDropTable(pCsr->pBt, 2, 0);
70733 #ifdef SQLITE_DEBUG
70734 sqlite3PagerPagecount(pPager, &nPage);
70735 assert( rc!=SQLITE_OK || nPage==1 );
70736 #endif
70737 }
70738 if( rc==SQLITE_OK ){
70739 rc = sqlite3BtreeCreateTable(pCsr->pBt, &iRoot, BTREE_BLOBKEY);
70740 }
70741 if( rc==SQLITE_OK ){
70742 assert( iRoot==2 );
70743 rc = sqlite3BtreeCursor(pCsr->pBt, iRoot, 1, pCsr->pKeyInfo, p);
70744 }
70745 }
70746
70747 pSorter->nBtree += sqlite3VarintLen(nKey) + nKey;
70748 }
70749 return rc;
70750 }
70751
70752 /*
70753 ** Helper function for sqlite3VdbeSorterRewind().
@@ -70761,16 +70934,16 @@
70761 int rc = SQLITE_OK; /* Return code */
70762 int i; /* Used to iterator through aIter[] */
70763 i64 nByte = 0; /* Total bytes in all opened PMAs */
70764
70765 /* Initialize the iterators. */
70766 for(i=0; rc==SQLITE_OK && i<SORTER_MAX_MERGE_COUNT; i++){
70767 VdbeSorterIter *pIter = &pSorter->aIter[i];
70768 rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
70769 pSorter->iReadOff = pIter->iEof;
70770 assert( pSorter->iReadOff<=pSorter->iWriteOff || rc!=SQLITE_OK );
70771 if( pSorter->iReadOff>=pSorter->iWriteOff ) break;
70772 }
70773
70774 /* Initialize the aTree[] array. */
70775 for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
70776 rc = vdbeSorterDoCompare(pCsr, i);
@@ -70793,18 +70966,22 @@
70793 int nByte; /* Bytes of space required for aIter/aTree */
70794 int N = 2; /* Power of 2 >= nIter */
70795
70796 assert( pSorter );
70797
70798 /* Write the current b-tree to a PMA. Close the b-tree cursor. */
70799 rc = vdbeSorterBtreeToPMA(db, pCsr);
70800 sqlite3BtreeCloseCursor(pCsr->pCursor);
70801 if( rc!=SQLITE_OK ) return rc;
70802 if( pSorter->nPMA==0 ){
70803 *pbEof = 1;
70804 return SQLITE_OK;
 
70805 }
 
 
 
 
70806
70807 /* Allocate space for aIter[] and aTree[]. */
70808 nIter = pSorter->nPMA;
70809 if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
70810 assert( nIter>0 );
@@ -70888,47 +71065,94 @@
70888 /*
70889 ** Advance to the next element in the sorter.
70890 */
70891 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
70892 VdbeSorter *pSorter = pCsr->pSorter;
70893 int iPrev = pSorter->aTree[1]; /* Index of iterator to advance */
70894 int i; /* Index of aTree[] to recalculate */
70895 int rc; /* Return code */
70896
70897 rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
70898 for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
70899 rc = vdbeSorterDoCompare(pCsr, i);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70900 }
 
 
70901
70902 *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
70903 return rc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70904 }
70905
70906 /*
70907 ** Copy the current sorter key into the memory cell pOut.
70908 */
70909 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
70910 VdbeSorter *pSorter = pCsr->pSorter;
70911 VdbeSorterIter *pIter;
70912
70913 pIter = &pSorter->aIter[ pSorter->aTree[1] ];
70914
70915 /* Coverage testing note: As things are currently, this call will always
70916 ** succeed. This is because the memory cell passed by the VDBE layer
70917 ** happens to be the same one as was used to assemble the keys before they
70918 ** were passed to the sorter - meaning it is always large enough for the
70919 ** largest key. But this could change very easily, so we leave the call
70920 ** to sqlite3VdbeMemGrow() in. */
70921 if( NEVER(sqlite3VdbeMemGrow(pOut, pIter->nKey, 0)) ){
70922 return SQLITE_NOMEM;
70923 }
70924 pOut->n = pIter->nKey;
70925 MemSetTypeFlag(pOut, MEM_Blob);
70926 memcpy(pOut->z, pIter->aKey, pIter->nKey);
70927
70928 return SQLITE_OK;
70929 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70930
70931 #endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
70932
70933 /************** End of vdbesort.c ********************************************/
70934 /************** Begin file journal.c *****************************************/
@@ -73691,11 +73915,12 @@
73691 pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
73692 pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
73693 pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
73694 pNewItem->jointype = pOldItem->jointype;
73695 pNewItem->iCursor = pOldItem->iCursor;
73696 pNewItem->isPopulated = pOldItem->isPopulated;
 
73697 pNewItem->isCorrelated = pOldItem->isCorrelated;
73698 pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
73699 pNewItem->notIndexed = pOldItem->notIndexed;
73700 pNewItem->pIndex = pOldItem->pIndex;
73701 pTab = pNewItem->pTab = pOldItem->pTab;
@@ -74251,12 +74476,11 @@
74251 assert(v);
74252 if( iCol<0 ){
74253 int iMem = ++pParse->nMem;
74254 int iAddr;
74255
74256 iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
74257 sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
74258
74259 sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
74260 eType = IN_INDEX_ROWID;
74261
74262 sqlite3VdbeJumpHere(v, iAddr);
@@ -74283,12 +74507,11 @@
74283 int iMem = ++pParse->nMem;
74284 int iAddr;
74285 char *pKey;
74286
74287 pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
74288 iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
74289 sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
74290
74291 sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
74292 pKey,P4_KEYINFO_HANDOFF);
74293 VdbeComment((v, "%s", pIdx->zName));
74294 eType = IN_INDEX_INDEX;
@@ -74365,11 +74588,11 @@
74365 Parse *pParse, /* Parsing context */
74366 Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
74367 int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
74368 int isRowid /* If true, LHS of IN operator is a rowid */
74369 ){
74370 int testAddr = 0; /* One-time test address */
74371 int rReg = 0; /* Register storing resulting */
74372 Vdbe *v = sqlite3GetVdbe(pParse);
74373 if( NEVER(v==0) ) return 0;
74374 sqlite3ExprCachePush(pParse);
74375
@@ -74383,19 +74606,17 @@
74383 ** If all of the above are false, then we can run this code just once
74384 ** save the results, and reuse the same result on subsequent invocations.
74385 */
74386 if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
74387 int mem = ++pParse->nMem;
74388 sqlite3VdbeAddOp1(v, OP_If, mem);
74389 testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
74390 assert( testAddr>0 || pParse->db->mallocFailed );
74391 }
74392
74393 #ifndef SQLITE_OMIT_EXPLAIN
74394 if( pParse->explain==2 ){
74395 char *zMsg = sqlite3MPrintf(
74396 pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr?"":"CORRELATED ",
74397 pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
74398 );
74399 sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
74400 }
74401 #endif
@@ -74483,13 +74704,13 @@
74483 /* If the expression is not constant then we will need to
74484 ** disable the test that was generated above that makes sure
74485 ** this code only executes once. Because for a non-constant
74486 ** expression we need to rerun this code each time.
74487 */
74488 if( testAddr && !sqlite3ExprIsConstant(pE2) ){
74489 sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
74490 testAddr = 0;
74491 }
74492
74493 /* Evaluate the expression and insert it into the temp table */
74494 if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
74495 sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
@@ -74554,12 +74775,12 @@
74554 ExprSetIrreducible(pExpr);
74555 break;
74556 }
74557 }
74558
74559 if( testAddr ){
74560 sqlite3VdbeJumpHere(v, testAddr-1);
74561 }
74562 sqlite3ExprCachePop(pParse, 1);
74563
74564 return rReg;
74565 }
@@ -75077,11 +75298,11 @@
75077 if( !pAggInfo->directMode ){
75078 assert( pCol->iMem>0 );
75079 inReg = pCol->iMem;
75080 break;
75081 }else if( pAggInfo->useSortingIdx ){
75082 sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
75083 pCol->iSorterColumn, target);
75084 break;
75085 }
75086 /* Otherwise, fall thru into the TK_COLUMN case */
75087 }
@@ -81235,27 +81456,19 @@
81235 Table *pTab = pIndex->pTable; /* The table that is indexed */
81236 int iTab = pParse->nTab++; /* Btree cursor used for pTab */
81237 int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
81238 int iSorter = iTab; /* Cursor opened by OpenSorter (if in use) */
81239 int addr1; /* Address of top of loop */
 
81240 int tnum; /* Root page of index */
81241 Vdbe *v; /* Generate code into this virtual machine */
81242 KeyInfo *pKey; /* KeyInfo for index */
81243 int regIdxKey; /* Registers containing the index key */
81244 int regRecord; /* Register holding assemblied index record */
81245 sqlite3 *db = pParse->db; /* The database connection */
81246 int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
81247
81248 /* Set bUseSorter to use OP_OpenSorter, or clear it to insert directly
81249 ** into the index. The sorter is used unless either OMIT_MERGE_SORT is
81250 ** defined or the system is configured to store temp files in-memory. */
81251 #ifdef SQLITE_OMIT_MERGE_SORT
81252 static const int bUseSorter = 0;
81253 #else
81254 const int bUseSorter = !sqlite3TempInMemory(pParse->db);
81255 #endif
81256
81257 #ifndef SQLITE_OMIT_AUTHORIZATION
81258 if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
81259 db->aDb[iDb].zName ) ){
81260 return;
81261 }
@@ -81277,32 +81490,44 @@
81277 (char *)pKey, P4_KEYINFO_HANDOFF);
81278 if( memRootPage>=0 ){
81279 sqlite3VdbeChangeP5(v, 1);
81280 }
81281
 
81282 /* Open the sorter cursor if we are to use one. */
81283 if( bUseSorter ){
81284 iSorter = pParse->nTab++;
81285 sqlite3VdbeAddOp4(v, OP_OpenSorter, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
81286 sqlite3VdbeChangeP5(v, BTREE_SORTER);
81287 }
81288
81289 /* Open the table. Loop through all rows of the table, inserting index
81290 ** records into the sorter. */
81291 sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
81292 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
 
81293 regRecord = sqlite3GetTempReg(pParse);
81294 regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
81295
81296 if( bUseSorter ){
81297 sqlite3VdbeAddOp2(v, OP_IdxInsert, iSorter, regRecord);
81298 sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
81299 sqlite3VdbeJumpHere(v, addr1);
81300 addr1 = sqlite3VdbeAddOp2(v, OP_Sort, iSorter, 0);
81301 sqlite3VdbeAddOp2(v, OP_RowKey, iSorter, regRecord);
81302 }
81303
 
 
 
 
 
 
 
 
 
 
 
 
81304 if( pIndex->onError!=OE_None ){
81305 const int regRowid = regIdxKey + pIndex->nColumn;
81306 const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
81307 void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
81308
@@ -81317,14 +81542,15 @@
81317 */
81318 sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
81319 sqlite3HaltConstraint(
81320 pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
81321 }
81322 sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, bUseSorter);
81323 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
 
81324 sqlite3ReleaseTempReg(pParse, regRecord);
81325 sqlite3VdbeAddOp2(v, OP_Next, iSorter, addr1+1);
81326 sqlite3VdbeJumpHere(v, addr1);
81327
81328 sqlite3VdbeAddOp1(v, OP_Close, iTab);
81329 sqlite3VdbeAddOp1(v, OP_Close, iIdx);
81330 sqlite3VdbeAddOp1(v, OP_Close, iSorter);
@@ -92204,10 +92430,12 @@
92204 pNew->addrOpenEphm[2] = -1;
92205 if( db->mallocFailed ) {
92206 clearSelect(db, pNew);
92207 if( pNew!=&standin ) sqlite3DbFree(db, pNew);
92208 pNew = 0;
 
 
92209 }
92210 return pNew;
92211 }
92212
92213 /*
@@ -92534,16 +92762,22 @@
92534 ){
92535 Vdbe *v = pParse->pVdbe;
92536 int nExpr = pOrderBy->nExpr;
92537 int regBase = sqlite3GetTempRange(pParse, nExpr+2);
92538 int regRecord = sqlite3GetTempReg(pParse);
 
92539 sqlite3ExprCacheClear(pParse);
92540 sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
92541 sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
92542 sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
92543 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
92544 sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
 
 
 
 
 
92545 sqlite3ReleaseTempReg(pParse, regRecord);
92546 sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
92547 if( pSelect->iLimit ){
92548 int addr1, addr2;
92549 int iLimit;
@@ -93008,13 +93242,24 @@
93008 sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
93009 regRowid = 0;
93010 }else{
93011 regRowid = sqlite3GetTempReg(pParse);
93012 }
93013 addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
93014 codeOffset(v, p, addrContinue);
93015 sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
 
 
 
 
 
 
 
 
 
 
 
93016 switch( eDest ){
93017 case SRT_Table:
93018 case SRT_EphemTab: {
93019 testcase( eDest==SRT_Table );
93020 testcase( eDest==SRT_EphemTab );
@@ -93063,11 +93308,15 @@
93063 sqlite3ReleaseTempReg(pParse, regRowid);
93064
93065 /* The bottom of the loop
93066 */
93067 sqlite3VdbeResolveLabel(v, addrContinue);
93068 sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
 
 
 
 
93069 sqlite3VdbeResolveLabel(v, addrBreak);
93070 if( eDest==SRT_Output || eDest==SRT_Coroutine ){
93071 sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
93072 }
93073 }
@@ -95895,11 +96144,15 @@
95895 struct SrcList_item *pItem = &pTabList->a[i];
95896 SelectDest dest;
95897 Select *pSub = pItem->pSelect;
95898 int isAggSub;
95899
95900 if( pSub==0 || pItem->isPopulated ) continue;
 
 
 
 
95901
95902 /* Increment Parse.nHeight by the height of the largest expression
95903 ** tree refered to by this, the parent select. The child select
95904 ** may contain expression trees of at most
95905 ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
@@ -95906,25 +96159,48 @@
95906 ** more conservative than necessary, but much easier than enforcing
95907 ** an exact limit.
95908 */
95909 pParse->nHeight += sqlite3SelectExprHeight(p);
95910
95911 /* Check to see if the subquery can be absorbed into the parent. */
95912 isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
95913 if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
 
95914 if( isAggSub ){
95915 isAgg = 1;
95916 p->selFlags |= SF_Aggregate;
95917 }
95918 i = -1;
95919 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95920 sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
95921 assert( pItem->isPopulated==0 );
95922 explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
95923 sqlite3Select(pParse, pSub, &dest);
95924 pItem->isPopulated = 1;
95925 pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
 
 
 
 
 
95926 }
95927 if( /*pParse->nErr ||*/ db->mallocFailed ){
95928 goto select_end;
95929 }
95930 pParse->nHeight -= sqlite3SelectExprHeight(p);
@@ -96029,10 +96305,14 @@
96029 /* Set the limiter.
96030 */
96031 iEnd = sqlite3VdbeMakeLabel(v);
96032 p->nSelectRow = (double)LARGEST_INT64;
96033 computeLimitRegisters(pParse, p, iEnd);
 
 
 
 
96034
96035 /* Open a virtual index to use for the distinct set.
96036 */
96037 if( p->selFlags & SF_Distinct ){
96038 KeyInfo *pKeyInfo;
@@ -96057,18 +96337,18 @@
96057 /* If sorting index that was created by a prior OP_OpenEphemeral
96058 ** instruction ended up not being needed, then change the OP_OpenEphemeral
96059 ** into an OP_Noop.
96060 */
96061 if( addrSortIndex>=0 && pOrderBy==0 ){
96062 sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
96063 p->addrOpenEphm[2] = -1;
96064 }
96065
96066 if( pWInfo->eDistinct ){
96067 VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
96068
96069 assert( addrDistinctIndex>0 );
96070 pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
96071
96072 assert( isDistinct );
96073 assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
96074 || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
@@ -96123,10 +96403,12 @@
96123 ** one row of the input to the aggregator has been
96124 ** processed */
96125 int iAbortFlag; /* Mem address which causes query abort if positive */
96126 int groupBySort; /* Rows come from source in GROUP BY order */
96127 int addrEnd; /* End of processing for this SELECT */
 
 
96128
96129 /* Remove any and all aliases between the result set and the
96130 ** GROUP BY clause.
96131 */
96132 if( pGroupBy ){
@@ -96184,16 +96466,16 @@
96184 int addrReset; /* Subroutine for resetting the accumulator */
96185 int regReset; /* Return address register for reset subroutine */
96186
96187 /* If there is a GROUP BY clause we might need a sorting index to
96188 ** implement it. Allocate that sorting index now. If it turns out
96189 ** that we do not need it after all, the OpenEphemeral instruction
96190 ** will be converted into a Noop.
96191 */
96192 sAggInfo.sortingIdx = pParse->nTab++;
96193 pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
96194 addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
96195 sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
96196 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
96197
96198 /* Initialize memory locations used by GROUP BY aggregate processing
96199 */
@@ -96270,15 +96552,18 @@
96270 j++;
96271 }
96272 }
96273 regRecord = sqlite3GetTempReg(pParse);
96274 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
96275 sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
96276 sqlite3ReleaseTempReg(pParse, regRecord);
96277 sqlite3ReleaseTempRange(pParse, regBase, nCol);
96278 sqlite3WhereEnd(pWInfo);
96279 sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
 
 
 
96280 VdbeComment((v, "GROUP BY sort"));
96281 sAggInfo.useSortingIdx = 1;
96282 sqlite3ExprCacheClear(pParse);
96283 }
96284
@@ -96287,13 +96572,17 @@
96287 ** Then compare the current GROUP BY terms against the GROUP BY terms
96288 ** from the previous row currently stored in a0, a1, a2...
96289 */
96290 addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
96291 sqlite3ExprCacheClear(pParse);
 
 
 
96292 for(j=0; j<pGroupBy->nExpr; j++){
96293 if( groupBySort ){
96294 sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j);
 
96295 }else{
96296 sAggInfo.directMode = 1;
96297 sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
96298 }
96299 }
@@ -96328,14 +96617,14 @@
96328 VdbeComment((v, "indicate data in accumulator"));
96329
96330 /* End of the loop
96331 */
96332 if( groupBySort ){
96333 sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop);
96334 }else{
96335 sqlite3WhereEnd(pWInfo);
96336 sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
96337 }
96338
96339 /* Output the final row of result
96340 */
96341 sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
@@ -100517,15 +100806,23 @@
100517 return mask;
100518 }
100519 static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
100520 Bitmask mask = 0;
100521 while( pS ){
 
100522 mask |= exprListTableUsage(pMaskSet, pS->pEList);
100523 mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
100524 mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
100525 mask |= exprTableUsage(pMaskSet, pS->pWhere);
100526 mask |= exprTableUsage(pMaskSet, pS->pHaving);
 
 
 
 
 
 
 
100527 pS = pS->pPrior;
100528 }
100529 return mask;
100530 }
100531
@@ -102044,12 +102341,11 @@
102044 /* Generate code to skip over the creation and initialization of the
102045 ** transient index on 2nd and subsequent iterations of the loop. */
102046 v = pParse->pVdbe;
102047 assert( v!=0 );
102048 regIsInit = ++pParse->nMem;
102049 addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
102050 sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
102051
102052 /* Count the number of columns that will be added to the index
102053 ** and used to match WHERE clause constraints */
102054 nColumn = 0;
102055 pTable = pSrc->pTab;
@@ -115981,11 +116277,41 @@
115981 char *aOut;
115982 int bFirstOut = 0;
115983
115984 *paOut = 0;
115985 *pnOut = 0;
115986 aOut = sqlite3_malloc(n1+n2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115987 if( !aOut ) return SQLITE_NOMEM;
115988
115989 p = aOut;
115990 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
115991 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
@@ -116008,10 +116334,11 @@
116008 }
116009 }
116010
116011 *paOut = aOut;
116012 *pnOut = (p-aOut);
 
116013 return SQLITE_OK;
116014 }
116015
116016 /*
116017 ** This function does a "phrase" merge of two doclists. In a phrase merge,
116018
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -656,11 +656,11 @@
656 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657 ** [sqlite_version()] and [sqlite_source_id()].
658 */
659 #define SQLITE_VERSION "3.7.8"
660 #define SQLITE_VERSION_NUMBER 3007008
661 #define SQLITE_SOURCE_ID "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"
662
663 /*
664 ** CAPI3REF: Run-Time Library Version Numbers
665 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
666 **
@@ -7632,18 +7632,10 @@
7632 */
7633 #ifndef SQLITE_TEMP_STORE
7634 # define SQLITE_TEMP_STORE 1
7635 #endif
7636
 
 
 
 
 
 
 
 
7637 /*
7638 ** GCC does not define the offsetof() macro so we'll have to do it
7639 ** ourselves.
7640 */
7641 #ifndef offsetof
@@ -7982,11 +7974,10 @@
7974 #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
7975 #define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
7976 #define BTREE_MEMORY 4 /* This is an in-memory DB */
7977 #define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
7978 #define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
 
7979
7980 SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
7981 SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
7982 SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
7983 SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
@@ -8383,106 +8374,109 @@
8374 #define OP_Jump 25
8375 #define OP_And 69 /* same as TK_AND */
8376 #define OP_Or 68 /* same as TK_OR */
8377 #define OP_Not 19 /* same as TK_NOT */
8378 #define OP_BitNot 93 /* same as TK_BITNOT */
8379 #define OP_Once 26
8380 #define OP_If 27
8381 #define OP_IfNot 28
8382 #define OP_IsNull 73 /* same as TK_ISNULL */
8383 #define OP_NotNull 74 /* same as TK_NOTNULL */
8384 #define OP_Column 29
8385 #define OP_Affinity 30
8386 #define OP_MakeRecord 31
8387 #define OP_Count 32
8388 #define OP_Savepoint 33
8389 #define OP_AutoCommit 34
8390 #define OP_Transaction 35
8391 #define OP_ReadCookie 36
8392 #define OP_SetCookie 37
8393 #define OP_VerifyCookie 38
8394 #define OP_OpenRead 39
8395 #define OP_OpenWrite 40
 
8396 #define OP_OpenAutoindex 41
8397 #define OP_OpenEphemeral 42
8398 #define OP_SorterOpen 43
8399 #define OP_OpenPseudo 44
8400 #define OP_Close 45
8401 #define OP_SeekLt 46
8402 #define OP_SeekLe 47
8403 #define OP_SeekGe 48
8404 #define OP_SeekGt 49
8405 #define OP_Seek 50
8406 #define OP_NotFound 51
8407 #define OP_Found 52
8408 #define OP_IsUnique 53
8409 #define OP_NotExists 54
8410 #define OP_Sequence 55
8411 #define OP_NewRowid 56
8412 #define OP_Insert 57
8413 #define OP_InsertInt 58
8414 #define OP_Delete 59
8415 #define OP_ResetCount 60
8416 #define OP_SorterCompare 61
8417 #define OP_SorterData 62
8418 #define OP_RowKey 63
8419 #define OP_RowData 64
8420 #define OP_Rowid 65
8421 #define OP_NullRow 66
8422 #define OP_Last 67
8423 #define OP_SorterSort 70
8424 #define OP_Sort 71
8425 #define OP_Rewind 72
8426 #define OP_SorterNext 81
8427 #define OP_Prev 92
8428 #define OP_Next 95
8429 #define OP_SorterInsert 96
8430 #define OP_IdxInsert 97
8431 #define OP_IdxDelete 98
8432 #define OP_IdxRowid 99
8433 #define OP_IdxLT 100
8434 #define OP_IdxGE 101
8435 #define OP_Destroy 102
8436 #define OP_Clear 103
8437 #define OP_CreateIndex 104
8438 #define OP_CreateTable 105
8439 #define OP_ParseSchema 106
8440 #define OP_LoadAnalysis 107
8441 #define OP_DropTable 108
8442 #define OP_DropIndex 109
8443 #define OP_DropTrigger 110
8444 #define OP_IntegrityCk 111
8445 #define OP_RowSetAdd 112
8446 #define OP_RowSetRead 113
8447 #define OP_RowSetTest 114
8448 #define OP_Program 115
8449 #define OP_Param 116
8450 #define OP_FkCounter 117
8451 #define OP_FkIfZero 118
8452 #define OP_MemMax 119
8453 #define OP_IfPos 120
8454 #define OP_IfNeg 121
8455 #define OP_IfZero 122
8456 #define OP_AggStep 123
8457 #define OP_AggFinal 124
8458 #define OP_Checkpoint 125
8459 #define OP_JournalMode 126
8460 #define OP_Vacuum 127
8461 #define OP_IncrVacuum 128
8462 #define OP_Expire 129
8463 #define OP_TableLock 131
8464 #define OP_VBegin 132
8465 #define OP_VCreate 133
8466 #define OP_VDestroy 134
8467 #define OP_VOpen 135
8468 #define OP_VFilter 136
8469 #define OP_VColumn 137
8470 #define OP_VNext 138
8471 #define OP_VRename 139
8472 #define OP_VUpdate 140
8473 #define OP_Pagecount 146
8474 #define OP_MaxPgcnt 147
8475 #define OP_Trace 148
8476 #define OP_Noop 149
8477 #define OP_Explain 150
8478
8479
8480 /* Properties such as "out2" or "jump" that are specified in
8481 ** comments following the "case" for each opcode in the vdbe.c
8482 ** are encoded into bitvectors as follows:
@@ -8496,26 +8490,26 @@
8490 #define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
8491 #define OPFLG_INITIALIZER {\
8492 /* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
8493 /* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
8494 /* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
8495 /* 24 */ 0x00, 0x01, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
8496 /* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
8497 /* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
8498 /* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
8499 /* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
8500 /* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
8501 /* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
8502 /* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
8503 /* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
8504 /* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
8505 /* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
8506 /* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
8507 /* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\
8508 /* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
8509 /* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
8510 /* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}
8511
8512 /************** End of opcodes.h *********************************************/
8513 /************** Continuing where we left off in vdbe.h ***********************/
8514
8515 /*
@@ -8534,11 +8528,11 @@
8528 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
8529 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
8530 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
8531 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
8532 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
8533 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
8534 SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
8535 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
8536 SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
8537 SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
8538 SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
@@ -8566,13 +8560,13 @@
8560 SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
8561 #ifndef SQLITE_OMIT_TRACE
8562 SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
8563 #endif
8564
8565 SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
 
8566 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
8567 SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
8568
8569 #ifndef SQLITE_OMIT_TRIGGER
8570 SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
8571 #endif
8572
@@ -8653,11 +8647,10 @@
8647 ** NOTE: These values must match the corresponding BTREE_ values in btree.h.
8648 */
8649 #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
8650 #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
8651 #define PAGER_MEMORY 0x0004 /* In-memory database */
 
8652
8653 /*
8654 ** Valid values for the second argument to sqlite3PagerLockingMode().
8655 */
8656 #define PAGER_LOCKINGMODE_QUERY -1
@@ -8749,13 +8742,10 @@
8742 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
8743 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
8744 SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
8745 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
8746 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
 
 
 
8747
8748 /* Functions used to truncate the database file. */
8749 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
8750
8751 #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
@@ -10186,10 +10176,11 @@
10176 u8 directMode; /* Direct rendering mode means take data directly
10177 ** from source tables rather than from accumulators */
10178 u8 useSortingIdx; /* In direct mode, reference the sorting index rather
10179 ** than the source table */
10180 int sortingIdx; /* Cursor number of the sorting index */
10181 int sortingIdxPTab; /* Cursor number of pseudo-table */
10182 ExprList *pGroupBy; /* The group by clause */
10183 int nSortingColumn; /* Number of columns in the sorting index */
10184 struct AggInfo_col { /* For each column used in source tables */
10185 Table *pTab; /* Source table */
10186 int iTable; /* Cursor number of the source table */
@@ -10495,11 +10486,12 @@
10486 char *zDatabase; /* Name of database holding this table */
10487 char *zName; /* Name of the table */
10488 char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
10489 Table *pTab; /* An SQL table corresponding to zName */
10490 Select *pSelect; /* A SELECT statement used in place of a table name */
10491 int addrFillSub; /* Address of subroutine to manifest a subquery */
10492 int regReturn; /* Register holding return address of addrFillSub */
10493 u8 jointype; /* Type of join between this able and the previous */
10494 u8 notIndexed; /* True if there is a NOT INDEXED clause */
10495 u8 isCorrelated; /* True if sub-query is correlated */
10496 #ifndef SQLITE_OMIT_EXPLAIN
10497 u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
@@ -10718,10 +10710,11 @@
10710 #define SF_Resolved 0x0002 /* Identifiers have been resolved */
10711 #define SF_Aggregate 0x0004 /* Contains aggregate functions */
10712 #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
10713 #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
10714 #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
10715 #define SF_UseSorter 0x0040 /* Sort using a sorter */
10716
10717
10718 /*
10719 ** The results of a select can be distributed in several ways. The
10720 ** "SRT" prefix means "SELECT Result Type".
@@ -12044,11 +12037,11 @@
12037 SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
12038 1, /* bCoreMutex */
12039 SQLITE_THREADSAFE==1, /* bFullMutex */
12040 SQLITE_USE_URI, /* bOpenUri */
12041 0x7ffffffe, /* mxStrlen */
12042 128, /* szLookaside */
12043 500, /* nLookaside */
12044 {0,0,0,0,0,0,0,0}, /* m */
12045 {0,0,0,0,0,0,0,0,0}, /* mutex */
12046 {0,0,0,0,0,0,0,0,0,0,0}, /* pcache */
12047 (void*)0, /* pHeap */
@@ -12267,10 +12260,13 @@
12260 "INT64_TYPE",
12261 #endif
12262 #ifdef SQLITE_LOCK_TRACE
12263 "LOCK_TRACE",
12264 #endif
12265 #ifdef SQLITE_MAX_SCHEMA_RETRY
12266 "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
12267 #endif
12268 #ifdef SQLITE_MEMDEBUG
12269 "MEMDEBUG",
12270 #endif
12271 #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
12272 "MIXED_ENDIAN_64BIT_FLOAT",
@@ -12601,16 +12597,17 @@
12597 Bool nullRow; /* True if pointing to a row with no data */
12598 Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
12599 Bool isTable; /* True if a table requiring integer keys */
12600 Bool isIndex; /* True if an index containing keys only - no data */
12601 Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
12602 Bool isSorter; /* True if a new-style sorter */
12603 sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
12604 const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
12605 i64 seqCount; /* Sequence counter */
12606 i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
12607 i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
12608 VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
12609
12610 /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
12611 ** OP_IsUnique opcode on this cursor. */
12612 int seekResult;
12613
@@ -12944,17 +12941,19 @@
12941 # define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
12942 # define sqlite3VdbeSorterClose(Y,Z)
12943 # define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
12944 # define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
12945 # define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
12946 # define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
12947 #else
12948 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
 
12949 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
12950 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
 
12951 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
12952 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
12953 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, Mem *);
12954 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(VdbeCursor *, Mem *, int *);
12955 #endif
12956
12957 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
12958 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
12959 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
@@ -14537,11 +14536,11 @@
14536 int flags,
14537 int *pOutFlags
14538 ){
14539 int rc = SQLITE_NOMEM;
14540 sqlite3_file *pFile;
14541 pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
14542 if( pFile ){
14543 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
14544 if( rc!=SQLITE_OK ){
14545 sqlite3_free(pFile);
14546 }else{
@@ -22100,66 +22099,66 @@
22099 /* 21 */ "MustBeInt",
22100 /* 22 */ "RealAffinity",
22101 /* 23 */ "Permutation",
22102 /* 24 */ "Compare",
22103 /* 25 */ "Jump",
22104 /* 26 */ "Once",
22105 /* 27 */ "If",
22106 /* 28 */ "IfNot",
22107 /* 29 */ "Column",
22108 /* 30 */ "Affinity",
22109 /* 31 */ "MakeRecord",
22110 /* 32 */ "Count",
22111 /* 33 */ "Savepoint",
22112 /* 34 */ "AutoCommit",
22113 /* 35 */ "Transaction",
22114 /* 36 */ "ReadCookie",
22115 /* 37 */ "SetCookie",
22116 /* 38 */ "VerifyCookie",
22117 /* 39 */ "OpenRead",
22118 /* 40 */ "OpenWrite",
22119 /* 41 */ "OpenAutoindex",
22120 /* 42 */ "OpenEphemeral",
22121 /* 43 */ "SorterOpen",
22122 /* 44 */ "OpenPseudo",
22123 /* 45 */ "Close",
22124 /* 46 */ "SeekLt",
22125 /* 47 */ "SeekLe",
22126 /* 48 */ "SeekGe",
22127 /* 49 */ "SeekGt",
22128 /* 50 */ "Seek",
22129 /* 51 */ "NotFound",
22130 /* 52 */ "Found",
22131 /* 53 */ "IsUnique",
22132 /* 54 */ "NotExists",
22133 /* 55 */ "Sequence",
22134 /* 56 */ "NewRowid",
22135 /* 57 */ "Insert",
22136 /* 58 */ "InsertInt",
22137 /* 59 */ "Delete",
22138 /* 60 */ "ResetCount",
22139 /* 61 */ "SorterCompare",
22140 /* 62 */ "SorterData",
22141 /* 63 */ "RowKey",
22142 /* 64 */ "RowData",
22143 /* 65 */ "Rowid",
22144 /* 66 */ "NullRow",
22145 /* 67 */ "Last",
22146 /* 68 */ "Or",
22147 /* 69 */ "And",
22148 /* 70 */ "SorterSort",
22149 /* 71 */ "Sort",
22150 /* 72 */ "Rewind",
22151 /* 73 */ "IsNull",
22152 /* 74 */ "NotNull",
22153 /* 75 */ "Ne",
22154 /* 76 */ "Eq",
22155 /* 77 */ "Gt",
22156 /* 78 */ "Le",
22157 /* 79 */ "Lt",
22158 /* 80 */ "Ge",
22159 /* 81 */ "SorterNext",
22160 /* 82 */ "BitAnd",
22161 /* 83 */ "BitOr",
22162 /* 84 */ "ShiftLeft",
22163 /* 85 */ "ShiftRight",
22164 /* 86 */ "Add",
@@ -22166,64 +22165,69 @@
22165 /* 87 */ "Subtract",
22166 /* 88 */ "Multiply",
22167 /* 89 */ "Divide",
22168 /* 90 */ "Remainder",
22169 /* 91 */ "Concat",
22170 /* 92 */ "Prev",
22171 /* 93 */ "BitNot",
22172 /* 94 */ "String8",
22173 /* 95 */ "Next",
22174 /* 96 */ "SorterInsert",
22175 /* 97 */ "IdxInsert",
22176 /* 98 */ "IdxDelete",
22177 /* 99 */ "IdxRowid",
22178 /* 100 */ "IdxLT",
22179 /* 101 */ "IdxGE",
22180 /* 102 */ "Destroy",
22181 /* 103 */ "Clear",
22182 /* 104 */ "CreateIndex",
22183 /* 105 */ "CreateTable",
22184 /* 106 */ "ParseSchema",
22185 /* 107 */ "LoadAnalysis",
22186 /* 108 */ "DropTable",
22187 /* 109 */ "DropIndex",
22188 /* 110 */ "DropTrigger",
22189 /* 111 */ "IntegrityCk",
22190 /* 112 */ "RowSetAdd",
22191 /* 113 */ "RowSetRead",
22192 /* 114 */ "RowSetTest",
22193 /* 115 */ "Program",
22194 /* 116 */ "Param",
22195 /* 117 */ "FkCounter",
22196 /* 118 */ "FkIfZero",
22197 /* 119 */ "MemMax",
22198 /* 120 */ "IfPos",
22199 /* 121 */ "IfNeg",
22200 /* 122 */ "IfZero",
22201 /* 123 */ "AggStep",
22202 /* 124 */ "AggFinal",
22203 /* 125 */ "Checkpoint",
22204 /* 126 */ "JournalMode",
22205 /* 127 */ "Vacuum",
22206 /* 128 */ "IncrVacuum",
22207 /* 129 */ "Expire",
22208 /* 130 */ "Real",
22209 /* 131 */ "TableLock",
22210 /* 132 */ "VBegin",
22211 /* 133 */ "VCreate",
22212 /* 134 */ "VDestroy",
22213 /* 135 */ "VOpen",
22214 /* 136 */ "VFilter",
22215 /* 137 */ "VColumn",
22216 /* 138 */ "VNext",
22217 /* 139 */ "VRename",
22218 /* 140 */ "VUpdate",
22219 /* 141 */ "ToText",
22220 /* 142 */ "ToBlob",
22221 /* 143 */ "ToNumeric",
22222 /* 144 */ "ToInt",
22223 /* 145 */ "ToReal",
22224 /* 146 */ "Pagecount",
22225 /* 147 */ "MaxPgcnt",
22226 /* 148 */ "Trace",
22227 /* 149 */ "Noop",
22228 /* 150 */ "Explain",
22229 };
22230 return azName[i];
22231 }
22232 #endif
22233
@@ -22314,11 +22318,11 @@
22318 */
22319 #ifdef MEMORY_DEBUG
22320 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
22321 #endif
22322
22323 #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
22324 # ifndef SQLITE_DEBUG_OS_TRACE
22325 # define SQLITE_DEBUG_OS_TRACE 0
22326 # endif
22327 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
22328 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -24656,11 +24660,11 @@
24660 */
24661 #ifdef MEMORY_DEBUG
24662 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
24663 #endif
24664
24665 #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
24666 # ifndef SQLITE_DEBUG_OS_TRACE
24667 # define SQLITE_DEBUG_OS_TRACE 0
24668 # endif
24669 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
24670 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -27716,15 +27720,15 @@
27720 SQLITE_API int sqlite3_fullsync_count = 0;
27721 #endif
27722
27723 /*
27724 ** We do not trust systems to provide a working fdatasync(). Some do.
27725 ** Others do no. To be safe, we will stick with the (slightly slower)
27726 ** fsync(). If you know that your system does support fdatasync() correctly,
27727 ** then simply compile with -Dfdatasync=fdatasync
27728 */
27729 #if !defined(fdatasync)
27730 # define fdatasync fsync
27731 #endif
27732
27733 /*
27734 ** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
@@ -28015,11 +28019,11 @@
28019 ** file-control operation. Enlarge the database to nBytes in size
28020 ** (rounded up to the next chunk-size). If the database is already
28021 ** nBytes or larger, this routine is a no-op.
28022 */
28023 static int fcntlSizeHint(unixFile *pFile, i64 nByte){
28024 if( pFile->szChunk>0 ){
28025 i64 nSize; /* Required file size */
28026 struct stat buf; /* Used to hold return values of fstat() */
28027
28028 if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
28029
@@ -28210,15 +28214,13 @@
28214 */
28215 struct unixShm {
28216 unixShmNode *pShmNode; /* The underlying unixShmNode object */
28217 unixShm *pNext; /* Next unixShm with the same unixShmNode */
28218 u8 hasMutex; /* True if holding the unixShmNode mutex */
28219 u8 id; /* Id of this connection within its unixShmNode */
28220 u16 sharedMask; /* Mask of shared locks held */
28221 u16 exclMask; /* Mask of exclusive locks held */
 
 
 
28222 };
28223
28224 /*
28225 ** Constants used for locking
28226 */
@@ -31435,11 +31437,11 @@
31437 */
31438 #ifdef MEMORY_DEBUG
31439 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
31440 #endif
31441
31442 #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
31443 # ifndef SQLITE_DEBUG_OS_TRACE
31444 # define SQLITE_DEBUG_OS_TRACE 0
31445 # endif
31446 int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
31447 # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
@@ -32768,11 +32770,11 @@
32770 /* If the user has configured a chunk-size for this file, truncate the
32771 ** file so that it consists of an integer number of chunks (i.e. the
32772 ** actual file size after the operation may be larger than the requested
32773 ** size).
32774 */
32775 if( pFile->szChunk>0 ){
32776 nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
32777 }
32778
32779 /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
32780 if( seekWinFile(pFile, nByte) ){
@@ -32797,13 +32799,23 @@
32799
32800 /*
32801 ** Make sure all writes to a particular file are committed to disk.
32802 */
32803 static int winSync(sqlite3_file *id, int flags){
32804 #ifndef SQLITE_NO_SYNC
32805 /*
32806 ** Used only when SQLITE_NO_SYNC is not defined.
32807 */
32808 BOOL rc;
32809 #endif
32810 #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
32811 (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
32812 /*
32813 ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
32814 ** OSTRACE() macros.
32815 */
32816 winFile *pFile = (winFile*)id;
32817 #else
32818 UNUSED_PARAMETER(id);
32819 #endif
32820
32821 assert( pFile );
@@ -33155,22 +33167,24 @@
33167 case SQLITE_FCNTL_CHUNK_SIZE: {
33168 pFile->szChunk = *(int *)pArg;
33169 return SQLITE_OK;
33170 }
33171 case SQLITE_FCNTL_SIZE_HINT: {
33172 if( pFile->szChunk>0 ){
33173 sqlite3_int64 oldSz;
33174 int rc = winFileSize(id, &oldSz);
33175 if( rc==SQLITE_OK ){
33176 sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
33177 if( newSz>oldSz ){
33178 SimulateIOErrorBenign(1);
33179 rc = winTruncate(id, newSz);
33180 SimulateIOErrorBenign(0);
33181 }
33182 }
33183 return rc;
33184 }
33185 return SQLITE_OK;
33186 }
33187 case SQLITE_FCNTL_PERSIST_WAL: {
33188 int bPersist = *(int*)pArg;
33189 if( bPersist<0 ){
33190 *(int*)pArg = pFile->bPersistWal;
@@ -38136,12 +38150,10 @@
38150 u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
38151 u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
38152 u8 tempFile; /* zFilename is a temporary file */
38153 u8 readOnly; /* True for a read-only database */
38154 u8 memDb; /* True to inhibit all file I/O */
 
 
38155
38156 /**************************************************************************
38157 ** The following block contains those class members that change during
38158 ** routine opertion. Class members not in this block are either fixed
38159 ** when the pager is first created or else only change when there is a
@@ -38361,19 +38373,10 @@
38373 );
38374 assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
38375 assert( pagerUseWal(p)==0 );
38376 }
38377
 
 
 
 
 
 
 
 
 
38378 /* If changeCountDone is set, a RESERVED lock or greater must be held
38379 ** on the file.
38380 */
38381 assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
38382 assert( p->eLock!=PENDING_LOCK );
@@ -41701,11 +41704,10 @@
41704 ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1
41705 ** while in the error state, hence it is impossible for this routine to
41706 ** be called in the error state. Nevertheless, we include a NEVER()
41707 ** test for the error state as a safeguard against future changes.
41708 */
 
41709 if( NEVER(pPager->errCode) ) return SQLITE_OK;
41710 if( pPager->doNotSpill ) return SQLITE_OK;
41711 if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
41712 return SQLITE_OK;
41713 }
@@ -42073,16 +42075,10 @@
42075 }
42076 /* pPager->xBusyHandler = 0; */
42077 /* pPager->pBusyHandlerArg = 0; */
42078 pPager->xReiniter = xReinit;
42079 /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
 
 
 
 
 
 
42080
42081 *ppPager = pPager;
42082 return SQLITE_OK;
42083 }
42084
@@ -43623,21 +43619,10 @@
43619 */
43620 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
43621 return MEMDB;
43622 }
43623
 
 
 
 
 
 
 
 
 
 
 
43624 /*
43625 ** Check that there are at least nSavepoint savepoints open. If there are
43626 ** currently less than nSavepoints open, then open one or more savepoints
43627 ** to make up the difference. If the number of savepoints is already
43628 ** equal to nSavepoint, then this function is a no-op.
@@ -48924,22 +48909,25 @@
48909 int *pRes /* Write search results here */
48910 ){
48911 int rc; /* Status code */
48912 UnpackedRecord *pIdxKey; /* Unpacked index key */
48913 char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */
48914 char *pFree = 0;
48915
48916 if( pKey ){
48917 assert( nKey==(i64)(int)nKey );
48918 pIdxKey = sqlite3VdbeAllocUnpackedRecord(
48919 pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
48920 );
48921 if( pIdxKey==0 ) return SQLITE_NOMEM;
48922 sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
48923 }else{
48924 pIdxKey = 0;
48925 }
48926 rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
48927 if( pFree ){
48928 sqlite3DbFree(pCur->pKeyInfo->db, pFree);
48929 }
48930 return rc;
48931 }
48932
48933 /*
@@ -50002,26 +49990,15 @@
49990 assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
49991
49992 /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
49993 assert( (flags & BTREE_SINGLE)==0 || isTempDb );
49994
 
 
 
 
 
 
 
 
 
 
49995 if( db->flags & SQLITE_NoReadlock ){
49996 flags |= BTREE_NO_READLOCK;
49997 }
49998 if( isMemdb ){
49999 flags |= BTREE_MEMORY;
 
50000 }
50001 if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
50002 vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
50003 }
50004 p = sqlite3MallocZero(sizeof(Btree));
@@ -51022,15 +50999,16 @@
50999 for(i=0; i<nCell; i++){
51000 u8 *pCell = findCell(pPage, i);
51001 if( eType==PTRMAP_OVERFLOW1 ){
51002 CellInfo info;
51003 btreeParseCellPtr(pPage, pCell, &info);
51004 if( info.iOverflow
51005 && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
51006 && iFrom==get4byte(&pCell[info.iOverflow])
51007 ){
51008 put4byte(&pCell[info.iOverflow], iTo);
51009 break;
51010 }
51011 }else{
51012 if( get4byte(pCell)==iFrom ){
51013 put4byte(pCell, iTo);
51014 break;
@@ -53458,10 +53436,13 @@
53436 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
53437 btreeParseCellPtr(pPage, pCell, &info);
53438 if( info.iOverflow==0 ){
53439 return SQLITE_OK; /* No overflow pages. Return without doing anything */
53440 }
53441 if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
53442 return SQLITE_CORRUPT; /* Cell extends past end of page */
53443 }
53444 ovflPgno = get4byte(&pCell[info.iOverflow]);
53445 assert( pBt->usableSize > 4 );
53446 ovflPageSize = pBt->usableSize - 4;
53447 nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
53448 assert( ovflPgno==0 || nOvfl>0 );
@@ -55560,20 +55541,13 @@
55541 releasePage(pPage);
55542 }
55543 return rc;
55544 }
55545 SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
 
55546 int rc;
55547 sqlite3BtreeEnter(p);
55548 rc = btreeDropTable(p, iTable, piMoved);
 
 
 
 
 
 
55549 sqlite3BtreeLeave(p);
55550 return rc;
55551 }
55552
55553
@@ -58758,11 +58732,11 @@
58732 assert( p->nOp - i >= 3 );
58733 assert( pOp[-1].opcode==OP_Integer );
58734 n = pOp[-1].p1;
58735 if( n>nMaxArgs ) nMaxArgs = n;
58736 #endif
58737 }else if( opcode==OP_Next || opcode==OP_SorterNext ){
58738 pOp->p4.xAdvance = sqlite3BtreeNext;
58739 pOp->p4type = P4_ADVANCE;
58740 }else if( opcode==OP_Prev ){
58741 pOp->p4.xAdvance = sqlite3BtreePrevious;
58742 pOp->p4type = P4_ADVANCE;
@@ -58995,22 +58969,19 @@
58969 p->pNext = pVdbe->pProgram;
58970 pVdbe->pProgram = p;
58971 }
58972
58973 /*
58974 ** Change the opcode at addr into OP_Noop
58975 */
58976 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
58977 if( p->aOp ){
58978 VdbeOp *pOp = &p->aOp[addr];
58979 sqlite3 *db = p->db;
58980 freeP4(db, pOp->p4type, pOp->p4.p);
58981 memset(pOp, 0, sizeof(pOp[0]));
58982 pOp->opcode = OP_Noop;
 
 
 
58983 }
58984 }
58985
58986 /*
58987 ** Change the value of the P4 operand for a specific instruction.
@@ -59162,11 +59133,11 @@
59133 ** check the value of p->nOp-1 before continuing.
59134 */
59135 SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
59136 /* C89 specifies that the constant "dummy" will be initialized to all
59137 ** zeros, which is correct. MSVC generates a warning, nevertheless. */
59138 static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
59139 assert( p->magic==VDBE_MAGIC_INIT );
59140 if( addr<0 ){
59141 #ifdef SQLITE_OMIT_TRACE
59142 if( p->nOp==0 ) return (VdbeOp*)&dummy;
59143 #endif
@@ -61155,61 +61126,74 @@
61126 }
61127 }
61128 return 0;
61129 }
61130
61131 /*
61132 ** This routine is used to allocate sufficient space for an UnpackedRecord
61133 ** structure large enough to be used with sqlite3VdbeRecordUnpack() if
61134 ** the first argument is a pointer to KeyInfo structure pKeyInfo.
61135 **
61136 ** The space is either allocated using sqlite3DbMallocRaw() or from within
61137 ** the unaligned buffer passed via the second and third arguments (presumably
61138 ** stack space). If the former, then *ppFree is set to a pointer that should
61139 ** be eventually freed by the caller using sqlite3DbFree(). Or, if the
61140 ** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
61141 ** before returning.
61142 **
61143 ** If an OOM error occurs, NULL is returned.
61144 */
61145 SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
61146 KeyInfo *pKeyInfo, /* Description of the record */
61147 char *pSpace, /* Unaligned space available */
61148 int szSpace, /* Size of pSpace[] in bytes */
61149 char **ppFree /* OUT: Caller should free this pointer */
61150 ){
61151 UnpackedRecord *p; /* Unpacked record to return */
61152 int nOff; /* Increment pSpace by nOff to align it */
61153 int nByte; /* Number of bytes required for *p */
61154
61155 /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
 
 
 
 
 
 
 
 
61156 ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
61157 ** it by. If pSpace is already 8-byte aligned, nOff should be zero.
61158 */
61159 nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
 
 
61160 nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
61161 if( nByte>szSpace+nOff ){
61162 p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
61163 *ppFree = (char *)p;
61164 if( !p ) return 0;
61165 }else{
61166 p = (UnpackedRecord*)&pSpace[nOff];
61167 *ppFree = 0;
61168 }
61169
61170 p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
61171 p->pKeyInfo = pKeyInfo;
61172 p->nField = pKeyInfo->nField + 1;
61173 return p;
61174 }
61175
61176 /*
61177 ** Given the nKey-byte encoding of a record in pKey[], populate the
61178 ** UnpackedRecord structure indicated by the fourth argument with the
61179 ** contents of the decoded record.
61180 */
61181 SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
61182 KeyInfo *pKeyInfo, /* Information about the record format */
61183 int nKey, /* Size of the binary record */
61184 const void *pKey, /* The binary record */
61185 UnpackedRecord *p /* Populate this structure before returning. */
61186 ){
61187 const unsigned char *aKey = (const unsigned char *)pKey;
61188 int d;
61189 u32 idx; /* Offset in aKey[] to read from */
61190 u16 u; /* Unsigned loop counter */
61191 u32 szHdr;
61192 Mem *pMem = p->aMem;
61193
61194 p->flags = 0;
61195 assert( EIGHT_BYTE_ALIGNMENT(pMem) );
61196 idx = getVarint32(aKey, szHdr);
61197 d = szHdr;
61198 u = 0;
61199 while( idx<szHdr && u<p->nField && d<=nKey ){
@@ -61224,35 +61208,10 @@
61208 pMem++;
61209 u++;
61210 }
61211 assert( u<=pKeyInfo->nField + 1 );
61212 p->nField = u;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61213 }
61214
61215 /*
61216 ** This function compares the two table rows or index records
61217 ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
@@ -63871,55 +63830,59 @@
63830 Db *pDb;
63831 } aw;
63832 struct OP_OpenEphemeral_stack_vars {
63833 VdbeCursor *pCx;
63834 } ax;
63835 struct OP_SorterOpen_stack_vars {
63836 VdbeCursor *pCx;
63837 } ay;
63838 struct OP_OpenPseudo_stack_vars {
63839 VdbeCursor *pCx;
63840 } az;
63841 struct OP_SeekGt_stack_vars {
63842 int res;
63843 int oc;
63844 VdbeCursor *pC;
63845 UnpackedRecord r;
63846 int nField;
63847 i64 iKey; /* The rowid we are to seek to */
63848 } ba;
63849 struct OP_Seek_stack_vars {
63850 VdbeCursor *pC;
63851 } bb;
63852 struct OP_Found_stack_vars {
63853 int alreadyExists;
63854 VdbeCursor *pC;
63855 int res;
63856 char *pFree;
63857 UnpackedRecord *pIdxKey;
63858 UnpackedRecord r;
63859 char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
63860 } bc;
63861 struct OP_IsUnique_stack_vars {
63862 u16 ii;
63863 VdbeCursor *pCx;
63864 BtCursor *pCrsr;
63865 u16 nField;
63866 Mem *aMx;
63867 UnpackedRecord r; /* B-Tree index search key */
63868 i64 R; /* Rowid stored in register P3 */
63869 } bd;
63870 struct OP_NotExists_stack_vars {
63871 VdbeCursor *pC;
63872 BtCursor *pCrsr;
63873 int res;
63874 u64 iKey;
63875 } be;
63876 struct OP_NewRowid_stack_vars {
63877 i64 v; /* The new rowid */
63878 VdbeCursor *pC; /* Cursor of table to get the new rowid */
63879 int res; /* Result of an sqlite3BtreeLast() */
63880 int cnt; /* Counter to limit the number of searches */
63881 Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
63882 VdbeFrame *pFrame; /* Root frame of VDBE */
63883 } bf;
63884 struct OP_InsertInt_stack_vars {
63885 Mem *pData; /* MEM cell holding data for the record to be inserted */
63886 Mem *pKey; /* MEM cell holding key for the record */
63887 i64 iKey; /* The integer ROWID or key for the record to be inserted */
63888 VdbeCursor *pC; /* Cursor to table into which insert is written */
@@ -63926,154 +63889,161 @@
63889 int nZero; /* Number of zero-bytes to append */
63890 int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
63891 const char *zDb; /* database name - used by the update hook */
63892 const char *zTbl; /* Table name - used by the opdate hook */
63893 int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
63894 } bg;
63895 struct OP_Delete_stack_vars {
63896 i64 iKey;
63897 VdbeCursor *pC;
63898 } bh;
63899 struct OP_SorterCompare_stack_vars {
63900 VdbeCursor *pC;
63901 int res;
63902 } bi;
63903 struct OP_SorterData_stack_vars {
63904 VdbeCursor *pC;
63905 } bj;
63906 struct OP_RowData_stack_vars {
63907 VdbeCursor *pC;
63908 BtCursor *pCrsr;
63909 u32 n;
63910 i64 n64;
63911 } bk;
63912 struct OP_Rowid_stack_vars {
63913 VdbeCursor *pC;
63914 i64 v;
63915 sqlite3_vtab *pVtab;
63916 const sqlite3_module *pModule;
63917 } bl;
63918 struct OP_NullRow_stack_vars {
63919 VdbeCursor *pC;
63920 } bm;
63921 struct OP_Last_stack_vars {
63922 VdbeCursor *pC;
63923 BtCursor *pCrsr;
63924 int res;
63925 } bn;
63926 struct OP_Rewind_stack_vars {
63927 VdbeCursor *pC;
63928 BtCursor *pCrsr;
63929 int res;
63930 } bo;
63931 struct OP_Next_stack_vars {
63932 VdbeCursor *pC;
63933 int res;
63934 } bp;
63935 struct OP_IdxInsert_stack_vars {
63936 VdbeCursor *pC;
63937 BtCursor *pCrsr;
63938 int nKey;
63939 const char *zKey;
63940 } bq;
63941 struct OP_IdxDelete_stack_vars {
63942 VdbeCursor *pC;
63943 BtCursor *pCrsr;
63944 int res;
63945 UnpackedRecord r;
63946 } br;
63947 struct OP_IdxRowid_stack_vars {
63948 BtCursor *pCrsr;
63949 VdbeCursor *pC;
63950 i64 rowid;
63951 } bs;
63952 struct OP_IdxGE_stack_vars {
63953 VdbeCursor *pC;
63954 int res;
63955 UnpackedRecord r;
63956 } bt;
63957 struct OP_Destroy_stack_vars {
63958 int iMoved;
63959 int iCnt;
63960 Vdbe *pVdbe;
63961 int iDb;
63962 } bu;
63963 struct OP_Clear_stack_vars {
63964 int nChange;
63965 } bv;
63966 struct OP_CreateTable_stack_vars {
63967 int pgno;
63968 int flags;
63969 Db *pDb;
63970 } bw;
63971 struct OP_ParseSchema_stack_vars {
63972 int iDb;
63973 const char *zMaster;
63974 char *zSql;
63975 InitData initData;
63976 } bx;
63977 struct OP_IntegrityCk_stack_vars {
63978 int nRoot; /* Number of tables to check. (Number of root pages.) */
63979 int *aRoot; /* Array of rootpage numbers for tables to be checked */
63980 int j; /* Loop counter */
63981 int nErr; /* Number of errors reported */
63982 char *z; /* Text of the error report */
63983 Mem *pnErr; /* Register keeping track of errors remaining */
63984 } by;
63985 struct OP_RowSetRead_stack_vars {
63986 i64 val;
63987 } bz;
63988 struct OP_RowSetTest_stack_vars {
63989 int iSet;
63990 int exists;
63991 } ca;
63992 struct OP_Program_stack_vars {
63993 int nMem; /* Number of memory registers for sub-program */
63994 int nByte; /* Bytes of runtime space required for sub-program */
63995 Mem *pRt; /* Register to allocate runtime space */
63996 Mem *pMem; /* Used to iterate through memory cells */
63997 Mem *pEnd; /* Last memory cell in new array */
63998 VdbeFrame *pFrame; /* New vdbe frame to execute in */
63999 SubProgram *pProgram; /* Sub-program to execute */
64000 void *t; /* Token identifying trigger */
64001 } cb;
64002 struct OP_Param_stack_vars {
64003 VdbeFrame *pFrame;
64004 Mem *pIn;
64005 } cc;
64006 struct OP_MemMax_stack_vars {
64007 Mem *pIn1;
64008 VdbeFrame *pFrame;
64009 } cd;
64010 struct OP_AggStep_stack_vars {
64011 int n;
64012 int i;
64013 Mem *pMem;
64014 Mem *pRec;
64015 sqlite3_context ctx;
64016 sqlite3_value **apVal;
64017 } ce;
64018 struct OP_AggFinal_stack_vars {
64019 Mem *pMem;
64020 } cf;
64021 struct OP_Checkpoint_stack_vars {
64022 int i; /* Loop counter */
64023 int aRes[3]; /* Results */
64024 Mem *pMem; /* Write results here */
64025 } cg;
64026 struct OP_JournalMode_stack_vars {
64027 Btree *pBt; /* Btree to change journal mode of */
64028 Pager *pPager; /* Pager associated with pBt */
64029 int eNew; /* New journal mode */
64030 int eOld; /* The old journal mode */
64031 const char *zFilename; /* Name of database file for pPager */
64032 } ch;
64033 struct OP_IncrVacuum_stack_vars {
64034 Btree *pBt;
64035 } ci;
64036 struct OP_VBegin_stack_vars {
64037 VTable *pVTab;
64038 } cj;
64039 struct OP_VOpen_stack_vars {
64040 VdbeCursor *pCur;
64041 sqlite3_vtab_cursor *pVtabCursor;
64042 sqlite3_vtab *pVtab;
64043 sqlite3_module *pModule;
64044 } ck;
64045 struct OP_VFilter_stack_vars {
64046 int nArg;
64047 int iQuery;
64048 const sqlite3_module *pModule;
64049 Mem *pQuery;
@@ -64082,40 +64052,40 @@
64052 sqlite3_vtab *pVtab;
64053 VdbeCursor *pCur;
64054 int res;
64055 int i;
64056 Mem **apArg;
64057 } cl;
64058 struct OP_VColumn_stack_vars {
64059 sqlite3_vtab *pVtab;
64060 const sqlite3_module *pModule;
64061 Mem *pDest;
64062 sqlite3_context sContext;
64063 } cm;
64064 struct OP_VNext_stack_vars {
64065 sqlite3_vtab *pVtab;
64066 const sqlite3_module *pModule;
64067 int res;
64068 VdbeCursor *pCur;
64069 } cn;
64070 struct OP_VRename_stack_vars {
64071 sqlite3_vtab *pVtab;
64072 Mem *pName;
64073 } co;
64074 struct OP_VUpdate_stack_vars {
64075 sqlite3_vtab *pVtab;
64076 sqlite3_module *pModule;
64077 int nArg;
64078 int i;
64079 sqlite_int64 rowid;
64080 Mem **apArg;
64081 Mem *pX;
64082 } cp;
64083 struct OP_Trace_stack_vars {
64084 char *zTrace;
64085 char *z;
64086 } cq;
64087 } u;
64088 /* End automatically generated code
64089 ********************************************************************/
64090
64091 assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
@@ -65581,10 +65551,20 @@
65551 sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
65552 }
65553 break;
65554 }
65555
65556 /* Opcode: Once P1 P2 * * *
65557 **
65558 ** Jump to P2 if the value in register P1 is a not null or zero. If
65559 ** the value is NULL or zero, fall through and change the P1 register
65560 ** to an integer 1.
65561 **
65562 ** When P1 is not used otherwise in a program, this opcode falls through
65563 ** once and jumps on all subsequent invocations. It is the equivalent
65564 ** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
65565 */
65566 /* Opcode: If P1 P2 P3 * *
65567 **
65568 ** Jump to P2 if the value in register P1 is true. The value
65569 ** is considered true if it is numeric and non-zero. If the value
65570 ** in P1 is NULL then take the jump if P3 is true.
@@ -65593,10 +65573,11 @@
65573 **
65574 ** Jump to P2 if the value in register P1 is False. The value
65575 ** is considered true if it has a numeric value of zero. If the value
65576 ** in P1 is NULL then take the jump if P3 is true.
65577 */
65578 case OP_Once: /* jump, in1 */
65579 case OP_If: /* jump, in1 */
65580 case OP_IfNot: { /* jump, in1 */
65581 #if 0 /* local variables moved into u.al */
65582 int c;
65583 #endif /* local variables moved into u.al */
@@ -65611,10 +65592,16 @@
65592 #endif
65593 if( pOp->opcode==OP_IfNot ) u.al.c = !u.al.c;
65594 }
65595 if( u.al.c ){
65596 pc = pOp->p2-1;
65597 }else if( pOp->opcode==OP_Once ){
65598 assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
65599 memAboutToChange(p, pIn1);
65600 pIn1->flags = MEM_Int;
65601 pIn1->u.i = 1;
65602 REGISTER_TRACE(pOp->p1, pIn1);
65603 }
65604 break;
65605 }
65606
65607 /* Opcode: IsNull P1 P2 * * *
@@ -66746,17 +66733,10 @@
66733 ** This opcode works the same as OP_OpenEphemeral. It has a
66734 ** different name to distinguish its use. Tables created using
66735 ** by this opcode will be used for automatically created transient
66736 ** indices in joins.
66737 */
 
 
 
 
 
 
 
66738 case OP_OpenAutoindex:
66739 case OP_OpenEphemeral: {
66740 #if 0 /* local variables moved into u.ax */
66741 VdbeCursor *pCx;
66742 #endif /* local variables moved into u.ax */
@@ -66766,11 +66746,10 @@
66746 SQLITE_OPEN_EXCLUSIVE |
66747 SQLITE_OPEN_DELETEONCLOSE |
66748 SQLITE_OPEN_TRANSIENT_DB;
66749
66750 assert( pOp->p1>=0 );
 
66751 u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
66752 if( u.ax.pCx==0 ) goto no_mem;
66753 u.ax.pCx->nullRow = 1;
66754 rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
66755 BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
@@ -66800,14 +66779,33 @@
66779 u.ax.pCx->isTable = 1;
66780 }
66781 }
66782 u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
66783 u.ax.pCx->isIndex = !u.ax.pCx->isTable;
66784 break;
66785 }
66786
66787 /* Opcode: OpenSorter P1 P2 * P4 *
66788 **
66789 ** This opcode works like OP_OpenEphemeral except that it opens
66790 ** a transient index that is specifically designed to sort large
66791 ** tables using an external merge-sort algorithm.
66792 */
66793 case OP_SorterOpen: {
66794 #if 0 /* local variables moved into u.ay */
66795 VdbeCursor *pCx;
66796 #endif /* local variables moved into u.ay */
66797 #ifndef SQLITE_OMIT_MERGE_SORT
66798 u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
66799 if( u.ay.pCx==0 ) goto no_mem;
66800 u.ay.pCx->pKeyInfo = pOp->p4.pKeyInfo;
66801 u.ay.pCx->pKeyInfo->enc = ENC(p->db);
66802 u.ay.pCx->isSorter = 1;
66803 rc = sqlite3VdbeSorterInit(db, u.ay.pCx);
66804 #else
66805 pOp->opcode = OP_OpenEphemeral;
66806 pc--;
66807 #endif
66808 break;
66809 }
66810
66811 /* Opcode: OpenPseudo P1 P2 P3 * *
@@ -66824,21 +66822,21 @@
66822 **
66823 ** P3 is the number of fields in the records that will be stored by
66824 ** the pseudo-table.
66825 */
66826 case OP_OpenPseudo: {
66827 #if 0 /* local variables moved into u.az */
66828 VdbeCursor *pCx;
66829 #endif /* local variables moved into u.az */
66830
66831 assert( pOp->p1>=0 );
66832 u.az.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
66833 if( u.az.pCx==0 ) goto no_mem;
66834 u.az.pCx->nullRow = 1;
66835 u.az.pCx->pseudoTableReg = pOp->p2;
66836 u.az.pCx->isTable = 1;
66837 u.az.pCx->isIndex = 0;
66838 break;
66839 }
66840
66841 /* Opcode: Close P1 * * * *
66842 **
@@ -66906,39 +66904,39 @@
66904 */
66905 case OP_SeekLt: /* jump, in3 */
66906 case OP_SeekLe: /* jump, in3 */
66907 case OP_SeekGe: /* jump, in3 */
66908 case OP_SeekGt: { /* jump, in3 */
66909 #if 0 /* local variables moved into u.ba */
66910 int res;
66911 int oc;
66912 VdbeCursor *pC;
66913 UnpackedRecord r;
66914 int nField;
66915 i64 iKey; /* The rowid we are to seek to */
66916 #endif /* local variables moved into u.ba */
66917
66918 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
66919 assert( pOp->p2!=0 );
66920 u.ba.pC = p->apCsr[pOp->p1];
66921 assert( u.ba.pC!=0 );
66922 assert( u.ba.pC->pseudoTableReg==0 );
66923 assert( OP_SeekLe == OP_SeekLt+1 );
66924 assert( OP_SeekGe == OP_SeekLt+2 );
66925 assert( OP_SeekGt == OP_SeekLt+3 );
66926 assert( u.ba.pC->isOrdered );
66927 if( ALWAYS(u.ba.pC->pCursor!=0) ){
66928 u.ba.oc = pOp->opcode;
66929 u.ba.pC->nullRow = 0;
66930 if( u.ba.pC->isTable ){
66931 /* The input value in P3 might be of any type: integer, real, string,
66932 ** blob, or NULL. But it needs to be an integer before we can do
66933 ** the seek, so covert it. */
66934 pIn3 = &aMem[pOp->p3];
66935 applyNumericAffinity(pIn3);
66936 u.ba.iKey = sqlite3VdbeIntValue(pIn3);
66937 u.ba.pC->rowidIsValid = 0;
66938
66939 /* If the P3 value could not be converted into an integer without
66940 ** loss of information, then special processing is required... */
66941 if( (pIn3->flags & MEM_Int)==0 ){
66942 if( (pIn3->flags & MEM_Real)==0 ){
@@ -66949,105 +66947,105 @@
66947 }
66948 /* If we reach this point, then the P3 value must be a floating
66949 ** point number. */
66950 assert( (pIn3->flags & MEM_Real)!=0 );
66951
66952 if( u.ba.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.ba.iKey || pIn3->r>0) ){
66953 /* The P3 value is too large in magnitude to be expressed as an
66954 ** integer. */
66955 u.ba.res = 1;
66956 if( pIn3->r<0 ){
66957 if( u.ba.oc>=OP_SeekGe ){ assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
66958 rc = sqlite3BtreeFirst(u.ba.pC->pCursor, &u.ba.res);
66959 if( rc!=SQLITE_OK ) goto abort_due_to_error;
66960 }
66961 }else{
66962 if( u.ba.oc<=OP_SeekLe ){ assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
66963 rc = sqlite3BtreeLast(u.ba.pC->pCursor, &u.ba.res);
66964 if( rc!=SQLITE_OK ) goto abort_due_to_error;
66965 }
66966 }
66967 if( u.ba.res ){
66968 pc = pOp->p2 - 1;
66969 }
66970 break;
66971 }else if( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekGe ){
66972 /* Use the ceiling() function to convert real->int */
66973 if( pIn3->r > (double)u.ba.iKey ) u.ba.iKey++;
66974 }else{
66975 /* Use the floor() function to convert real->int */
66976 assert( u.ba.oc==OP_SeekLe || u.ba.oc==OP_SeekGt );
66977 if( pIn3->r < (double)u.ba.iKey ) u.ba.iKey--;
66978 }
66979 }
66980 rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, 0, (u64)u.ba.iKey, 0, &u.ba.res);
66981 if( rc!=SQLITE_OK ){
66982 goto abort_due_to_error;
66983 }
66984 if( u.ba.res==0 ){
66985 u.ba.pC->rowidIsValid = 1;
66986 u.ba.pC->lastRowid = u.ba.iKey;
66987 }
66988 }else{
66989 u.ba.nField = pOp->p4.i;
66990 assert( pOp->p4type==P4_INT32 );
66991 assert( u.ba.nField>0 );
66992 u.ba.r.pKeyInfo = u.ba.pC->pKeyInfo;
66993 u.ba.r.nField = (u16)u.ba.nField;
66994
66995 /* The next line of code computes as follows, only faster:
66996 ** if( u.ba.oc==OP_SeekGt || u.ba.oc==OP_SeekLe ){
66997 ** u.ba.r.flags = UNPACKED_INCRKEY;
66998 ** }else{
66999 ** u.ba.r.flags = 0;
67000 ** }
67001 */
67002 u.ba.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.ba.oc - OP_SeekLt)));
67003 assert( u.ba.oc!=OP_SeekGt || u.ba.r.flags==UNPACKED_INCRKEY );
67004 assert( u.ba.oc!=OP_SeekLe || u.ba.r.flags==UNPACKED_INCRKEY );
67005 assert( u.ba.oc!=OP_SeekGe || u.ba.r.flags==0 );
67006 assert( u.ba.oc!=OP_SeekLt || u.ba.r.flags==0 );
67007
67008 u.ba.r.aMem = &aMem[pOp->p3];
67009 #ifdef SQLITE_DEBUG
67010 { int i; for(i=0; i<u.ba.r.nField; i++) assert( memIsValid(&u.ba.r.aMem[i]) ); }
67011 #endif
67012 ExpandBlob(u.ba.r.aMem);
67013 rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, &u.ba.r, 0, 0, &u.ba.res);
67014 if( rc!=SQLITE_OK ){
67015 goto abort_due_to_error;
67016 }
67017 u.ba.pC->rowidIsValid = 0;
67018 }
67019 u.ba.pC->deferredMoveto = 0;
67020 u.ba.pC->cacheStatus = CACHE_STALE;
67021 #ifdef SQLITE_TEST
67022 sqlite3_search_count++;
67023 #endif
67024 if( u.ba.oc>=OP_SeekGe ){ assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
67025 if( u.ba.res<0 || (u.ba.res==0 && u.ba.oc==OP_SeekGt) ){
67026 rc = sqlite3BtreeNext(u.ba.pC->pCursor, &u.ba.res);
67027 if( rc!=SQLITE_OK ) goto abort_due_to_error;
67028 u.ba.pC->rowidIsValid = 0;
67029 }else{
67030 u.ba.res = 0;
67031 }
67032 }else{
67033 assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
67034 if( u.ba.res>0 || (u.ba.res==0 && u.ba.oc==OP_SeekLt) ){
67035 rc = sqlite3BtreePrevious(u.ba.pC->pCursor, &u.ba.res);
67036 if( rc!=SQLITE_OK ) goto abort_due_to_error;
67037 u.ba.pC->rowidIsValid = 0;
67038 }else{
67039 /* u.ba.res might be negative because the table is empty. Check to
67040 ** see if this is the case.
67041 */
67042 u.ba.res = sqlite3BtreeEof(u.ba.pC->pCursor);
67043 }
67044 }
67045 assert( pOp->p2>0 );
67046 if( u.ba.res ){
67047 pc = pOp->p2 - 1;
67048 }
67049 }else{
67050 /* This happens when attempting to open the sqlite3_master table
67051 ** for read access returns SQLITE_EMPTY. In this case always
@@ -67066,24 +67064,24 @@
67064 ** This is actually a deferred seek. Nothing actually happens until
67065 ** the cursor is used to read a record. That way, if no reads
67066 ** occur, no unnecessary I/O happens.
67067 */
67068 case OP_Seek: { /* in2 */
67069 #if 0 /* local variables moved into u.bb */
67070 VdbeCursor *pC;
67071 #endif /* local variables moved into u.bb */
67072
67073 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67074 u.bb.pC = p->apCsr[pOp->p1];
67075 assert( u.bb.pC!=0 );
67076 if( ALWAYS(u.bb.pC->pCursor!=0) ){
67077 assert( u.bb.pC->isTable );
67078 u.bb.pC->nullRow = 0;
67079 pIn2 = &aMem[pOp->p2];
67080 u.bb.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
67081 u.bb.pC->rowidIsValid = 0;
67082 u.bb.pC->deferredMoveto = 1;
67083 }
67084 break;
67085 }
67086
67087
@@ -67111,66 +67109,67 @@
67109 **
67110 ** See also: Found, NotExists, IsUnique
67111 */
67112 case OP_NotFound: /* jump, in3 */
67113 case OP_Found: { /* jump, in3 */
67114 #if 0 /* local variables moved into u.bc */
67115 int alreadyExists;
67116 VdbeCursor *pC;
67117 int res;
67118 char *pFree;
67119 UnpackedRecord *pIdxKey;
67120 UnpackedRecord r;
67121 char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
67122 #endif /* local variables moved into u.bc */
67123
67124 #ifdef SQLITE_TEST
67125 sqlite3_found_count++;
67126 #endif
67127
67128 u.bc.alreadyExists = 0;
67129 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67130 assert( pOp->p4type==P4_INT32 );
67131 u.bc.pC = p->apCsr[pOp->p1];
67132 assert( u.bc.pC!=0 );
67133 pIn3 = &aMem[pOp->p3];
67134 if( ALWAYS(u.bc.pC->pCursor!=0) ){
67135
67136 assert( u.bc.pC->isTable==0 );
67137 if( pOp->p4.i>0 ){
67138 u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
67139 u.bc.r.nField = (u16)pOp->p4.i;
67140 u.bc.r.aMem = pIn3;
67141 #ifdef SQLITE_DEBUG
67142 { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
67143 #endif
67144 u.bc.r.flags = UNPACKED_PREFIX_MATCH;
67145 u.bc.pIdxKey = &u.bc.r;
67146 }else{
67147 u.bc.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
67148 u.bc.pC->pKeyInfo, u.bc.aTempRec, sizeof(u.bc.aTempRec), &u.bc.pFree
67149 );
67150 if( u.bc.pIdxKey==0 ) goto no_mem;
67151 assert( pIn3->flags & MEM_Blob );
67152 assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
67153 sqlite3VdbeRecordUnpack(u.bc.pC->pKeyInfo, pIn3->n, pIn3->z, u.bc.pIdxKey);
67154 u.bc.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
67155 }
67156 rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, u.bc.pIdxKey, 0, 0, &u.bc.res);
 
 
 
 
67157 if( pOp->p4.i==0 ){
67158 sqlite3DbFree(db, u.bc.pFree);
67159 }
67160 if( rc!=SQLITE_OK ){
67161 break;
67162 }
67163 u.bc.alreadyExists = (u.bc.res==0);
67164 u.bc.pC->deferredMoveto = 0;
67165 u.bc.pC->cacheStatus = CACHE_STALE;
67166 }
67167 if( pOp->opcode==OP_Found ){
67168 if( u.bc.alreadyExists ) pc = pOp->p2 - 1;
67169 }else{
67170 if( !u.bc.alreadyExists ) pc = pOp->p2 - 1;
67171 }
67172 break;
67173 }
67174
67175 /* Opcode: IsUnique P1 P2 P3 P4 *
@@ -67198,67 +67197,67 @@
67197 ** instruction.
67198 **
67199 ** See also: NotFound, NotExists, Found
67200 */
67201 case OP_IsUnique: { /* jump, in3 */
67202 #if 0 /* local variables moved into u.bd */
67203 u16 ii;
67204 VdbeCursor *pCx;
67205 BtCursor *pCrsr;
67206 u16 nField;
67207 Mem *aMx;
67208 UnpackedRecord r; /* B-Tree index search key */
67209 i64 R; /* Rowid stored in register P3 */
67210 #endif /* local variables moved into u.bd */
67211
67212 pIn3 = &aMem[pOp->p3];
67213 u.bd.aMx = &aMem[pOp->p4.i];
67214 /* Assert that the values of parameters P1 and P4 are in range. */
67215 assert( pOp->p4type==P4_INT32 );
67216 assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
67217 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67218
67219 /* Find the index cursor. */
67220 u.bd.pCx = p->apCsr[pOp->p1];
67221 assert( u.bd.pCx->deferredMoveto==0 );
67222 u.bd.pCx->seekResult = 0;
67223 u.bd.pCx->cacheStatus = CACHE_STALE;
67224 u.bd.pCrsr = u.bd.pCx->pCursor;
67225
67226 /* If any of the values are NULL, take the jump. */
67227 u.bd.nField = u.bd.pCx->pKeyInfo->nField;
67228 for(u.bd.ii=0; u.bd.ii<u.bd.nField; u.bd.ii++){
67229 if( u.bd.aMx[u.bd.ii].flags & MEM_Null ){
67230 pc = pOp->p2 - 1;
67231 u.bd.pCrsr = 0;
67232 break;
67233 }
67234 }
67235 assert( (u.bd.aMx[u.bd.nField].flags & MEM_Null)==0 );
67236
67237 if( u.bd.pCrsr!=0 ){
67238 /* Populate the index search key. */
67239 u.bd.r.pKeyInfo = u.bd.pCx->pKeyInfo;
67240 u.bd.r.nField = u.bd.nField + 1;
67241 u.bd.r.flags = UNPACKED_PREFIX_SEARCH;
67242 u.bd.r.aMem = u.bd.aMx;
67243 #ifdef SQLITE_DEBUG
67244 { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
67245 #endif
67246
67247 /* Extract the value of u.bd.R from register P3. */
67248 sqlite3VdbeMemIntegerify(pIn3);
67249 u.bd.R = pIn3->u.i;
67250
67251 /* Search the B-Tree index. If no conflicting record is found, jump
67252 ** to P2. Otherwise, copy the rowid of the conflicting record to
67253 ** register P3 and fall through to the next instruction. */
67254 rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, &u.bd.r, 0, 0, &u.bd.pCx->seekResult);
67255 if( (u.bd.r.flags & UNPACKED_PREFIX_SEARCH) || u.bd.r.rowid==u.bd.R ){
67256 pc = pOp->p2 - 1;
67257 }else{
67258 pIn3->u.i = u.bd.r.rowid;
67259 }
67260 }
67261 break;
67262 }
67263
@@ -67275,46 +67274,46 @@
67274 ** P1 is an index.
67275 **
67276 ** See also: Found, NotFound, IsUnique
67277 */
67278 case OP_NotExists: { /* jump, in3 */
67279 #if 0 /* local variables moved into u.be */
67280 VdbeCursor *pC;
67281 BtCursor *pCrsr;
67282 int res;
67283 u64 iKey;
67284 #endif /* local variables moved into u.be */
67285
67286 pIn3 = &aMem[pOp->p3];
67287 assert( pIn3->flags & MEM_Int );
67288 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67289 u.be.pC = p->apCsr[pOp->p1];
67290 assert( u.be.pC!=0 );
67291 assert( u.be.pC->isTable );
67292 assert( u.be.pC->pseudoTableReg==0 );
67293 u.be.pCrsr = u.be.pC->pCursor;
67294 if( ALWAYS(u.be.pCrsr!=0) ){
67295 u.be.res = 0;
67296 u.be.iKey = pIn3->u.i;
67297 rc = sqlite3BtreeMovetoUnpacked(u.be.pCrsr, 0, u.be.iKey, 0, &u.be.res);
67298 u.be.pC->lastRowid = pIn3->u.i;
67299 u.be.pC->rowidIsValid = u.be.res==0 ?1:0;
67300 u.be.pC->nullRow = 0;
67301 u.be.pC->cacheStatus = CACHE_STALE;
67302 u.be.pC->deferredMoveto = 0;
67303 if( u.be.res!=0 ){
67304 pc = pOp->p2 - 1;
67305 assert( u.be.pC->rowidIsValid==0 );
67306 }
67307 u.be.pC->seekResult = u.be.res;
67308 }else{
67309 /* This happens when an attempt to open a read cursor on the
67310 ** sqlite_master table returns SQLITE_EMPTY.
67311 */
67312 pc = pOp->p2 - 1;
67313 assert( u.be.pC->rowidIsValid==0 );
67314 u.be.pC->seekResult = 0;
67315 }
67316 break;
67317 }
67318
67319 /* Opcode: Sequence P1 P2 * * *
@@ -67345,25 +67344,25 @@
67344 ** an SQLITE_FULL error is generated. The P3 register is updated with the '
67345 ** generated record number. This P3 mechanism is used to help implement the
67346 ** AUTOINCREMENT feature.
67347 */
67348 case OP_NewRowid: { /* out2-prerelease */
67349 #if 0 /* local variables moved into u.bf */
67350 i64 v; /* The new rowid */
67351 VdbeCursor *pC; /* Cursor of table to get the new rowid */
67352 int res; /* Result of an sqlite3BtreeLast() */
67353 int cnt; /* Counter to limit the number of searches */
67354 Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
67355 VdbeFrame *pFrame; /* Root frame of VDBE */
67356 #endif /* local variables moved into u.bf */
67357
67358 u.bf.v = 0;
67359 u.bf.res = 0;
67360 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67361 u.bf.pC = p->apCsr[pOp->p1];
67362 assert( u.bf.pC!=0 );
67363 if( NEVER(u.bf.pC->pCursor==0) ){
67364 /* The zero initialization above is all that is needed */
67365 }else{
67366 /* The next rowid or record number (different terms for the same
67367 ** thing) is obtained in a two-step algorithm.
67368 **
@@ -67375,11 +67374,11 @@
67374 ** The second algorithm is to select a rowid at random and see if
67375 ** it already exists in the table. If it does not exist, we have
67376 ** succeeded. If the random rowid does exist, we select a new one
67377 ** and try again, up to 100 times.
67378 */
67379 assert( u.bf.pC->isTable );
67380
67381 #ifdef SQLITE_32BIT_ROWID
67382 # define MAX_ROWID 0x7fffffff
67383 #else
67384 /* Some compilers complain about constants of the form 0x7fffffffffffffff.
@@ -67387,101 +67386,101 @@
67386 ** to provide the constant while making all compilers happy.
67387 */
67388 # define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
67389 #endif
67390
67391 if( !u.bf.pC->useRandomRowid ){
67392 u.bf.v = sqlite3BtreeGetCachedRowid(u.bf.pC->pCursor);
67393 if( u.bf.v==0 ){
67394 rc = sqlite3BtreeLast(u.bf.pC->pCursor, &u.bf.res);
67395 if( rc!=SQLITE_OK ){
67396 goto abort_due_to_error;
67397 }
67398 if( u.bf.res ){
67399 u.bf.v = 1; /* IMP: R-61914-48074 */
67400 }else{
67401 assert( sqlite3BtreeCursorIsValid(u.bf.pC->pCursor) );
67402 rc = sqlite3BtreeKeySize(u.bf.pC->pCursor, &u.bf.v);
67403 assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
67404 if( u.bf.v==MAX_ROWID ){
67405 u.bf.pC->useRandomRowid = 1;
67406 }else{
67407 u.bf.v++; /* IMP: R-29538-34987 */
67408 }
67409 }
67410 }
67411
67412 #ifndef SQLITE_OMIT_AUTOINCREMENT
67413 if( pOp->p3 ){
67414 /* Assert that P3 is a valid memory cell. */
67415 assert( pOp->p3>0 );
67416 if( p->pFrame ){
67417 for(u.bf.pFrame=p->pFrame; u.bf.pFrame->pParent; u.bf.pFrame=u.bf.pFrame->pParent);
67418 /* Assert that P3 is a valid memory cell. */
67419 assert( pOp->p3<=u.bf.pFrame->nMem );
67420 u.bf.pMem = &u.bf.pFrame->aMem[pOp->p3];
67421 }else{
67422 /* Assert that P3 is a valid memory cell. */
67423 assert( pOp->p3<=p->nMem );
67424 u.bf.pMem = &aMem[pOp->p3];
67425 memAboutToChange(p, u.bf.pMem);
67426 }
67427 assert( memIsValid(u.bf.pMem) );
67428
67429 REGISTER_TRACE(pOp->p3, u.bf.pMem);
67430 sqlite3VdbeMemIntegerify(u.bf.pMem);
67431 assert( (u.bf.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
67432 if( u.bf.pMem->u.i==MAX_ROWID || u.bf.pC->useRandomRowid ){
67433 rc = SQLITE_FULL; /* IMP: R-12275-61338 */
67434 goto abort_due_to_error;
67435 }
67436 if( u.bf.v<u.bf.pMem->u.i+1 ){
67437 u.bf.v = u.bf.pMem->u.i + 1;
67438 }
67439 u.bf.pMem->u.i = u.bf.v;
67440 }
67441 #endif
67442
67443 sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, u.bf.v<MAX_ROWID ? u.bf.v+1 : 0);
67444 }
67445 if( u.bf.pC->useRandomRowid ){
67446 /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
67447 ** largest possible integer (9223372036854775807) then the database
67448 ** engine starts picking positive candidate ROWIDs at random until
67449 ** it finds one that is not previously used. */
67450 assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
67451 ** an AUTOINCREMENT table. */
67452 /* on the first attempt, simply do one more than previous */
67453 u.bf.v = lastRowid;
67454 u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
67455 u.bf.v++; /* ensure non-zero */
67456 u.bf.cnt = 0;
67457 while( ((rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, 0, (u64)u.bf.v,
67458 0, &u.bf.res))==SQLITE_OK)
67459 && (u.bf.res==0)
67460 && (++u.bf.cnt<100)){
67461 /* collision - try another random rowid */
67462 sqlite3_randomness(sizeof(u.bf.v), &u.bf.v);
67463 if( u.bf.cnt<5 ){
67464 /* try "small" random rowids for the initial attempts */
67465 u.bf.v &= 0xffffff;
67466 }else{
67467 u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
67468 }
67469 u.bf.v++; /* ensure non-zero */
67470 }
67471 if( rc==SQLITE_OK && u.bf.res==0 ){
67472 rc = SQLITE_FULL; /* IMP: R-38219-53002 */
67473 goto abort_due_to_error;
67474 }
67475 assert( u.bf.v>0 ); /* EV: R-40812-03570 */
67476 }
67477 u.bf.pC->rowidIsValid = 0;
67478 u.bf.pC->deferredMoveto = 0;
67479 u.bf.pC->cacheStatus = CACHE_STALE;
67480 }
67481 pOut->u.i = u.bf.v;
67482 break;
67483 }
67484
67485 /* Opcode: Insert P1 P2 P3 P4 P5
67486 **
@@ -67527,74 +67526,74 @@
67526 ** This works exactly like OP_Insert except that the key is the
67527 ** integer value P3, not the value of the integer stored in register P3.
67528 */
67529 case OP_Insert:
67530 case OP_InsertInt: {
67531 #if 0 /* local variables moved into u.bg */
67532 Mem *pData; /* MEM cell holding data for the record to be inserted */
67533 Mem *pKey; /* MEM cell holding key for the record */
67534 i64 iKey; /* The integer ROWID or key for the record to be inserted */
67535 VdbeCursor *pC; /* Cursor to table into which insert is written */
67536 int nZero; /* Number of zero-bytes to append */
67537 int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
67538 const char *zDb; /* database name - used by the update hook */
67539 const char *zTbl; /* Table name - used by the opdate hook */
67540 int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
67541 #endif /* local variables moved into u.bg */
67542
67543 u.bg.pData = &aMem[pOp->p2];
67544 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67545 assert( memIsValid(u.bg.pData) );
67546 u.bg.pC = p->apCsr[pOp->p1];
67547 assert( u.bg.pC!=0 );
67548 assert( u.bg.pC->pCursor!=0 );
67549 assert( u.bg.pC->pseudoTableReg==0 );
67550 assert( u.bg.pC->isTable );
67551 REGISTER_TRACE(pOp->p2, u.bg.pData);
67552
67553 if( pOp->opcode==OP_Insert ){
67554 u.bg.pKey = &aMem[pOp->p3];
67555 assert( u.bg.pKey->flags & MEM_Int );
67556 assert( memIsValid(u.bg.pKey) );
67557 REGISTER_TRACE(pOp->p3, u.bg.pKey);
67558 u.bg.iKey = u.bg.pKey->u.i;
67559 }else{
67560 assert( pOp->opcode==OP_InsertInt );
67561 u.bg.iKey = pOp->p3;
67562 }
67563
67564 if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
67565 if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bg.iKey;
67566 if( u.bg.pData->flags & MEM_Null ){
67567 u.bg.pData->z = 0;
67568 u.bg.pData->n = 0;
67569 }else{
67570 assert( u.bg.pData->flags & (MEM_Blob|MEM_Str) );
67571 }
67572 u.bg.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bg.pC->seekResult : 0);
67573 if( u.bg.pData->flags & MEM_Zero ){
67574 u.bg.nZero = u.bg.pData->u.nZero;
67575 }else{
67576 u.bg.nZero = 0;
67577 }
67578 sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
67579 rc = sqlite3BtreeInsert(u.bg.pC->pCursor, 0, u.bg.iKey,
67580 u.bg.pData->z, u.bg.pData->n, u.bg.nZero,
67581 pOp->p5 & OPFLAG_APPEND, u.bg.seekResult
67582 );
67583 u.bg.pC->rowidIsValid = 0;
67584 u.bg.pC->deferredMoveto = 0;
67585 u.bg.pC->cacheStatus = CACHE_STALE;
67586
67587 /* Invoke the update-hook if required. */
67588 if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
67589 u.bg.zDb = db->aDb[u.bg.pC->iDb].zName;
67590 u.bg.zTbl = pOp->p4.z;
67591 u.bg.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
67592 assert( u.bg.pC->isTable );
67593 db->xUpdateCallback(db->pUpdateArg, u.bg.op, u.bg.zDb, u.bg.zTbl, u.bg.iKey);
67594 assert( u.bg.pC->iDb>=0 );
67595 }
67596 break;
67597 }
67598
67599 /* Opcode: Delete P1 P2 * P4 *
@@ -67616,51 +67615,51 @@
67615 ** pointing to. The update hook will be invoked, if it exists.
67616 ** If P4 is not NULL then the P1 cursor must have been positioned
67617 ** using OP_NotFound prior to invoking this opcode.
67618 */
67619 case OP_Delete: {
67620 #if 0 /* local variables moved into u.bh */
67621 i64 iKey;
67622 VdbeCursor *pC;
67623 #endif /* local variables moved into u.bh */
67624
67625 u.bh.iKey = 0;
67626 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67627 u.bh.pC = p->apCsr[pOp->p1];
67628 assert( u.bh.pC!=0 );
67629 assert( u.bh.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
67630
67631 /* If the update-hook will be invoked, set u.bh.iKey to the rowid of the
67632 ** row being deleted.
67633 */
67634 if( db->xUpdateCallback && pOp->p4.z ){
67635 assert( u.bh.pC->isTable );
67636 assert( u.bh.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
67637 u.bh.iKey = u.bh.pC->lastRowid;
67638 }
67639
67640 /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
67641 ** OP_Column on the same table without any intervening operations that
67642 ** might move or invalidate the cursor. Hence cursor u.bh.pC is always pointing
67643 ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
67644 ** below is always a no-op and cannot fail. We will run it anyhow, though,
67645 ** to guard against future changes to the code generator.
67646 **/
67647 assert( u.bh.pC->deferredMoveto==0 );
67648 rc = sqlite3VdbeCursorMoveto(u.bh.pC);
67649 if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
67650
67651 sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
67652 rc = sqlite3BtreeDelete(u.bh.pC->pCursor);
67653 u.bh.pC->cacheStatus = CACHE_STALE;
67654
67655 /* Invoke the update-hook if required. */
67656 if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
67657 const char *zDb = db->aDb[u.bh.pC->iDb].zName;
67658 const char *zTbl = pOp->p4.z;
67659 db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bh.iKey);
67660 assert( u.bh.pC->iDb>=0 );
67661 }
67662 if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
67663 break;
67664 }
67665 /* Opcode: ResetCount * * * * *
@@ -67673,10 +67672,53 @@
67672 case OP_ResetCount: {
67673 sqlite3VdbeSetChanges(db, p->nChange);
67674 p->nChange = 0;
67675 break;
67676 }
67677
67678 /* Opcode: SorterCompare P1 P2 P3
67679 **
67680 ** P1 is a sorter cursor. This instruction compares the record blob in
67681 ** register P3 with the entry that the sorter cursor currently points to.
67682 ** If, excluding the rowid fields at the end, the two records are a match,
67683 ** fall through to the next instruction. Otherwise, jump to instruction P2.
67684 */
67685 case OP_SorterCompare: {
67686 #if 0 /* local variables moved into u.bi */
67687 VdbeCursor *pC;
67688 int res;
67689 #endif /* local variables moved into u.bi */
67690
67691 u.bi.pC = p->apCsr[pOp->p1];
67692 assert( isSorter(u.bi.pC) );
67693 pIn3 = &aMem[pOp->p3];
67694 rc = sqlite3VdbeSorterCompare(u.bi.pC, pIn3, &u.bi.res);
67695 if( u.bi.res ){
67696 pc = pOp->p2-1;
67697 }
67698 break;
67699 };
67700
67701 /* Opcode: SorterData P1 P2 * * *
67702 **
67703 ** Write into register P2 the current sorter data for sorter cursor P1.
67704 */
67705 case OP_SorterData: {
67706 #if 0 /* local variables moved into u.bj */
67707 VdbeCursor *pC;
67708 #endif /* local variables moved into u.bj */
67709 #ifndef SQLITE_OMIT_MERGE_SORT
67710 pOut = &aMem[pOp->p2];
67711 u.bj.pC = p->apCsr[pOp->p1];
67712 assert( u.bj.pC->isSorter );
67713 rc = sqlite3VdbeSorterRowkey(u.bj.pC, pOut);
67714 #else
67715 pOp->opcode = OP_RowKey;
67716 pc--;
67717 #endif
67718 break;
67719 }
67720
67721 /* Opcode: RowData P1 P2 * * *
67722 **
67723 ** Write into register P2 the complete row data for cursor P1.
67724 ** There is no interpretation of the data.
@@ -67696,72 +67738,67 @@
67738 ** If the P1 cursor must be pointing to a valid row (not a NULL row)
67739 ** of a real table, not a pseudo-table.
67740 */
67741 case OP_RowKey:
67742 case OP_RowData: {
67743 #if 0 /* local variables moved into u.bk */
67744 VdbeCursor *pC;
67745 BtCursor *pCrsr;
67746 u32 n;
67747 i64 n64;
67748 #endif /* local variables moved into u.bk */
67749
67750 pOut = &aMem[pOp->p2];
67751 memAboutToChange(p, pOut);
67752
67753 /* Note that RowKey and RowData are really exactly the same instruction */
67754 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67755 u.bk.pC = p->apCsr[pOp->p1];
67756 assert( u.bk.pC->isSorter==0 );
67757 assert( u.bk.pC->isTable || pOp->opcode!=OP_RowData );
67758 assert( u.bk.pC->isIndex || pOp->opcode==OP_RowData );
67759 assert( u.bk.pC!=0 );
67760 assert( u.bk.pC->nullRow==0 );
67761 assert( u.bk.pC->pseudoTableReg==0 );
67762 assert( !u.bk.pC->isSorter );
67763 assert( u.bk.pC->pCursor!=0 );
67764 u.bk.pCrsr = u.bk.pC->pCursor;
67765 assert( sqlite3BtreeCursorIsValid(u.bk.pCrsr) );
 
 
 
 
 
67766
67767 /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
67768 ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
67769 ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always
67770 ** a no-op and can never fail. But we leave it in place as a safety.
67771 */
67772 assert( u.bk.pC->deferredMoveto==0 );
67773 rc = sqlite3VdbeCursorMoveto(u.bk.pC);
67774 if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
67775
67776 if( u.bk.pC->isIndex ){
67777 assert( !u.bk.pC->isTable );
67778 rc = sqlite3BtreeKeySize(u.bk.pCrsr, &u.bk.n64);
67779 assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
67780 if( u.bk.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
67781 goto too_big;
67782 }
67783 u.bk.n = (u32)u.bk.n64;
67784 }else{
67785 rc = sqlite3BtreeDataSize(u.bk.pCrsr, &u.bk.n);
67786 assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
67787 if( u.bk.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
67788 goto too_big;
67789 }
67790 }
67791 if( sqlite3VdbeMemGrow(pOut, u.bk.n, 0) ){
67792 goto no_mem;
67793 }
67794 pOut->n = u.bk.n;
67795 MemSetTypeFlag(pOut, MEM_Blob);
67796 if( u.bk.pC->isIndex ){
67797 rc = sqlite3BtreeKey(u.bk.pCrsr, 0, u.bk.n, pOut->z);
67798 }else{
67799 rc = sqlite3BtreeData(u.bk.pCrsr, 0, u.bk.n, pOut->z);
67800 }
67801 pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
67802 UPDATE_MAX_BLOBSIZE(pOut);
67803 break;
67804 }
@@ -67774,46 +67811,46 @@
67811 ** P1 can be either an ordinary table or a virtual table. There used to
67812 ** be a separate OP_VRowid opcode for use with virtual tables, but this
67813 ** one opcode now works for both table types.
67814 */
67815 case OP_Rowid: { /* out2-prerelease */
67816 #if 0 /* local variables moved into u.bl */
67817 VdbeCursor *pC;
67818 i64 v;
67819 sqlite3_vtab *pVtab;
67820 const sqlite3_module *pModule;
67821 #endif /* local variables moved into u.bl */
67822
67823 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67824 u.bl.pC = p->apCsr[pOp->p1];
67825 assert( u.bl.pC!=0 );
67826 assert( u.bl.pC->pseudoTableReg==0 );
67827 if( u.bl.pC->nullRow ){
67828 pOut->flags = MEM_Null;
67829 break;
67830 }else if( u.bl.pC->deferredMoveto ){
67831 u.bl.v = u.bl.pC->movetoTarget;
67832 #ifndef SQLITE_OMIT_VIRTUALTABLE
67833 }else if( u.bl.pC->pVtabCursor ){
67834 u.bl.pVtab = u.bl.pC->pVtabCursor->pVtab;
67835 u.bl.pModule = u.bl.pVtab->pModule;
67836 assert( u.bl.pModule->xRowid );
67837 rc = u.bl.pModule->xRowid(u.bl.pC->pVtabCursor, &u.bl.v);
67838 importVtabErrMsg(p, u.bl.pVtab);
67839 #endif /* SQLITE_OMIT_VIRTUALTABLE */
67840 }else{
67841 assert( u.bl.pC->pCursor!=0 );
67842 rc = sqlite3VdbeCursorMoveto(u.bl.pC);
67843 if( rc ) goto abort_due_to_error;
67844 if( u.bl.pC->rowidIsValid ){
67845 u.bl.v = u.bl.pC->lastRowid;
67846 }else{
67847 rc = sqlite3BtreeKeySize(u.bl.pC->pCursor, &u.bl.v);
67848 assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */
67849 }
67850 }
67851 pOut->u.i = u.bl.v;
67852 break;
67853 }
67854
67855 /* Opcode: NullRow P1 * * * *
67856 **
@@ -67820,22 +67857,22 @@
67857 ** Move the cursor P1 to a null row. Any OP_Column operations
67858 ** that occur while the cursor is on the null row will always
67859 ** write a NULL.
67860 */
67861 case OP_NullRow: {
67862 #if 0 /* local variables moved into u.bm */
67863 VdbeCursor *pC;
67864 #endif /* local variables moved into u.bm */
67865
67866 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67867 u.bm.pC = p->apCsr[pOp->p1];
67868 assert( u.bm.pC!=0 );
67869 u.bm.pC->nullRow = 1;
67870 u.bm.pC->rowidIsValid = 0;
67871 assert( u.bm.pC->pCursor || u.bm.pC->pVtabCursor );
67872 if( u.bm.pC->pCursor ){
67873 sqlite3BtreeClearCursor(u.bm.pC->pCursor);
67874 }
67875 break;
67876 }
67877
67878 /* Opcode: Last P1 P2 * * *
@@ -67845,30 +67882,30 @@
67882 ** If the table or index is empty and P2>0, then jump immediately to P2.
67883 ** If P2 is 0 or if the table or index is not empty, fall through
67884 ** to the following instruction.
67885 */
67886 case OP_Last: { /* jump */
67887 #if 0 /* local variables moved into u.bn */
67888 VdbeCursor *pC;
67889 BtCursor *pCrsr;
67890 int res;
67891 #endif /* local variables moved into u.bn */
67892
67893 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67894 u.bn.pC = p->apCsr[pOp->p1];
67895 assert( u.bn.pC!=0 );
67896 u.bn.pCrsr = u.bn.pC->pCursor;
67897 if( NEVER(u.bn.pCrsr==0) ){
67898 u.bn.res = 1;
67899 }else{
67900 rc = sqlite3BtreeLast(u.bn.pCrsr, &u.bn.res);
67901 }
67902 u.bn.pC->nullRow = (u8)u.bn.res;
67903 u.bn.pC->deferredMoveto = 0;
67904 u.bn.pC->rowidIsValid = 0;
67905 u.bn.pC->cacheStatus = CACHE_STALE;
67906 if( pOp->p2>0 && u.bn.res ){
67907 pc = pOp->p2 - 1;
67908 }
67909 break;
67910 }
67911
@@ -67883,10 +67920,14 @@
67920 ** end. We use the OP_Sort opcode instead of OP_Rewind to do the
67921 ** rewinding so that the global variable will be incremented and
67922 ** regression tests can determine whether or not the optimizer is
67923 ** correctly optimizing out sorts.
67924 */
67925 case OP_SorterSort: /* jump */
67926 #ifdef SQLITE_OMIT_MERGE_SORT
67927 pOp->opcode = OP_Sort;
67928 #endif
67929 case OP_Sort: { /* jump */
67930 #ifdef SQLITE_TEST
67931 sqlite3_sort_count++;
67932 sqlite3_search_count--;
67933 #endif
@@ -67900,34 +67941,35 @@
67941 ** If the table or index is empty and P2>0, then jump immediately to P2.
67942 ** If P2 is 0 or if the table or index is not empty, fall through
67943 ** to the following instruction.
67944 */
67945 case OP_Rewind: { /* jump */
67946 #if 0 /* local variables moved into u.bo */
67947 VdbeCursor *pC;
67948 BtCursor *pCrsr;
67949 int res;
67950 #endif /* local variables moved into u.bo */
67951
67952 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
67953 u.bo.pC = p->apCsr[pOp->p1];
67954 assert( u.bo.pC!=0 );
67955 assert( u.bo.pC->isSorter==(pOp->opcode==OP_SorterSort) );
67956 u.bo.res = 1;
67957 if( isSorter(u.bo.pC) ){
67958 rc = sqlite3VdbeSorterRewind(db, u.bo.pC, &u.bo.res);
67959 }else{
67960 u.bo.pCrsr = u.bo.pC->pCursor;
67961 assert( u.bo.pCrsr );
67962 rc = sqlite3BtreeFirst(u.bo.pCrsr, &u.bo.res);
67963 u.bo.pC->atFirst = u.bo.res==0 ?1:0;
67964 u.bo.pC->deferredMoveto = 0;
67965 u.bo.pC->cacheStatus = CACHE_STALE;
67966 u.bo.pC->rowidIsValid = 0;
67967 }
67968 u.bo.pC->nullRow = (u8)u.bo.res;
67969 assert( pOp->p2>0 && pOp->p2<p->nOp );
67970 if( u.bo.res ){
67971 pc = pOp->p2 - 1;
67972 }
67973 break;
67974 }
67975
@@ -67961,45 +68003,50 @@
68003 ** sqlite3BtreePrevious().
68004 **
68005 ** If P5 is positive and the jump is taken, then event counter
68006 ** number P5-1 in the prepared statement is incremented.
68007 */
68008 case OP_SorterNext: /* jump */
68009 #ifdef SQLITE_OMIT_MERGE_SORT
68010 pOp->opcode = OP_Next;
68011 #endif
68012 case OP_Prev: /* jump */
68013 case OP_Next: { /* jump */
68014 #if 0 /* local variables moved into u.bp */
68015 VdbeCursor *pC;
68016 int res;
68017 #endif /* local variables moved into u.bp */
68018
68019 CHECK_FOR_INTERRUPT;
68020 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68021 assert( pOp->p5<=ArraySize(p->aCounter) );
68022 u.bp.pC = p->apCsr[pOp->p1];
68023 if( u.bp.pC==0 ){
68024 break; /* See ticket #2273 */
68025 }
68026 assert( u.bp.pC->isSorter==(pOp->opcode==OP_SorterNext) );
68027 if( isSorter(u.bp.pC) ){
68028 assert( pOp->opcode==OP_SorterNext );
68029 rc = sqlite3VdbeSorterNext(db, u.bp.pC, &u.bp.res);
68030 }else{
68031 u.bp.res = 1;
68032 assert( u.bp.pC->deferredMoveto==0 );
68033 assert( u.bp.pC->pCursor );
68034 assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
68035 assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
68036 rc = pOp->p4.xAdvance(u.bp.pC->pCursor, &u.bp.res);
68037 }
68038 u.bp.pC->nullRow = (u8)u.bp.res;
68039 u.bp.pC->cacheStatus = CACHE_STALE;
68040 if( u.bp.res==0 ){
68041 pc = pOp->p2 - 1;
68042 if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
68043 #ifdef SQLITE_TEST
68044 sqlite3_search_count++;
68045 #endif
68046 }
68047 u.bp.pC->rowidIsValid = 0;
68048 break;
68049 }
68050
68051 /* Opcode: IdxInsert P1 P2 P3 * P5
68052 **
@@ -68011,38 +68058,44 @@
68058 ** insert is likely to be an append.
68059 **
68060 ** This instruction only works for indices. The equivalent instruction
68061 ** for tables is OP_Insert.
68062 */
68063 case OP_SorterInsert: /* in2 */
68064 #ifdef SQLITE_OMIT_MERGE_SORT
68065 pOp->opcode = OP_IdxInsert;
68066 #endif
68067 case OP_IdxInsert: { /* in2 */
68068 #if 0 /* local variables moved into u.bq */
68069 VdbeCursor *pC;
68070 BtCursor *pCrsr;
68071 int nKey;
68072 const char *zKey;
68073 #endif /* local variables moved into u.bq */
68074
68075 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68076 u.bq.pC = p->apCsr[pOp->p1];
68077 assert( u.bq.pC!=0 );
68078 assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
68079 pIn2 = &aMem[pOp->p2];
68080 assert( pIn2->flags & MEM_Blob );
68081 u.bq.pCrsr = u.bq.pC->pCursor;
68082 if( ALWAYS(u.bq.pCrsr!=0) ){
68083 assert( u.bq.pC->isTable==0 );
68084 rc = ExpandBlob(pIn2);
68085 if( rc==SQLITE_OK ){
68086 if( isSorter(u.bq.pC) ){
68087 rc = sqlite3VdbeSorterWrite(db, u.bq.pC, pIn2);
68088 }else{
68089 u.bq.nKey = pIn2->n;
68090 u.bq.zKey = pIn2->z;
68091 rc = sqlite3BtreeInsert(u.bq.pCrsr, u.bq.zKey, u.bq.nKey, "", 0, 0, pOp->p3,
68092 ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bq.pC->seekResult : 0)
68093 );
68094 assert( u.bq.pC->deferredMoveto==0 );
68095 u.bq.pC->cacheStatus = CACHE_STALE;
68096 }
68097 }
68098 }
68099 break;
68100 }
68101
@@ -68051,37 +68104,37 @@
68104 ** The content of P3 registers starting at register P2 form
68105 ** an unpacked index key. This opcode removes that entry from the
68106 ** index opened by cursor P1.
68107 */
68108 case OP_IdxDelete: {
68109 #if 0 /* local variables moved into u.br */
68110 VdbeCursor *pC;
68111 BtCursor *pCrsr;
68112 int res;
68113 UnpackedRecord r;
68114 #endif /* local variables moved into u.br */
68115
68116 assert( pOp->p3>0 );
68117 assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
68118 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68119 u.br.pC = p->apCsr[pOp->p1];
68120 assert( u.br.pC!=0 );
68121 u.br.pCrsr = u.br.pC->pCursor;
68122 if( ALWAYS(u.br.pCrsr!=0) ){
68123 u.br.r.pKeyInfo = u.br.pC->pKeyInfo;
68124 u.br.r.nField = (u16)pOp->p3;
68125 u.br.r.flags = 0;
68126 u.br.r.aMem = &aMem[pOp->p2];
68127 #ifdef SQLITE_DEBUG
68128 { int i; for(i=0; i<u.br.r.nField; i++) assert( memIsValid(&u.br.r.aMem[i]) ); }
68129 #endif
68130 rc = sqlite3BtreeMovetoUnpacked(u.br.pCrsr, &u.br.r, 0, 0, &u.br.res);
68131 if( rc==SQLITE_OK && u.br.res==0 ){
68132 rc = sqlite3BtreeDelete(u.br.pCrsr);
68133 }
68134 assert( u.br.pC->deferredMoveto==0 );
68135 u.br.pC->cacheStatus = CACHE_STALE;
68136 }
68137 break;
68138 }
68139
68140 /* Opcode: IdxRowid P1 P2 * * *
@@ -68091,32 +68144,32 @@
68144 ** the rowid of the table entry to which this index entry points.
68145 **
68146 ** See also: Rowid, MakeRecord.
68147 */
68148 case OP_IdxRowid: { /* out2-prerelease */
68149 #if 0 /* local variables moved into u.bs */
68150 BtCursor *pCrsr;
68151 VdbeCursor *pC;
68152 i64 rowid;
68153 #endif /* local variables moved into u.bs */
68154
68155 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68156 u.bs.pC = p->apCsr[pOp->p1];
68157 assert( u.bs.pC!=0 );
68158 u.bs.pCrsr = u.bs.pC->pCursor;
68159 pOut->flags = MEM_Null;
68160 if( ALWAYS(u.bs.pCrsr!=0) ){
68161 rc = sqlite3VdbeCursorMoveto(u.bs.pC);
68162 if( NEVER(rc) ) goto abort_due_to_error;
68163 assert( u.bs.pC->deferredMoveto==0 );
68164 assert( u.bs.pC->isTable==0 );
68165 if( !u.bs.pC->nullRow ){
68166 rc = sqlite3VdbeIdxRowid(db, u.bs.pCrsr, &u.bs.rowid);
68167 if( rc!=SQLITE_OK ){
68168 goto abort_due_to_error;
68169 }
68170 pOut->u.i = u.bs.rowid;
68171 pOut->flags = MEM_Int;
68172 }
68173 }
68174 break;
68175 }
@@ -68147,43 +68200,43 @@
68200 ** If P5 is non-zero then the key value is increased by an epsilon prior
68201 ** to the comparison. This makes the opcode work like IdxLE.
68202 */
68203 case OP_IdxLT: /* jump */
68204 case OP_IdxGE: { /* jump */
68205 #if 0 /* local variables moved into u.bt */
68206 VdbeCursor *pC;
68207 int res;
68208 UnpackedRecord r;
68209 #endif /* local variables moved into u.bt */
68210
68211 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
68212 u.bt.pC = p->apCsr[pOp->p1];
68213 assert( u.bt.pC!=0 );
68214 assert( u.bt.pC->isOrdered );
68215 if( ALWAYS(u.bt.pC->pCursor!=0) ){
68216 assert( u.bt.pC->deferredMoveto==0 );
68217 assert( pOp->p5==0 || pOp->p5==1 );
68218 assert( pOp->p4type==P4_INT32 );
68219 u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
68220 u.bt.r.nField = (u16)pOp->p4.i;
68221 if( pOp->p5 ){
68222 u.bt.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
68223 }else{
68224 u.bt.r.flags = UNPACKED_IGNORE_ROWID;
68225 }
68226 u.bt.r.aMem = &aMem[pOp->p3];
68227 #ifdef SQLITE_DEBUG
68228 { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
68229 #endif
68230 rc = sqlite3VdbeIdxKeyCompare(u.bt.pC, &u.bt.r, &u.bt.res);
68231 if( pOp->opcode==OP_IdxLT ){
68232 u.bt.res = -u.bt.res;
68233 }else{
68234 assert( pOp->opcode==OP_IdxGE );
68235 u.bt.res++;
68236 }
68237 if( u.bt.res>0 ){
68238 pc = pOp->p2 - 1 ;
68239 }
68240 }
68241 break;
68242 }
@@ -68207,43 +68260,43 @@
68260 ** If AUTOVACUUM is disabled then a zero is stored in register P2.
68261 **
68262 ** See also: Clear
68263 */
68264 case OP_Destroy: { /* out2-prerelease */
68265 #if 0 /* local variables moved into u.bu */
68266 int iMoved;
68267 int iCnt;
68268 Vdbe *pVdbe;
68269 int iDb;
68270 #endif /* local variables moved into u.bu */
68271 #ifndef SQLITE_OMIT_VIRTUALTABLE
68272 u.bu.iCnt = 0;
68273 for(u.bu.pVdbe=db->pVdbe; u.bu.pVdbe; u.bu.pVdbe = u.bu.pVdbe->pNext){
68274 if( u.bu.pVdbe->magic==VDBE_MAGIC_RUN && u.bu.pVdbe->inVtabMethod<2 && u.bu.pVdbe->pc>=0 ){
68275 u.bu.iCnt++;
68276 }
68277 }
68278 #else
68279 u.bu.iCnt = db->activeVdbeCnt;
68280 #endif
68281 pOut->flags = MEM_Null;
68282 if( u.bu.iCnt>1 ){
68283 rc = SQLITE_LOCKED;
68284 p->errorAction = OE_Abort;
68285 }else{
68286 u.bu.iDb = pOp->p3;
68287 assert( u.bu.iCnt==1 );
68288 assert( (p->btreeMask & (((yDbMask)1)<<u.bu.iDb))!=0 );
68289 rc = sqlite3BtreeDropTable(db->aDb[u.bu.iDb].pBt, pOp->p1, &u.bu.iMoved);
68290 pOut->flags = MEM_Int;
68291 pOut->u.i = u.bu.iMoved;
68292 #ifndef SQLITE_OMIT_AUTOVACUUM
68293 if( rc==SQLITE_OK && u.bu.iMoved!=0 ){
68294 sqlite3RootPageMoved(db, u.bu.iDb, u.bu.iMoved, pOp->p1);
68295 /* All OP_Destroy operations occur on the same btree */
68296 assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bu.iDb+1 );
68297 resetSchemaOnFault = u.bu.iDb+1;
68298 }
68299 #endif
68300 }
68301 break;
68302 }
@@ -68265,25 +68318,25 @@
68318 ** also incremented by the number of rows in the table being cleared.
68319 **
68320 ** See also: Destroy
68321 */
68322 case OP_Clear: {
68323 #if 0 /* local variables moved into u.bv */
68324 int nChange;
68325 #endif /* local variables moved into u.bv */
68326
68327 u.bv.nChange = 0;
68328 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
68329 rc = sqlite3BtreeClearTable(
68330 db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bv.nChange : 0)
68331 );
68332 if( pOp->p3 ){
68333 p->nChange += u.bv.nChange;
68334 if( pOp->p3>0 ){
68335 assert( memIsValid(&aMem[pOp->p3]) );
68336 memAboutToChange(p, &aMem[pOp->p3]);
68337 aMem[pOp->p3].u.i += u.bv.nChange;
68338 }
68339 }
68340 break;
68341 }
68342
@@ -68309,29 +68362,29 @@
68362 **
68363 ** See documentation on OP_CreateTable for additional information.
68364 */
68365 case OP_CreateIndex: /* out2-prerelease */
68366 case OP_CreateTable: { /* out2-prerelease */
68367 #if 0 /* local variables moved into u.bw */
68368 int pgno;
68369 int flags;
68370 Db *pDb;
68371 #endif /* local variables moved into u.bw */
68372
68373 u.bw.pgno = 0;
68374 assert( pOp->p1>=0 && pOp->p1<db->nDb );
68375 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
68376 u.bw.pDb = &db->aDb[pOp->p1];
68377 assert( u.bw.pDb->pBt!=0 );
68378 if( pOp->opcode==OP_CreateTable ){
68379 /* u.bw.flags = BTREE_INTKEY; */
68380 u.bw.flags = BTREE_INTKEY;
68381 }else{
68382 u.bw.flags = BTREE_BLOBKEY;
68383 }
68384 rc = sqlite3BtreeCreateTable(u.bw.pDb->pBt, &u.bw.pgno, u.bw.flags);
68385 pOut->u.i = u.bw.pgno;
68386 break;
68387 }
68388
68389 /* Opcode: ParseSchema P1 * * P4 *
68390 **
@@ -68340,48 +68393,48 @@
68393 **
68394 ** This opcode invokes the parser to create a new virtual machine,
68395 ** then runs the new virtual machine. It is thus a re-entrant opcode.
68396 */
68397 case OP_ParseSchema: {
68398 #if 0 /* local variables moved into u.bx */
68399 int iDb;
68400 const char *zMaster;
68401 char *zSql;
68402 InitData initData;
68403 #endif /* local variables moved into u.bx */
68404
68405 /* Any prepared statement that invokes this opcode will hold mutexes
68406 ** on every btree. This is a prerequisite for invoking
68407 ** sqlite3InitCallback().
68408 */
68409 #ifdef SQLITE_DEBUG
68410 for(u.bx.iDb=0; u.bx.iDb<db->nDb; u.bx.iDb++){
68411 assert( u.bx.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bx.iDb].pBt) );
68412 }
68413 #endif
68414
68415 u.bx.iDb = pOp->p1;
68416 assert( u.bx.iDb>=0 && u.bx.iDb<db->nDb );
68417 assert( DbHasProperty(db, u.bx.iDb, DB_SchemaLoaded) );
68418 /* Used to be a conditional */ {
68419 u.bx.zMaster = SCHEMA_TABLE(u.bx.iDb);
68420 u.bx.initData.db = db;
68421 u.bx.initData.iDb = pOp->p1;
68422 u.bx.initData.pzErrMsg = &p->zErrMsg;
68423 u.bx.zSql = sqlite3MPrintf(db,
68424 "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
68425 db->aDb[u.bx.iDb].zName, u.bx.zMaster, pOp->p4.z);
68426 if( u.bx.zSql==0 ){
68427 rc = SQLITE_NOMEM;
68428 }else{
68429 assert( db->init.busy==0 );
68430 db->init.busy = 1;
68431 u.bx.initData.rc = SQLITE_OK;
68432 assert( !db->mallocFailed );
68433 rc = sqlite3_exec(db, u.bx.zSql, sqlite3InitCallback, &u.bx.initData, 0);
68434 if( rc==SQLITE_OK ) rc = u.bx.initData.rc;
68435 sqlite3DbFree(db, u.bx.zSql);
68436 db->init.busy = 0;
68437 }
68438 }
68439 if( rc==SQLITE_NOMEM ){
68440 goto no_mem;
@@ -68460,45 +68513,45 @@
68513 ** file, not the main database file.
68514 **
68515 ** This opcode is used to implement the integrity_check pragma.
68516 */
68517 case OP_IntegrityCk: {
68518 #if 0 /* local variables moved into u.by */
68519 int nRoot; /* Number of tables to check. (Number of root pages.) */
68520 int *aRoot; /* Array of rootpage numbers for tables to be checked */
68521 int j; /* Loop counter */
68522 int nErr; /* Number of errors reported */
68523 char *z; /* Text of the error report */
68524 Mem *pnErr; /* Register keeping track of errors remaining */
68525 #endif /* local variables moved into u.by */
68526
68527 u.by.nRoot = pOp->p2;
68528 assert( u.by.nRoot>0 );
68529 u.by.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.by.nRoot+1) );
68530 if( u.by.aRoot==0 ) goto no_mem;
68531 assert( pOp->p3>0 && pOp->p3<=p->nMem );
68532 u.by.pnErr = &aMem[pOp->p3];
68533 assert( (u.by.pnErr->flags & MEM_Int)!=0 );
68534 assert( (u.by.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
68535 pIn1 = &aMem[pOp->p1];
68536 for(u.by.j=0; u.by.j<u.by.nRoot; u.by.j++){
68537 u.by.aRoot[u.by.j] = (int)sqlite3VdbeIntValue(&pIn1[u.by.j]);
68538 }
68539 u.by.aRoot[u.by.j] = 0;
68540 assert( pOp->p5<db->nDb );
68541 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
68542 u.by.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.by.aRoot, u.by.nRoot,
68543 (int)u.by.pnErr->u.i, &u.by.nErr);
68544 sqlite3DbFree(db, u.by.aRoot);
68545 u.by.pnErr->u.i -= u.by.nErr;
68546 sqlite3VdbeMemSetNull(pIn1);
68547 if( u.by.nErr==0 ){
68548 assert( u.by.z==0 );
68549 }else if( u.by.z==0 ){
68550 goto no_mem;
68551 }else{
68552 sqlite3VdbeMemSetStr(pIn1, u.by.z, -1, SQLITE_UTF8, sqlite3_free);
68553 }
68554 UPDATE_MAX_BLOBSIZE(pIn1);
68555 sqlite3VdbeChangeEncoding(pIn1, encoding);
68556 break;
68557 }
@@ -68528,24 +68581,24 @@
68581 ** Extract the smallest value from boolean index P1 and put that value into
68582 ** register P3. Or, if boolean index P1 is initially empty, leave P3
68583 ** unchanged and jump to instruction P2.
68584 */
68585 case OP_RowSetRead: { /* jump, in1, out3 */
68586 #if 0 /* local variables moved into u.bz */
68587 i64 val;
68588 #endif /* local variables moved into u.bz */
68589 CHECK_FOR_INTERRUPT;
68590 pIn1 = &aMem[pOp->p1];
68591 if( (pIn1->flags & MEM_RowSet)==0
68592 || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bz.val)==0
68593 ){
68594 /* The boolean index is empty */
68595 sqlite3VdbeMemSetNull(pIn1);
68596 pc = pOp->p2 - 1;
68597 }else{
68598 /* A value was pulled from the index */
68599 sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bz.val);
68600 }
68601 break;
68602 }
68603
68604 /* Opcode: RowSetTest P1 P2 P3 P4
@@ -68570,18 +68623,18 @@
68623 ** inserted, there is no need to search to see if the same value was
68624 ** previously inserted as part of set X (only if it was previously
68625 ** inserted as part of some other set).
68626 */
68627 case OP_RowSetTest: { /* jump, in1, in3 */
68628 #if 0 /* local variables moved into u.ca */
68629 int iSet;
68630 int exists;
68631 #endif /* local variables moved into u.ca */
68632
68633 pIn1 = &aMem[pOp->p1];
68634 pIn3 = &aMem[pOp->p3];
68635 u.ca.iSet = pOp->p4.i;
68636 assert( pIn3->flags&MEM_Int );
68637
68638 /* If there is anything other than a rowset object in memory cell P1,
68639 ** delete it now and initialize P1 with an empty rowset
68640 */
@@ -68589,21 +68642,21 @@
68642 sqlite3VdbeMemSetRowSet(pIn1);
68643 if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
68644 }
68645
68646 assert( pOp->p4type==P4_INT32 );
68647 assert( u.ca.iSet==-1 || u.ca.iSet>=0 );
68648 if( u.ca.iSet ){
68649 u.ca.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
68650 (u8)(u.ca.iSet>=0 ? u.ca.iSet & 0xf : 0xff),
68651 pIn3->u.i);
68652 if( u.ca.exists ){
68653 pc = pOp->p2 - 1;
68654 break;
68655 }
68656 }
68657 if( u.ca.iSet>=0 ){
68658 sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
68659 }
68660 break;
68661 }
68662
@@ -68622,25 +68675,25 @@
68675 ** memory required by the sub-vdbe at runtime.
68676 **
68677 ** P4 is a pointer to the VM containing the trigger program.
68678 */
68679 case OP_Program: { /* jump */
68680 #if 0 /* local variables moved into u.cb */
68681 int nMem; /* Number of memory registers for sub-program */
68682 int nByte; /* Bytes of runtime space required for sub-program */
68683 Mem *pRt; /* Register to allocate runtime space */
68684 Mem *pMem; /* Used to iterate through memory cells */
68685 Mem *pEnd; /* Last memory cell in new array */
68686 VdbeFrame *pFrame; /* New vdbe frame to execute in */
68687 SubProgram *pProgram; /* Sub-program to execute */
68688 void *t; /* Token identifying trigger */
68689 #endif /* local variables moved into u.cb */
68690
68691 u.cb.pProgram = pOp->p4.pProgram;
68692 u.cb.pRt = &aMem[pOp->p3];
68693 assert( memIsValid(u.cb.pRt) );
68694 assert( u.cb.pProgram->nOp>0 );
68695
68696 /* If the p5 flag is clear, then recursive invocation of triggers is
68697 ** disabled for backwards compatibility (p5 is set if this sub-program
68698 ** is really a trigger, not a foreign key action, and the flag set
68699 ** and cleared by the "PRAGMA recursive_triggers" command is clear).
@@ -68650,79 +68703,79 @@
68703 ** SubProgram (if the trigger may be executed with more than one different
68704 ** ON CONFLICT algorithm). SubProgram structures associated with a
68705 ** single trigger all have the same value for the SubProgram.token
68706 ** variable. */
68707 if( pOp->p5 ){
68708 u.cb.t = u.cb.pProgram->token;
68709 for(u.cb.pFrame=p->pFrame; u.cb.pFrame && u.cb.pFrame->token!=u.cb.t; u.cb.pFrame=u.cb.pFrame->pParent);
68710 if( u.cb.pFrame ) break;
68711 }
68712
68713 if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
68714 rc = SQLITE_ERROR;
68715 sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
68716 break;
68717 }
68718
68719 /* Register u.cb.pRt is used to store the memory required to save the state
68720 ** of the current program, and the memory required at runtime to execute
68721 ** the trigger program. If this trigger has been fired before, then u.cb.pRt
68722 ** is already allocated. Otherwise, it must be initialized. */
68723 if( (u.cb.pRt->flags&MEM_Frame)==0 ){
68724 /* SubProgram.nMem is set to the number of memory cells used by the
68725 ** program stored in SubProgram.aOp. As well as these, one memory
68726 ** cell is required for each cursor used by the program. Set local
68727 ** variable u.cb.nMem (and later, VdbeFrame.nChildMem) to this value.
68728 */
68729 u.cb.nMem = u.cb.pProgram->nMem + u.cb.pProgram->nCsr;
68730 u.cb.nByte = ROUND8(sizeof(VdbeFrame))
68731 + u.cb.nMem * sizeof(Mem)
68732 + u.cb.pProgram->nCsr * sizeof(VdbeCursor *);
68733 u.cb.pFrame = sqlite3DbMallocZero(db, u.cb.nByte);
68734 if( !u.cb.pFrame ){
68735 goto no_mem;
68736 }
68737 sqlite3VdbeMemRelease(u.cb.pRt);
68738 u.cb.pRt->flags = MEM_Frame;
68739 u.cb.pRt->u.pFrame = u.cb.pFrame;
68740
68741 u.cb.pFrame->v = p;
68742 u.cb.pFrame->nChildMem = u.cb.nMem;
68743 u.cb.pFrame->nChildCsr = u.cb.pProgram->nCsr;
68744 u.cb.pFrame->pc = pc;
68745 u.cb.pFrame->aMem = p->aMem;
68746 u.cb.pFrame->nMem = p->nMem;
68747 u.cb.pFrame->apCsr = p->apCsr;
68748 u.cb.pFrame->nCursor = p->nCursor;
68749 u.cb.pFrame->aOp = p->aOp;
68750 u.cb.pFrame->nOp = p->nOp;
68751 u.cb.pFrame->token = u.cb.pProgram->token;
68752
68753 u.cb.pEnd = &VdbeFrameMem(u.cb.pFrame)[u.cb.pFrame->nChildMem];
68754 for(u.cb.pMem=VdbeFrameMem(u.cb.pFrame); u.cb.pMem!=u.cb.pEnd; u.cb.pMem++){
68755 u.cb.pMem->flags = MEM_Null;
68756 u.cb.pMem->db = db;
68757 }
68758 }else{
68759 u.cb.pFrame = u.cb.pRt->u.pFrame;
68760 assert( u.cb.pProgram->nMem+u.cb.pProgram->nCsr==u.cb.pFrame->nChildMem );
68761 assert( u.cb.pProgram->nCsr==u.cb.pFrame->nChildCsr );
68762 assert( pc==u.cb.pFrame->pc );
68763 }
68764
68765 p->nFrame++;
68766 u.cb.pFrame->pParent = p->pFrame;
68767 u.cb.pFrame->lastRowid = lastRowid;
68768 u.cb.pFrame->nChange = p->nChange;
68769 p->nChange = 0;
68770 p->pFrame = u.cb.pFrame;
68771 p->aMem = aMem = &VdbeFrameMem(u.cb.pFrame)[-1];
68772 p->nMem = u.cb.pFrame->nChildMem;
68773 p->nCursor = (u16)u.cb.pFrame->nChildCsr;
68774 p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
68775 p->aOp = aOp = u.cb.pProgram->aOp;
68776 p->nOp = u.cb.pProgram->nOp;
68777 pc = -1;
68778
68779 break;
68780 }
68781
@@ -68737,17 +68790,17 @@
68790 ** The address of the cell in the parent frame is determined by adding
68791 ** the value of the P1 argument to the value of the P1 argument to the
68792 ** calling OP_Program instruction.
68793 */
68794 case OP_Param: { /* out2-prerelease */
68795 #if 0 /* local variables moved into u.cc */
68796 VdbeFrame *pFrame;
68797 Mem *pIn;
68798 #endif /* local variables moved into u.cc */
68799 u.cc.pFrame = p->pFrame;
68800 u.cc.pIn = &u.cc.pFrame->aMem[pOp->p1 + u.cc.pFrame->aOp[u.cc.pFrame->pc].p1];
68801 sqlite3VdbeMemShallowCopy(pOut, u.cc.pIn, MEM_Ephem);
68802 break;
68803 }
68804
68805 #endif /* #ifndef SQLITE_OMIT_TRIGGER */
68806
@@ -68799,26 +68852,26 @@
68852 **
68853 ** This instruction throws an error if the memory cell is not initially
68854 ** an integer.
68855 */
68856 case OP_MemMax: { /* in2 */
68857 #if 0 /* local variables moved into u.cd */
68858 Mem *pIn1;
68859 VdbeFrame *pFrame;
68860 #endif /* local variables moved into u.cd */
68861 if( p->pFrame ){
68862 for(u.cd.pFrame=p->pFrame; u.cd.pFrame->pParent; u.cd.pFrame=u.cd.pFrame->pParent);
68863 u.cd.pIn1 = &u.cd.pFrame->aMem[pOp->p1];
68864 }else{
68865 u.cd.pIn1 = &aMem[pOp->p1];
68866 }
68867 assert( memIsValid(u.cd.pIn1) );
68868 sqlite3VdbeMemIntegerify(u.cd.pIn1);
68869 pIn2 = &aMem[pOp->p2];
68870 sqlite3VdbeMemIntegerify(pIn2);
68871 if( u.cd.pIn1->u.i<pIn2->u.i){
68872 u.cd.pIn1->u.i = pIn2->u.i;
68873 }
68874 break;
68875 }
68876 #endif /* SQLITE_OMIT_AUTOINCREMENT */
68877
@@ -68881,54 +68934,54 @@
68934 **
68935 ** The P5 arguments are taken from register P2 and its
68936 ** successors.
68937 */
68938 case OP_AggStep: {
68939 #if 0 /* local variables moved into u.ce */
68940 int n;
68941 int i;
68942 Mem *pMem;
68943 Mem *pRec;
68944 sqlite3_context ctx;
68945 sqlite3_value **apVal;
68946 #endif /* local variables moved into u.ce */
68947
68948 u.ce.n = pOp->p5;
68949 assert( u.ce.n>=0 );
68950 u.ce.pRec = &aMem[pOp->p2];
68951 u.ce.apVal = p->apArg;
68952 assert( u.ce.apVal || u.ce.n==0 );
68953 for(u.ce.i=0; u.ce.i<u.ce.n; u.ce.i++, u.ce.pRec++){
68954 assert( memIsValid(u.ce.pRec) );
68955 u.ce.apVal[u.ce.i] = u.ce.pRec;
68956 memAboutToChange(p, u.ce.pRec);
68957 sqlite3VdbeMemStoreType(u.ce.pRec);
68958 }
68959 u.ce.ctx.pFunc = pOp->p4.pFunc;
68960 assert( pOp->p3>0 && pOp->p3<=p->nMem );
68961 u.ce.ctx.pMem = u.ce.pMem = &aMem[pOp->p3];
68962 u.ce.pMem->n++;
68963 u.ce.ctx.s.flags = MEM_Null;
68964 u.ce.ctx.s.z = 0;
68965 u.ce.ctx.s.zMalloc = 0;
68966 u.ce.ctx.s.xDel = 0;
68967 u.ce.ctx.s.db = db;
68968 u.ce.ctx.isError = 0;
68969 u.ce.ctx.pColl = 0;
68970 if( u.ce.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
68971 assert( pOp>p->aOp );
68972 assert( pOp[-1].p4type==P4_COLLSEQ );
68973 assert( pOp[-1].opcode==OP_CollSeq );
68974 u.ce.ctx.pColl = pOp[-1].p4.pColl;
68975 }
68976 (u.ce.ctx.pFunc->xStep)(&u.ce.ctx, u.ce.n, u.ce.apVal); /* IMP: R-24505-23230 */
68977 if( u.ce.ctx.isError ){
68978 sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ce.ctx.s));
68979 rc = u.ce.ctx.isError;
68980 }
68981
68982 sqlite3VdbeMemRelease(&u.ce.ctx.s);
68983
68984 break;
68985 }
68986
68987 /* Opcode: AggFinal P1 P2 * P4 *
@@ -68942,23 +68995,23 @@
68995 ** functions that can take varying numbers of arguments. The
68996 ** P4 argument is only needed for the degenerate case where
68997 ** the step function was not previously called.
68998 */
68999 case OP_AggFinal: {
69000 #if 0 /* local variables moved into u.cf */
69001 Mem *pMem;
69002 #endif /* local variables moved into u.cf */
69003 assert( pOp->p1>0 && pOp->p1<=p->nMem );
69004 u.cf.pMem = &aMem[pOp->p1];
69005 assert( (u.cf.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
69006 rc = sqlite3VdbeMemFinalize(u.cf.pMem, pOp->p4.pFunc);
69007 if( rc ){
69008 sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cf.pMem));
69009 }
69010 sqlite3VdbeChangeEncoding(u.cf.pMem, encoding);
69011 UPDATE_MAX_BLOBSIZE(u.cf.pMem);
69012 if( sqlite3VdbeMemTooBig(u.cf.pMem) ){
69013 goto too_big;
69014 }
69015 break;
69016 }
69017
@@ -68973,29 +69026,29 @@
69026 ** in the WAL that have been checkpointed after the checkpoint
69027 ** completes into mem[P3+2]. However on an error, mem[P3+1] and
69028 ** mem[P3+2] are initialized to -1.
69029 */
69030 case OP_Checkpoint: {
69031 #if 0 /* local variables moved into u.cg */
69032 int i; /* Loop counter */
69033 int aRes[3]; /* Results */
69034 Mem *pMem; /* Write results here */
69035 #endif /* local variables moved into u.cg */
69036
69037 u.cg.aRes[0] = 0;
69038 u.cg.aRes[1] = u.cg.aRes[2] = -1;
69039 assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
69040 || pOp->p2==SQLITE_CHECKPOINT_FULL
69041 || pOp->p2==SQLITE_CHECKPOINT_RESTART
69042 );
69043 rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cg.aRes[1], &u.cg.aRes[2]);
69044 if( rc==SQLITE_BUSY ){
69045 rc = SQLITE_OK;
69046 u.cg.aRes[0] = 1;
69047 }
69048 for(u.cg.i=0, u.cg.pMem = &aMem[pOp->p3]; u.cg.i<3; u.cg.i++, u.cg.pMem++){
69049 sqlite3VdbeMemSetInt64(u.cg.pMem, (i64)u.cg.aRes[u.cg.i]);
69050 }
69051 break;
69052 };
69053 #endif
69054
@@ -69010,95 +69063,95 @@
69063 ** If changing into or out of WAL mode the procedure is more complicated.
69064 **
69065 ** Write a string containing the final journal-mode to register P2.
69066 */
69067 case OP_JournalMode: { /* out2-prerelease */
69068 #if 0 /* local variables moved into u.ch */
69069 Btree *pBt; /* Btree to change journal mode of */
69070 Pager *pPager; /* Pager associated with pBt */
69071 int eNew; /* New journal mode */
69072 int eOld; /* The old journal mode */
69073 const char *zFilename; /* Name of database file for pPager */
69074 #endif /* local variables moved into u.ch */
69075
69076 u.ch.eNew = pOp->p3;
69077 assert( u.ch.eNew==PAGER_JOURNALMODE_DELETE
69078 || u.ch.eNew==PAGER_JOURNALMODE_TRUNCATE
69079 || u.ch.eNew==PAGER_JOURNALMODE_PERSIST
69080 || u.ch.eNew==PAGER_JOURNALMODE_OFF
69081 || u.ch.eNew==PAGER_JOURNALMODE_MEMORY
69082 || u.ch.eNew==PAGER_JOURNALMODE_WAL
69083 || u.ch.eNew==PAGER_JOURNALMODE_QUERY
69084 );
69085 assert( pOp->p1>=0 && pOp->p1<db->nDb );
69086
69087 u.ch.pBt = db->aDb[pOp->p1].pBt;
69088 u.ch.pPager = sqlite3BtreePager(u.ch.pBt);
69089 u.ch.eOld = sqlite3PagerGetJournalMode(u.ch.pPager);
69090 if( u.ch.eNew==PAGER_JOURNALMODE_QUERY ) u.ch.eNew = u.ch.eOld;
69091 if( !sqlite3PagerOkToChangeJournalMode(u.ch.pPager) ) u.ch.eNew = u.ch.eOld;
69092
69093 #ifndef SQLITE_OMIT_WAL
69094 u.ch.zFilename = sqlite3PagerFilename(u.ch.pPager);
69095
69096 /* Do not allow a transition to journal_mode=WAL for a database
69097 ** in temporary storage or if the VFS does not support shared memory
69098 */
69099 if( u.ch.eNew==PAGER_JOURNALMODE_WAL
69100 && (u.ch.zFilename[0]==0 /* Temp file */
69101 || !sqlite3PagerWalSupported(u.ch.pPager)) /* No shared-memory support */
69102 ){
69103 u.ch.eNew = u.ch.eOld;
69104 }
69105
69106 if( (u.ch.eNew!=u.ch.eOld)
69107 && (u.ch.eOld==PAGER_JOURNALMODE_WAL || u.ch.eNew==PAGER_JOURNALMODE_WAL)
69108 ){
69109 if( !db->autoCommit || db->activeVdbeCnt>1 ){
69110 rc = SQLITE_ERROR;
69111 sqlite3SetString(&p->zErrMsg, db,
69112 "cannot change %s wal mode from within a transaction",
69113 (u.ch.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
69114 );
69115 break;
69116 }else{
69117
69118 if( u.ch.eOld==PAGER_JOURNALMODE_WAL ){
69119 /* If leaving WAL mode, close the log file. If successful, the call
69120 ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
69121 ** file. An EXCLUSIVE lock may still be held on the database file
69122 ** after a successful return.
69123 */
69124 rc = sqlite3PagerCloseWal(u.ch.pPager);
69125 if( rc==SQLITE_OK ){
69126 sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);
69127 }
69128 }else if( u.ch.eOld==PAGER_JOURNALMODE_MEMORY ){
69129 /* Cannot transition directly from MEMORY to WAL. Use mode OFF
69130 ** as an intermediate */
69131 sqlite3PagerSetJournalMode(u.ch.pPager, PAGER_JOURNALMODE_OFF);
69132 }
69133
69134 /* Open a transaction on the database file. Regardless of the journal
69135 ** mode, this transaction always uses a rollback journal.
69136 */
69137 assert( sqlite3BtreeIsInTrans(u.ch.pBt)==0 );
69138 if( rc==SQLITE_OK ){
69139 rc = sqlite3BtreeSetVersion(u.ch.pBt, (u.ch.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
69140 }
69141 }
69142 }
69143 #endif /* ifndef SQLITE_OMIT_WAL */
69144
69145 if( rc ){
69146 u.ch.eNew = u.ch.eOld;
69147 }
69148 u.ch.eNew = sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);
69149
69150 pOut = &aMem[pOp->p2];
69151 pOut->flags = MEM_Str|MEM_Static|MEM_Term;
69152 pOut->z = (char *)sqlite3JournalModename(u.ch.eNew);
69153 pOut->n = sqlite3Strlen30(pOut->z);
69154 pOut->enc = SQLITE_UTF8;
69155 sqlite3VdbeChangeEncoding(pOut, encoding);
69156 break;
69157 };
@@ -69123,18 +69176,18 @@
69176 ** Perform a single step of the incremental vacuum procedure on
69177 ** the P1 database. If the vacuum has finished, jump to instruction
69178 ** P2. Otherwise, fall through to the next instruction.
69179 */
69180 case OP_IncrVacuum: { /* jump */
69181 #if 0 /* local variables moved into u.ci */
69182 Btree *pBt;
69183 #endif /* local variables moved into u.ci */
69184
69185 assert( pOp->p1>=0 && pOp->p1<db->nDb );
69186 assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
69187 u.ci.pBt = db->aDb[pOp->p1].pBt;
69188 rc = sqlite3BtreeIncrVacuum(u.ci.pBt);
69189 if( rc==SQLITE_DONE ){
69190 pc = pOp->p2 - 1;
69191 rc = SQLITE_OK;
69192 }
69193 break;
@@ -69200,16 +69253,16 @@
69253 ** Also, whether or not P4 is set, check that this is not being called from
69254 ** within a callback to a virtual table xSync() method. If it is, the error
69255 ** code will be set to SQLITE_LOCKED.
69256 */
69257 case OP_VBegin: {
69258 #if 0 /* local variables moved into u.cj */
69259 VTable *pVTab;
69260 #endif /* local variables moved into u.cj */
69261 u.cj.pVTab = pOp->p4.pVtab;
69262 rc = sqlite3VtabBegin(db, u.cj.pVTab);
69263 if( u.cj.pVTab ) importVtabErrMsg(p, u.cj.pVTab->pVtab);
69264 break;
69265 }
69266 #endif /* SQLITE_OMIT_VIRTUALTABLE */
69267
69268 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -69244,36 +69297,36 @@
69297 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
69298 ** P1 is a cursor number. This opcode opens a cursor to the virtual
69299 ** table and stores that cursor in P1.
69300 */
69301 case OP_VOpen: {
69302 #if 0 /* local variables moved into u.ck */
69303 VdbeCursor *pCur;
69304 sqlite3_vtab_cursor *pVtabCursor;
69305 sqlite3_vtab *pVtab;
69306 sqlite3_module *pModule;
69307 #endif /* local variables moved into u.ck */
69308
69309 u.ck.pCur = 0;
69310 u.ck.pVtabCursor = 0;
69311 u.ck.pVtab = pOp->p4.pVtab->pVtab;
69312 u.ck.pModule = (sqlite3_module *)u.ck.pVtab->pModule;
69313 assert(u.ck.pVtab && u.ck.pModule);
69314 rc = u.ck.pModule->xOpen(u.ck.pVtab, &u.ck.pVtabCursor);
69315 importVtabErrMsg(p, u.ck.pVtab);
69316 if( SQLITE_OK==rc ){
69317 /* Initialize sqlite3_vtab_cursor base class */
69318 u.ck.pVtabCursor->pVtab = u.ck.pVtab;
69319
69320 /* Initialise vdbe cursor object */
69321 u.ck.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
69322 if( u.ck.pCur ){
69323 u.ck.pCur->pVtabCursor = u.ck.pVtabCursor;
69324 u.ck.pCur->pModule = u.ck.pVtabCursor->pVtab->pModule;
69325 }else{
69326 db->mallocFailed = 1;
69327 u.ck.pModule->xClose(u.ck.pVtabCursor);
69328 }
69329 }
69330 break;
69331 }
69332 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69296,11 +69349,11 @@
69349 ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
69350 **
69351 ** A jump is made to P2 if the result set after filtering would be empty.
69352 */
69353 case OP_VFilter: { /* jump */
69354 #if 0 /* local variables moved into u.cl */
69355 int nArg;
69356 int iQuery;
69357 const sqlite3_module *pModule;
69358 Mem *pQuery;
69359 Mem *pArgc;
@@ -69308,49 +69361,49 @@
69361 sqlite3_vtab *pVtab;
69362 VdbeCursor *pCur;
69363 int res;
69364 int i;
69365 Mem **apArg;
69366 #endif /* local variables moved into u.cl */
69367
69368 u.cl.pQuery = &aMem[pOp->p3];
69369 u.cl.pArgc = &u.cl.pQuery[1];
69370 u.cl.pCur = p->apCsr[pOp->p1];
69371 assert( memIsValid(u.cl.pQuery) );
69372 REGISTER_TRACE(pOp->p3, u.cl.pQuery);
69373 assert( u.cl.pCur->pVtabCursor );
69374 u.cl.pVtabCursor = u.cl.pCur->pVtabCursor;
69375 u.cl.pVtab = u.cl.pVtabCursor->pVtab;
69376 u.cl.pModule = u.cl.pVtab->pModule;
69377
69378 /* Grab the index number and argc parameters */
69379 assert( (u.cl.pQuery->flags&MEM_Int)!=0 && u.cl.pArgc->flags==MEM_Int );
69380 u.cl.nArg = (int)u.cl.pArgc->u.i;
69381 u.cl.iQuery = (int)u.cl.pQuery->u.i;
69382
69383 /* Invoke the xFilter method */
69384 {
69385 u.cl.res = 0;
69386 u.cl.apArg = p->apArg;
69387 for(u.cl.i = 0; u.cl.i<u.cl.nArg; u.cl.i++){
69388 u.cl.apArg[u.cl.i] = &u.cl.pArgc[u.cl.i+1];
69389 sqlite3VdbeMemStoreType(u.cl.apArg[u.cl.i]);
69390 }
69391
69392 p->inVtabMethod = 1;
69393 rc = u.cl.pModule->xFilter(u.cl.pVtabCursor, u.cl.iQuery, pOp->p4.z, u.cl.nArg, u.cl.apArg);
69394 p->inVtabMethod = 0;
69395 importVtabErrMsg(p, u.cl.pVtab);
69396 if( rc==SQLITE_OK ){
69397 u.cl.res = u.cl.pModule->xEof(u.cl.pVtabCursor);
69398 }
69399
69400 if( u.cl.res ){
69401 pc = pOp->p2 - 1;
69402 }
69403 }
69404 u.cl.pCur->nullRow = 0;
69405
69406 break;
69407 }
69408 #endif /* SQLITE_OMIT_VIRTUALTABLE */
69409
@@ -69360,55 +69413,55 @@
69413 ** Store the value of the P2-th column of
69414 ** the row of the virtual-table that the
69415 ** P1 cursor is pointing to into register P3.
69416 */
69417 case OP_VColumn: {
69418 #if 0 /* local variables moved into u.cm */
69419 sqlite3_vtab *pVtab;
69420 const sqlite3_module *pModule;
69421 Mem *pDest;
69422 sqlite3_context sContext;
69423 #endif /* local variables moved into u.cm */
69424
69425 VdbeCursor *pCur = p->apCsr[pOp->p1];
69426 assert( pCur->pVtabCursor );
69427 assert( pOp->p3>0 && pOp->p3<=p->nMem );
69428 u.cm.pDest = &aMem[pOp->p3];
69429 memAboutToChange(p, u.cm.pDest);
69430 if( pCur->nullRow ){
69431 sqlite3VdbeMemSetNull(u.cm.pDest);
69432 break;
69433 }
69434 u.cm.pVtab = pCur->pVtabCursor->pVtab;
69435 u.cm.pModule = u.cm.pVtab->pModule;
69436 assert( u.cm.pModule->xColumn );
69437 memset(&u.cm.sContext, 0, sizeof(u.cm.sContext));
69438
69439 /* The output cell may already have a buffer allocated. Move
69440 ** the current contents to u.cm.sContext.s so in case the user-function
69441 ** can use the already allocated buffer instead of allocating a
69442 ** new one.
69443 */
69444 sqlite3VdbeMemMove(&u.cm.sContext.s, u.cm.pDest);
69445 MemSetTypeFlag(&u.cm.sContext.s, MEM_Null);
69446
69447 rc = u.cm.pModule->xColumn(pCur->pVtabCursor, &u.cm.sContext, pOp->p2);
69448 importVtabErrMsg(p, u.cm.pVtab);
69449 if( u.cm.sContext.isError ){
69450 rc = u.cm.sContext.isError;
69451 }
69452
69453 /* Copy the result of the function to the P3 register. We
69454 ** do this regardless of whether or not an error occurred to ensure any
69455 ** dynamic allocation in u.cm.sContext.s (a Mem struct) is released.
69456 */
69457 sqlite3VdbeChangeEncoding(&u.cm.sContext.s, encoding);
69458 sqlite3VdbeMemMove(u.cm.pDest, &u.cm.sContext.s);
69459 REGISTER_TRACE(pOp->p3, u.cm.pDest);
69460 UPDATE_MAX_BLOBSIZE(u.cm.pDest);
69461
69462 if( sqlite3VdbeMemTooBig(u.cm.pDest) ){
69463 goto too_big;
69464 }
69465 break;
69466 }
69467 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69419,42 +69472,42 @@
69472 ** Advance virtual table P1 to the next row in its result set and
69473 ** jump to instruction P2. Or, if the virtual table has reached
69474 ** the end of its result set, then fall through to the next instruction.
69475 */
69476 case OP_VNext: { /* jump */
69477 #if 0 /* local variables moved into u.cn */
69478 sqlite3_vtab *pVtab;
69479 const sqlite3_module *pModule;
69480 int res;
69481 VdbeCursor *pCur;
69482 #endif /* local variables moved into u.cn */
69483
69484 u.cn.res = 0;
69485 u.cn.pCur = p->apCsr[pOp->p1];
69486 assert( u.cn.pCur->pVtabCursor );
69487 if( u.cn.pCur->nullRow ){
69488 break;
69489 }
69490 u.cn.pVtab = u.cn.pCur->pVtabCursor->pVtab;
69491 u.cn.pModule = u.cn.pVtab->pModule;
69492 assert( u.cn.pModule->xNext );
69493
69494 /* Invoke the xNext() method of the module. There is no way for the
69495 ** underlying implementation to return an error if one occurs during
69496 ** xNext(). Instead, if an error occurs, true is returned (indicating that
69497 ** data is available) and the error code returned when xColumn or
69498 ** some other method is next invoked on the save virtual table cursor.
69499 */
69500 p->inVtabMethod = 1;
69501 rc = u.cn.pModule->xNext(u.cn.pCur->pVtabCursor);
69502 p->inVtabMethod = 0;
69503 importVtabErrMsg(p, u.cn.pVtab);
69504 if( rc==SQLITE_OK ){
69505 u.cn.res = u.cn.pModule->xEof(u.cn.pCur->pVtabCursor);
69506 }
69507
69508 if( !u.cn.res ){
69509 /* If there is data, jump to P2 */
69510 pc = pOp->p2 - 1;
69511 }
69512 break;
69513 }
@@ -69466,23 +69519,23 @@
69519 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
69520 ** This opcode invokes the corresponding xRename method. The value
69521 ** in register P1 is passed as the zName argument to the xRename method.
69522 */
69523 case OP_VRename: {
69524 #if 0 /* local variables moved into u.co */
69525 sqlite3_vtab *pVtab;
69526 Mem *pName;
69527 #endif /* local variables moved into u.co */
69528
69529 u.co.pVtab = pOp->p4.pVtab->pVtab;
69530 u.co.pName = &aMem[pOp->p1];
69531 assert( u.co.pVtab->pModule->xRename );
69532 assert( memIsValid(u.co.pName) );
69533 REGISTER_TRACE(pOp->p1, u.co.pName);
69534 assert( u.co.pName->flags & MEM_Str );
69535 rc = u.co.pVtab->pModule->xRename(u.co.pVtab, u.co.pName->z);
69536 importVtabErrMsg(p, u.co.pVtab);
69537 p->expired = 0;
69538
69539 break;
69540 }
69541 #endif
@@ -69510,45 +69563,45 @@
69563 ** P1 is a boolean flag. If it is set to true and the xUpdate call
69564 ** is successful, then the value returned by sqlite3_last_insert_rowid()
69565 ** is set to the value of the rowid for the row just inserted.
69566 */
69567 case OP_VUpdate: {
69568 #if 0 /* local variables moved into u.cp */
69569 sqlite3_vtab *pVtab;
69570 sqlite3_module *pModule;
69571 int nArg;
69572 int i;
69573 sqlite_int64 rowid;
69574 Mem **apArg;
69575 Mem *pX;
69576 #endif /* local variables moved into u.cp */
69577
69578 assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
69579 || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
69580 );
69581 u.cp.pVtab = pOp->p4.pVtab->pVtab;
69582 u.cp.pModule = (sqlite3_module *)u.cp.pVtab->pModule;
69583 u.cp.nArg = pOp->p2;
69584 assert( pOp->p4type==P4_VTAB );
69585 if( ALWAYS(u.cp.pModule->xUpdate) ){
69586 u8 vtabOnConflict = db->vtabOnConflict;
69587 u.cp.apArg = p->apArg;
69588 u.cp.pX = &aMem[pOp->p3];
69589 for(u.cp.i=0; u.cp.i<u.cp.nArg; u.cp.i++){
69590 assert( memIsValid(u.cp.pX) );
69591 memAboutToChange(p, u.cp.pX);
69592 sqlite3VdbeMemStoreType(u.cp.pX);
69593 u.cp.apArg[u.cp.i] = u.cp.pX;
69594 u.cp.pX++;
69595 }
69596 db->vtabOnConflict = pOp->p5;
69597 rc = u.cp.pModule->xUpdate(u.cp.pVtab, u.cp.nArg, u.cp.apArg, &u.cp.rowid);
69598 db->vtabOnConflict = vtabOnConflict;
69599 importVtabErrMsg(p, u.cp.pVtab);
69600 if( rc==SQLITE_OK && pOp->p1 ){
69601 assert( u.cp.nArg>1 && u.cp.apArg[0] && (u.cp.apArg[0]->flags&MEM_Null) );
69602 db->lastRowid = lastRowid = u.cp.rowid;
69603 }
69604 if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
69605 if( pOp->p5==OE_Ignore ){
69606 rc = SQLITE_OK;
69607 }else{
@@ -69604,25 +69657,25 @@
69657 **
69658 ** If tracing is enabled (by the sqlite3_trace()) interface, then
69659 ** the UTF-8 string contained in P4 is emitted on the trace callback.
69660 */
69661 case OP_Trace: {
69662 #if 0 /* local variables moved into u.cq */
69663 char *zTrace;
69664 char *z;
69665 #endif /* local variables moved into u.cq */
69666
69667 if( db->xTrace && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
69668 u.cq.z = sqlite3VdbeExpandSql(p, u.cq.zTrace);
69669 db->xTrace(db->pTraceArg, u.cq.z);
69670 sqlite3DbFree(db, u.cq.z);
69671 }
69672 #ifdef SQLITE_DEBUG
69673 if( (db->flags & SQLITE_SqlTrace)!=0
69674 && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
69675 ){
69676 sqlite3DebugPrintf("SQL-trace: %s\n", u.cq.zTrace);
69677 }
69678 #endif /* SQLITE_DEBUG */
69679 break;
69680 }
69681 #endif
@@ -70021,21 +70074,21 @@
70074 /* Make sure a mutex is held on the table to be accessed */
70075 sqlite3VdbeUsesBtree(v, iDb);
70076
70077 /* Configure the OP_TableLock instruction */
70078 #ifdef SQLITE_OMIT_SHARED_CACHE
70079 sqlite3VdbeChangeToNoop(v, 2);
70080 #else
70081 sqlite3VdbeChangeP1(v, 2, iDb);
70082 sqlite3VdbeChangeP2(v, 2, pTab->tnum);
70083 sqlite3VdbeChangeP3(v, 2, flags);
70084 sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
70085 #endif
70086
70087 /* Remove either the OP_OpenWrite or OpenRead. Set the P2
70088 ** parameter of the other to pTab->tnum. */
70089 sqlite3VdbeChangeToNoop(v, 4 - flags);
70090 sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
70091 sqlite3VdbeChangeP3(v, 3 + flags, iDb);
70092
70093 /* Configure the number of columns. Configure the cursor to
70094 ** think that the table has one more column than it really
@@ -70239,10 +70292,11 @@
70292
70293
70294 #ifndef SQLITE_OMIT_MERGE_SORT
70295
70296 typedef struct VdbeSorterIter VdbeSorterIter;
70297 typedef struct SorterRecord SorterRecord;
70298
70299 /*
70300 ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
70301 **
70302 ** As keys are added to the sorter, they are written to disk in a series
@@ -70310,19 +70364,22 @@
70364 ** In other words, each time we advance to the next sorter element, log2(N)
70365 ** key comparison operations are required, where N is the number of segments
70366 ** being merged (rounded up to the next power of 2).
70367 */
70368 struct VdbeSorter {
70369 int nInMemory; /* Current size of pRecord list as PMA */
 
70370 int nTree; /* Used size of aTree/aIter (power of 2) */
70371 VdbeSorterIter *aIter; /* Array of iterators to merge */
70372 int *aTree; /* Current state of incremental merge */
70373 i64 iWriteOff; /* Current write offset within file pTemp1 */
70374 i64 iReadOff; /* Current read offset within file pTemp1 */
70375 sqlite3_file *pTemp1; /* PMA file 1 */
70376 int nPMA; /* Number of PMAs stored in pTemp1 */
70377 SorterRecord *pRecord; /* Head of in-memory record list */
70378 int mnPmaSize; /* Minimum PMA size, in bytes */
70379 int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */
70380 UnpackedRecord *pUnpacked; /* Used to unpack keys */
70381 };
70382
70383 /*
70384 ** The following type is an iterator for a PMA. It caches the current key in
70385 ** variables nKey/aKey. If the iterator is at EOF, pFile==0.
@@ -70334,10 +70391,21 @@
70391 int nAlloc; /* Bytes of space at aAlloc */
70392 u8 *aAlloc; /* Allocated space */
70393 int nKey; /* Number of bytes in key */
70394 u8 *aKey; /* Pointer to current key */
70395 };
70396
70397 /*
70398 ** A structure to store a single record. All in-memory records are connected
70399 ** together into a linked list headed at VdbeSorter.pRecord using the
70400 ** SorterRecord.pNext pointer.
70401 */
70402 struct SorterRecord {
70403 void *pVal;
70404 int nVal;
70405 SorterRecord *pNext;
70406 };
70407
70408 /* Minimum allowable value for the VdbeSorter.nWorking variable */
70409 #define SORTER_MIN_WORKING 10
70410
70411 /* Maximum number of segments to merge in a single pass. */
@@ -70360,41 +70428,46 @@
70428 sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */
70429 VdbeSorterIter *pIter /* Iterator to advance */
70430 ){
70431 int rc; /* Return Code */
70432 int nRead; /* Number of bytes read */
70433 int nRec = 0; /* Size of record in bytes */
70434 int iOff = 0; /* Size of serialized size varint in bytes */
70435
70436 assert( pIter->iEof>=pIter->iReadOff );
70437 if( pIter->iEof-pIter->iReadOff>5 ){
70438 nRead = 5;
70439 }else{
70440 nRead = (int)(pIter->iEof - pIter->iReadOff);
70441 }
70442 if( nRead<=0 ){
70443 /* This is an EOF condition */
70444 vdbeSorterIterZero(db, pIter);
70445 return SQLITE_OK;
70446 }
70447
70448 rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
70449 if( rc==SQLITE_OK ){
70450 iOff = getVarint32(pIter->aAlloc, nRec);
70451 if( (iOff+nRec)>nRead ){
70452 int nRead2; /* Number of extra bytes to read */
70453 if( (iOff+nRec)>pIter->nAlloc ){
70454 int nNew = pIter->nAlloc*2;
70455 while( (iOff+nRec)>nNew ) nNew = nNew*2;
70456 pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
70457 if( !pIter->aAlloc ) return SQLITE_NOMEM;
70458 pIter->nAlloc = nNew;
70459 }
70460
70461 nRead2 = iOff + nRec - nRead;
70462 rc = sqlite3OsRead(
70463 pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
70464 );
70465 }
70466 }
70467
70468 assert( rc!=SQLITE_OK || nRec>0 );
70469 pIter->iReadOff += iOff+nRec;
70470 pIter->nKey = nRec;
70471 pIter->aKey = &pIter->aAlloc[iOff];
70472 return rc;
70473 }
@@ -70434,25 +70507,18 @@
70507 ** set to the integer value read. If an error occurs, the final values of
70508 ** both *piOffset and *piVal are undefined.
70509 */
70510 static int vdbeSorterReadVarint(
70511 sqlite3_file *pFile, /* File to read from */
 
70512 i64 *piOffset, /* IN/OUT: Read offset in pFile */
70513 i64 *piVal /* OUT: Value read from file */
70514 ){
70515 u8 aVarint[9]; /* Buffer large enough for a varint */
70516 i64 iOff = *piOffset; /* Offset in file to read from */
 
70517 int rc; /* Return code */
70518
70519 rc = sqlite3OsRead(pFile, aVarint, 9, iOff);
 
 
 
 
 
70520 if( rc==SQLITE_OK ){
70521 *piOffset += getVarint(aVarint, (u64 *)piVal);
70522 }
70523
70524 return rc;
@@ -70480,22 +70546,68 @@
70546 pIter->nAlloc = 128;
70547 pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
70548 if( !pIter->aAlloc ){
70549 rc = SQLITE_NOMEM;
70550 }else{
 
70551 i64 nByte; /* Total size of PMA in bytes */
70552 rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte);
70553 *pnByte += nByte;
70554 pIter->iEof = pIter->iReadOff + nByte;
70555 }
70556 if( rc==SQLITE_OK ){
70557 rc = vdbeSorterIterNext(db, pIter);
70558 }
70559 return rc;
70560 }
70561
70562
70563 /*
70564 ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
70565 ** size nKey2 bytes). Argument pKeyInfo supplies the collation functions
70566 ** used by the comparison. If an error occurs, return an SQLite error code.
70567 ** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive
70568 ** value, depending on whether key1 is smaller, equal to or larger than key2.
70569 **
70570 ** If the bOmitRowid argument is non-zero, assume both keys end in a rowid
70571 ** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid
70572 ** is true and key1 contains even a single NULL value, it is considered to
70573 ** be less than key2. Even if key2 also contains NULL values.
70574 **
70575 ** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
70576 ** has been allocated and contains an unpacked record that is used as key2.
70577 */
70578 static void vdbeSorterCompare(
70579 VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
70580 int bOmitRowid, /* Ignore rowid field at end of keys */
70581 void *pKey1, int nKey1, /* Left side of comparison */
70582 void *pKey2, int nKey2, /* Right side of comparison */
70583 int *pRes /* OUT: Result of comparison */
70584 ){
70585 KeyInfo *pKeyInfo = pCsr->pKeyInfo;
70586 VdbeSorter *pSorter = pCsr->pSorter;
70587 UnpackedRecord *r2 = pSorter->pUnpacked;
70588 int i;
70589
70590 if( pKey2 ){
70591 sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
70592 }
70593
70594 if( bOmitRowid ){
70595 r2->nField = pKeyInfo->nField;
70596 assert( r2->nField>0 );
70597 for(i=0; i<r2->nField; i++){
70598 if( r2->aMem[i].flags & MEM_Null ){
70599 *pRes = -1;
70600 return;
70601 }
70602 }
70603 r2->flags |= UNPACKED_PREFIX_MATCH;
70604 }
70605
70606 *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
70607 }
70608
70609 /*
70610 ** This function is called to compare two iterator keys when merging
70611 ** multiple b-tree segments. Parameter iOut is the index of the aTree[]
70612 ** value to recalculate.
70613 */
@@ -70523,24 +70635,20 @@
70635 if( p1->pFile==0 ){
70636 iRes = i2;
70637 }else if( p2->pFile==0 ){
70638 iRes = i1;
70639 }else{
70640 int res;
70641 assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */
70642 vdbeSorterCompare(
70643 pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
 
70644 );
70645 if( res<=0 ){
 
 
70646 iRes = i1;
70647 }else{
70648 iRes = i2;
70649 }
 
70650 }
70651
70652 pSorter->aTree[iOut] = iRes;
70653 return SQLITE_OK;
70654 }
@@ -70547,13 +70655,46 @@
70655
70656 /*
70657 ** Initialize the temporary index cursor just opened as a sorter cursor.
70658 */
70659 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
70660 int pgsz; /* Page size of main database */
70661 int mxCache; /* Cache size */
70662 VdbeSorter *pSorter; /* The new sorter */
70663 char *d; /* Dummy */
70664
70665 assert( pCsr->pKeyInfo && pCsr->pBt==0 );
70666 pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
70667 if( pSorter==0 ){
70668 return SQLITE_NOMEM;
70669 }
70670
70671 pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d);
70672 if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM;
70673 assert( pSorter->pUnpacked==(UnpackedRecord *)d );
70674
70675 if( !sqlite3TempInMemory(db) ){
70676 pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
70677 pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
70678 mxCache = db->aDb[0].pSchema->cache_size;
70679 if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
70680 pSorter->mxPmaSize = mxCache * pgsz;
70681 }
70682
70683 return SQLITE_OK;
70684 }
70685
70686 /*
70687 ** Free the list of sorted records starting at pRecord.
70688 */
70689 static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
70690 SorterRecord *p;
70691 SorterRecord *pNext;
70692 for(p=pRecord; p; p=pNext){
70693 pNext = p->pNext;
70694 sqlite3DbFree(db, p);
70695 }
70696 }
70697
70698 /*
70699 ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
70700 */
@@ -70568,10 +70709,12 @@
70709 sqlite3DbFree(db, pSorter->aIter);
70710 }
70711 if( pSorter->pTemp1 ){
70712 sqlite3OsCloseFree(pSorter->pTemp1);
70713 }
70714 vdbeSorterRecordFree(db, pSorter->pRecord);
70715 sqlite3DbFree(db, pSorter->pUnpacked);
70716 sqlite3DbFree(db, pSorter);
70717 pCsr->pSorter = 0;
70718 }
70719 }
70720
@@ -70587,14 +70730,86 @@
70730 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
70731 SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy
70732 );
70733 }
70734
70735 /*
70736 ** Merge the two sorted lists p1 and p2 into a single list.
70737 ** Set *ppOut to the head of the new list.
70738 */
70739 static void vdbeSorterMerge(
70740 VdbeCursor *pCsr, /* For pKeyInfo */
70741 SorterRecord *p1, /* First list to merge */
70742 SorterRecord *p2, /* Second list to merge */
70743 SorterRecord **ppOut /* OUT: Head of merged list */
70744 ){
70745 SorterRecord *pFinal = 0;
70746 SorterRecord **pp = &pFinal;
70747 void *pVal2 = p2 ? p2->pVal : 0;
70748
70749 while( p1 && p2 ){
70750 int res;
70751 vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
70752 if( res<=0 ){
70753 *pp = p1;
70754 pp = &p1->pNext;
70755 p1 = p1->pNext;
70756 pVal2 = 0;
70757 }else{
70758 *pp = p2;
70759 pp = &p2->pNext;
70760 p2 = p2->pNext;
70761 if( p2==0 ) break;
70762 pVal2 = p2->pVal;
70763 }
70764 }
70765 *pp = p1 ? p1 : p2;
70766 *ppOut = pFinal;
70767 }
70768
70769 /*
70770 ** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK
70771 ** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
70772 ** occurs.
70773 */
70774 static int vdbeSorterSort(VdbeCursor *pCsr){
70775 int i;
70776 SorterRecord **aSlot;
70777 SorterRecord *p;
70778 VdbeSorter *pSorter = pCsr->pSorter;
70779
70780 aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
70781 if( !aSlot ){
70782 return SQLITE_NOMEM;
70783 }
70784
70785 p = pSorter->pRecord;
70786 while( p ){
70787 SorterRecord *pNext = p->pNext;
70788 p->pNext = 0;
70789 for(i=0; aSlot[i]; i++){
70790 vdbeSorterMerge(pCsr, p, aSlot[i], &p);
70791 aSlot[i] = 0;
70792 }
70793 aSlot[i] = p;
70794 p = pNext;
70795 }
70796
70797 p = 0;
70798 for(i=0; i<64; i++){
70799 vdbeSorterMerge(pCsr, p, aSlot[i], &p);
70800 }
70801 pSorter->pRecord = p;
70802
70803 sqlite3_free(aSlot);
70804 return SQLITE_OK;
70805 }
70806
70807
70808 /*
70809 ** Write the current contents of the in-memory linked-list to a PMA. Return
70810 ** SQLITE_OK if successful, or an SQLite error code otherwise.
70811 **
70812 ** The format of a PMA is:
70813 **
70814 ** * A varint. This varint contains the total number of bytes of content
70815 ** in the PMA (not including the varint itself).
@@ -70601,153 +70816,111 @@
70816 **
70817 ** * One or more records packed end-to-end in order of ascending keys.
70818 ** Each record consists of a varint followed by a blob of data (the
70819 ** key). The varint is the number of bytes in the blob of data.
70820 */
70821 static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
70822 int rc = SQLITE_OK; /* Return code */
70823 VdbeSorter *pSorter = pCsr->pSorter;
 
70824
70825 if( pSorter->nInMemory==0 ){
70826 assert( pSorter->pRecord==0 );
70827 return rc;
70828 }
70829
70830 rc = vdbeSorterSort(pCsr);
70831
70832 /* If the first temporary PMA file has not been opened, open it now. */
70833 if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
70834 rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
70835 assert( rc!=SQLITE_OK || pSorter->pTemp1 );
70836 assert( pSorter->iWriteOff==0 );
70837 assert( pSorter->nPMA==0 );
70838 }
70839
70840 if( rc==SQLITE_OK ){
70841 i64 iOff = pSorter->iWriteOff;
70842 SorterRecord *p;
70843 SorterRecord *pNext = 0;
70844 static const char eightZeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
70845
70846 pSorter->nPMA++;
70847 rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nInMemory, &iOff);
70848 for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){
70849 pNext = p->pNext;
70850 rc = vdbeSorterWriteVarint(pSorter->pTemp1, p->nVal, &iOff);
70851
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70852 if( rc==SQLITE_OK ){
70853 rc = sqlite3OsWrite(pSorter->pTemp1, p->pVal, p->nVal, iOff);
70854 iOff += p->nVal;
 
 
 
 
70855 }
70856
70857 sqlite3DbFree(db, p);
70858 }
70859
70860 /* This assert verifies that unless an error has occurred, the size of
70861 ** the PMA on disk is the same as the expected size stored in
70862 ** pSorter->nInMemory. */
70863 assert( rc!=SQLITE_OK || pSorter->nInMemory==(
70864 iOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nInMemory)
70865 ));
70866
70867 pSorter->iWriteOff = iOff;
70868 if( rc==SQLITE_OK ){
70869 /* Terminate each file with 8 extra bytes so that from any offset
70870 ** in the file we can always read 9 bytes without a SHORT_READ error */
70871 rc = sqlite3OsWrite(pSorter->pTemp1, eightZeros, 8, iOff);
70872 }
70873 pSorter->pRecord = p;
70874 }
70875
 
70876 return rc;
70877 }
70878
70879 /*
70880 ** Add a record to the sorter.
 
 
 
 
 
 
 
 
 
 
70881 */
70882 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
70883 sqlite3 *db, /* Database handle */
70884 VdbeCursor *pCsr, /* Sorter cursor */
70885 Mem *pVal /* Memory cell containing record */
70886 ){
70887 VdbeSorter *pSorter = pCsr->pSorter;
70888 int rc = SQLITE_OK; /* Return Code */
70889 SorterRecord *pNew; /* New list element */
70890
70891 assert( pSorter );
70892 pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n;
70893
70894 pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord));
70895 if( pNew==0 ){
70896 rc = SQLITE_NOMEM;
70897 }else{
70898 pNew->pVal = (void *)&pNew[1];
70899 memcpy(pNew->pVal, pVal->z, pVal->n);
70900 pNew->nVal = pVal->n;
70901 pNew->pNext = pSorter->pRecord;
70902 pSorter->pRecord = pNew;
70903 }
70904
70905 /* See if the contents of the sorter should now be written out. They
70906 ** are written out when either of the following are true:
70907 **
70908 ** * The total memory allocated for the in-memory list is greater
70909 ** than (page-size * cache-size), or
70910 **
70911 ** * The total memory allocated for the in-memory list is greater
70912 ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
70913 */
70914 if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
70915 (pSorter->nInMemory>pSorter->mxPmaSize)
70916 || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
70917 )){
70918 rc = vdbeSorterListToPMA(db, pCsr);
70919 pSorter->nInMemory = 0;
70920 }
70921
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70922 return rc;
70923 }
70924
70925 /*
70926 ** Helper function for sqlite3VdbeSorterRewind().
@@ -70761,16 +70934,16 @@
70934 int rc = SQLITE_OK; /* Return code */
70935 int i; /* Used to iterator through aIter[] */
70936 i64 nByte = 0; /* Total bytes in all opened PMAs */
70937
70938 /* Initialize the iterators. */
70939 for(i=0; i<SORTER_MAX_MERGE_COUNT; i++){
70940 VdbeSorterIter *pIter = &pSorter->aIter[i];
70941 rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
70942 pSorter->iReadOff = pIter->iEof;
70943 assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff );
70944 if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break;
70945 }
70946
70947 /* Initialize the aTree[] array. */
70948 for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
70949 rc = vdbeSorterDoCompare(pCsr, i);
@@ -70793,18 +70966,22 @@
70966 int nByte; /* Bytes of space required for aIter/aTree */
70967 int N = 2; /* Power of 2 >= nIter */
70968
70969 assert( pSorter );
70970
70971 /* If no data has been written to disk, then do not do so now. Instead,
70972 ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
70973 ** from the in-memory list. */
 
70974 if( pSorter->nPMA==0 ){
70975 *pbEof = !pSorter->pRecord;
70976 assert( pSorter->aTree==0 );
70977 return vdbeSorterSort(pCsr);
70978 }
70979
70980 /* Write the current b-tree to a PMA. Close the b-tree cursor. */
70981 rc = vdbeSorterListToPMA(db, pCsr);
70982 if( rc!=SQLITE_OK ) return rc;
70983
70984 /* Allocate space for aIter[] and aTree[]. */
70985 nIter = pSorter->nPMA;
70986 if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
70987 assert( nIter>0 );
@@ -70888,47 +71065,94 @@
71065 /*
71066 ** Advance to the next element in the sorter.
71067 */
71068 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
71069 VdbeSorter *pSorter = pCsr->pSorter;
 
 
71070 int rc; /* Return code */
71071
71072 if( pSorter->aTree ){
71073 int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
71074 int i; /* Index of aTree[] to recalculate */
71075
71076 rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
71077 for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
71078 rc = vdbeSorterDoCompare(pCsr, i);
71079 }
71080
71081 *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
71082 }else{
71083 SorterRecord *pFree = pSorter->pRecord;
71084 pSorter->pRecord = pFree->pNext;
71085 pFree->pNext = 0;
71086 vdbeSorterRecordFree(db, pFree);
71087 *pbEof = !pSorter->pRecord;
71088 rc = SQLITE_OK;
71089 }
71090 return rc;
71091 }
71092
71093 /*
71094 ** Return a pointer to a buffer owned by the sorter that contains the
71095 ** current key.
71096 */
71097 static void *vdbeSorterRowkey(
71098 VdbeSorter *pSorter, /* Sorter object */
71099 int *pnKey /* OUT: Size of current key in bytes */
71100 ){
71101 void *pKey;
71102 if( pSorter->aTree ){
71103 VdbeSorterIter *pIter;
71104 pIter = &pSorter->aIter[ pSorter->aTree[1] ];
71105 *pnKey = pIter->nKey;
71106 pKey = pIter->aKey;
71107 }else{
71108 *pnKey = pSorter->pRecord->nVal;
71109 pKey = pSorter->pRecord->pVal;
71110 }
71111 return pKey;
71112 }
71113
71114 /*
71115 ** Copy the current sorter key into the memory cell pOut.
71116 */
71117 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
71118 VdbeSorter *pSorter = pCsr->pSorter;
71119 void *pKey; int nKey; /* Sorter key to copy into pOut */
71120
71121 pKey = vdbeSorterRowkey(pSorter, &nKey);
71122 if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){
 
 
 
 
 
 
 
71123 return SQLITE_NOMEM;
71124 }
71125 pOut->n = nKey;
71126 MemSetTypeFlag(pOut, MEM_Blob);
71127 memcpy(pOut->z, pKey, nKey);
71128
71129 return SQLITE_OK;
71130 }
71131
71132 /*
71133 ** Compare the key in memory cell pVal with the key that the sorter cursor
71134 ** passed as the first argument currently points to. For the purposes of
71135 ** the comparison, ignore the rowid field at the end of each record.
71136 **
71137 ** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
71138 ** Otherwise, set *pRes to a negative, zero or positive value if the
71139 ** key in pVal is smaller than, equal to or larger than the current sorter
71140 ** key.
71141 */
71142 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
71143 VdbeCursor *pCsr, /* Sorter cursor */
71144 Mem *pVal, /* Value to compare to current sorter key */
71145 int *pRes /* OUT: Result of comparison */
71146 ){
71147 VdbeSorter *pSorter = pCsr->pSorter;
71148 void *pKey; int nKey; /* Sorter key to compare pVal with */
71149
71150 pKey = vdbeSorterRowkey(pSorter, &nKey);
71151 vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
71152 return SQLITE_OK;
71153 }
71154
71155 #endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
71156
71157 /************** End of vdbesort.c ********************************************/
71158 /************** Begin file journal.c *****************************************/
@@ -73691,11 +73915,12 @@
73915 pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
73916 pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
73917 pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
73918 pNewItem->jointype = pOldItem->jointype;
73919 pNewItem->iCursor = pOldItem->iCursor;
73920 pNewItem->addrFillSub = pOldItem->addrFillSub;
73921 pNewItem->regReturn = pOldItem->regReturn;
73922 pNewItem->isCorrelated = pOldItem->isCorrelated;
73923 pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
73924 pNewItem->notIndexed = pOldItem->notIndexed;
73925 pNewItem->pIndex = pOldItem->pIndex;
73926 pTab = pNewItem->pTab = pOldItem->pTab;
@@ -74251,12 +74476,11 @@
74476 assert(v);
74477 if( iCol<0 ){
74478 int iMem = ++pParse->nMem;
74479 int iAddr;
74480
74481 iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
 
74482
74483 sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
74484 eType = IN_INDEX_ROWID;
74485
74486 sqlite3VdbeJumpHere(v, iAddr);
@@ -74283,12 +74507,11 @@
74507 int iMem = ++pParse->nMem;
74508 int iAddr;
74509 char *pKey;
74510
74511 pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
74512 iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
 
74513
74514 sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
74515 pKey,P4_KEYINFO_HANDOFF);
74516 VdbeComment((v, "%s", pIdx->zName));
74517 eType = IN_INDEX_INDEX;
@@ -74365,11 +74588,11 @@
74588 Parse *pParse, /* Parsing context */
74589 Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
74590 int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
74591 int isRowid /* If true, LHS of IN operator is a rowid */
74592 ){
74593 int testAddr = -1; /* One-time test address */
74594 int rReg = 0; /* Register storing resulting */
74595 Vdbe *v = sqlite3GetVdbe(pParse);
74596 if( NEVER(v==0) ) return 0;
74597 sqlite3ExprCachePush(pParse);
74598
@@ -74383,19 +74606,17 @@
74606 ** If all of the above are false, then we can run this code just once
74607 ** save the results, and reuse the same result on subsequent invocations.
74608 */
74609 if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
74610 int mem = ++pParse->nMem;
74611 testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
 
 
74612 }
74613
74614 #ifndef SQLITE_OMIT_EXPLAIN
74615 if( pParse->explain==2 ){
74616 char *zMsg = sqlite3MPrintf(
74617 pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
74618 pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
74619 );
74620 sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
74621 }
74622 #endif
@@ -74483,13 +74704,13 @@
74704 /* If the expression is not constant then we will need to
74705 ** disable the test that was generated above that makes sure
74706 ** this code only executes once. Because for a non-constant
74707 ** expression we need to rerun this code each time.
74708 */
74709 if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
74710 sqlite3VdbeChangeToNoop(v, testAddr);
74711 testAddr = -1;
74712 }
74713
74714 /* Evaluate the expression and insert it into the temp table */
74715 if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
74716 sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
@@ -74554,12 +74775,12 @@
74775 ExprSetIrreducible(pExpr);
74776 break;
74777 }
74778 }
74779
74780 if( testAddr>=0 ){
74781 sqlite3VdbeJumpHere(v, testAddr);
74782 }
74783 sqlite3ExprCachePop(pParse, 1);
74784
74785 return rReg;
74786 }
@@ -75077,11 +75298,11 @@
75298 if( !pAggInfo->directMode ){
75299 assert( pCol->iMem>0 );
75300 inReg = pCol->iMem;
75301 break;
75302 }else if( pAggInfo->useSortingIdx ){
75303 sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
75304 pCol->iSorterColumn, target);
75305 break;
75306 }
75307 /* Otherwise, fall thru into the TK_COLUMN case */
75308 }
@@ -81235,27 +81456,19 @@
81456 Table *pTab = pIndex->pTable; /* The table that is indexed */
81457 int iTab = pParse->nTab++; /* Btree cursor used for pTab */
81458 int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
81459 int iSorter = iTab; /* Cursor opened by OpenSorter (if in use) */
81460 int addr1; /* Address of top of loop */
81461 int addr2; /* Address to jump to for next iteration */
81462 int tnum; /* Root page of index */
81463 Vdbe *v; /* Generate code into this virtual machine */
81464 KeyInfo *pKey; /* KeyInfo for index */
81465 int regIdxKey; /* Registers containing the index key */
81466 int regRecord; /* Register holding assemblied index record */
81467 sqlite3 *db = pParse->db; /* The database connection */
81468 int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
81469
 
 
 
 
 
 
 
 
 
81470 #ifndef SQLITE_OMIT_AUTHORIZATION
81471 if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
81472 db->aDb[iDb].zName ) ){
81473 return;
81474 }
@@ -81277,32 +81490,44 @@
81490 (char *)pKey, P4_KEYINFO_HANDOFF);
81491 if( memRootPage>=0 ){
81492 sqlite3VdbeChangeP5(v, 1);
81493 }
81494
81495 #ifndef SQLITE_OMIT_MERGE_SORT
81496 /* Open the sorter cursor if we are to use one. */
81497 iSorter = pParse->nTab++;
81498 sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
81499 #endif
 
 
81500
81501 /* Open the table. Loop through all rows of the table, inserting index
81502 ** records into the sorter. */
81503 sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
81504 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
81505 addr2 = addr1 + 1;
81506 regRecord = sqlite3GetTempReg(pParse);
81507 regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
81508
81509 #ifndef SQLITE_OMIT_MERGE_SORT
81510 sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
81511 sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
81512 sqlite3VdbeJumpHere(v, addr1);
81513 addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
81514 if( pIndex->onError!=OE_None ){
81515 int j2 = sqlite3VdbeCurrentAddr(v) + 3;
81516 sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
81517 addr2 = sqlite3VdbeCurrentAddr(v);
81518 sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
81519 sqlite3HaltConstraint(
81520 pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
81521 );
81522 }else{
81523 addr2 = sqlite3VdbeCurrentAddr(v);
81524 }
81525 sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
81526 sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
81527 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
81528 #else
81529 if( pIndex->onError!=OE_None ){
81530 const int regRowid = regIdxKey + pIndex->nColumn;
81531 const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
81532 void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
81533
@@ -81317,14 +81542,15 @@
81542 */
81543 sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
81544 sqlite3HaltConstraint(
81545 pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
81546 }
81547 sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
81548 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
81549 #endif
81550 sqlite3ReleaseTempReg(pParse, regRecord);
81551 sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
81552 sqlite3VdbeJumpHere(v, addr1);
81553
81554 sqlite3VdbeAddOp1(v, OP_Close, iTab);
81555 sqlite3VdbeAddOp1(v, OP_Close, iIdx);
81556 sqlite3VdbeAddOp1(v, OP_Close, iSorter);
@@ -92204,10 +92430,12 @@
92430 pNew->addrOpenEphm[2] = -1;
92431 if( db->mallocFailed ) {
92432 clearSelect(db, pNew);
92433 if( pNew!=&standin ) sqlite3DbFree(db, pNew);
92434 pNew = 0;
92435 }else{
92436 assert( pNew->pSrc!=0 || pParse->nErr>0 );
92437 }
92438 return pNew;
92439 }
92440
92441 /*
@@ -92534,16 +92762,22 @@
92762 ){
92763 Vdbe *v = pParse->pVdbe;
92764 int nExpr = pOrderBy->nExpr;
92765 int regBase = sqlite3GetTempRange(pParse, nExpr+2);
92766 int regRecord = sqlite3GetTempReg(pParse);
92767 int op;
92768 sqlite3ExprCacheClear(pParse);
92769 sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
92770 sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
92771 sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
92772 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
92773 if( pSelect->selFlags & SF_UseSorter ){
92774 op = OP_SorterInsert;
92775 }else{
92776 op = OP_IdxInsert;
92777 }
92778 sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
92779 sqlite3ReleaseTempReg(pParse, regRecord);
92780 sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
92781 if( pSelect->iLimit ){
92782 int addr1, addr2;
92783 int iLimit;
@@ -93008,13 +93242,24 @@
93242 sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
93243 regRowid = 0;
93244 }else{
93245 regRowid = sqlite3GetTempReg(pParse);
93246 }
93247 if( p->selFlags & SF_UseSorter ){
93248 int regSortOut = ++pParse->nMem;
93249 int ptab2 = pParse->nTab++;
93250 sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
93251 addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
93252 codeOffset(v, p, addrContinue);
93253 sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
93254 sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
93255 sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
93256 }else{
93257 addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
93258 codeOffset(v, p, addrContinue);
93259 sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
93260 }
93261 switch( eDest ){
93262 case SRT_Table:
93263 case SRT_EphemTab: {
93264 testcase( eDest==SRT_Table );
93265 testcase( eDest==SRT_EphemTab );
@@ -93063,11 +93308,15 @@
93308 sqlite3ReleaseTempReg(pParse, regRowid);
93309
93310 /* The bottom of the loop
93311 */
93312 sqlite3VdbeResolveLabel(v, addrContinue);
93313 if( p->selFlags & SF_UseSorter ){
93314 sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr);
93315 }else{
93316 sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
93317 }
93318 sqlite3VdbeResolveLabel(v, addrBreak);
93319 if( eDest==SRT_Output || eDest==SRT_Coroutine ){
93320 sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
93321 }
93322 }
@@ -95895,11 +96144,15 @@
96144 struct SrcList_item *pItem = &pTabList->a[i];
96145 SelectDest dest;
96146 Select *pSub = pItem->pSelect;
96147 int isAggSub;
96148
96149 if( pSub==0 ) continue;
96150 if( pItem->addrFillSub ){
96151 sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
96152 continue;
96153 }
96154
96155 /* Increment Parse.nHeight by the height of the largest expression
96156 ** tree refered to by this, the parent select. The child select
96157 ** may contain expression trees of at most
96158 ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
@@ -95906,25 +96159,48 @@
96159 ** more conservative than necessary, but much easier than enforcing
96160 ** an exact limit.
96161 */
96162 pParse->nHeight += sqlite3SelectExprHeight(p);
96163
 
96164 isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
96165 if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
96166 /* This subquery can be absorbed into its parent. */
96167 if( isAggSub ){
96168 isAgg = 1;
96169 p->selFlags |= SF_Aggregate;
96170 }
96171 i = -1;
96172 }else{
96173 /* Generate a subroutine that will fill an ephemeral table with
96174 ** the content of this subquery. pItem->addrFillSub will point
96175 ** to the address of the generated subroutine. pItem->regReturn
96176 ** is a register allocated to hold the subroutine return address
96177 */
96178 int topAddr;
96179 int onceAddr = 0;
96180 int retAddr;
96181 assert( pItem->addrFillSub==0 );
96182 pItem->regReturn = ++pParse->nMem;
96183 topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
96184 pItem->addrFillSub = topAddr+1;
96185 VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
96186 if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
96187 /* If the subquery is no correlated and if we are not inside of
96188 ** a trigger, then we only need to compute the value of the subquery
96189 ** once. */
96190 int regOnce = ++pParse->nMem;
96191 onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
96192 }
96193 sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
 
96194 explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
96195 sqlite3Select(pParse, pSub, &dest);
 
96196 pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
96197 if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
96198 retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
96199 VdbeComment((v, "end %s", pItem->pTab->zName));
96200 sqlite3VdbeChangeP1(v, topAddr, retAddr);
96201
96202 }
96203 if( /*pParse->nErr ||*/ db->mallocFailed ){
96204 goto select_end;
96205 }
96206 pParse->nHeight -= sqlite3SelectExprHeight(p);
@@ -96029,10 +96305,14 @@
96305 /* Set the limiter.
96306 */
96307 iEnd = sqlite3VdbeMakeLabel(v);
96308 p->nSelectRow = (double)LARGEST_INT64;
96309 computeLimitRegisters(pParse, p, iEnd);
96310 if( p->iLimit==0 && addrSortIndex>=0 ){
96311 sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
96312 p->selFlags |= SF_UseSorter;
96313 }
96314
96315 /* Open a virtual index to use for the distinct set.
96316 */
96317 if( p->selFlags & SF_Distinct ){
96318 KeyInfo *pKeyInfo;
@@ -96057,18 +96337,18 @@
96337 /* If sorting index that was created by a prior OP_OpenEphemeral
96338 ** instruction ended up not being needed, then change the OP_OpenEphemeral
96339 ** into an OP_Noop.
96340 */
96341 if( addrSortIndex>=0 && pOrderBy==0 ){
96342 sqlite3VdbeChangeToNoop(v, addrSortIndex);
96343 p->addrOpenEphm[2] = -1;
96344 }
96345
96346 if( pWInfo->eDistinct ){
96347 VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
96348
96349 assert( addrDistinctIndex>=0 );
96350 pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
96351
96352 assert( isDistinct );
96353 assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
96354 || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
@@ -96123,10 +96403,12 @@
96403 ** one row of the input to the aggregator has been
96404 ** processed */
96405 int iAbortFlag; /* Mem address which causes query abort if positive */
96406 int groupBySort; /* Rows come from source in GROUP BY order */
96407 int addrEnd; /* End of processing for this SELECT */
96408 int sortPTab = 0; /* Pseudotable used to decode sorting results */
96409 int sortOut = 0; /* Output register from the sorter */
96410
96411 /* Remove any and all aliases between the result set and the
96412 ** GROUP BY clause.
96413 */
96414 if( pGroupBy ){
@@ -96184,16 +96466,16 @@
96466 int addrReset; /* Subroutine for resetting the accumulator */
96467 int regReset; /* Return address register for reset subroutine */
96468
96469 /* If there is a GROUP BY clause we might need a sorting index to
96470 ** implement it. Allocate that sorting index now. If it turns out
96471 ** that we do not need it after all, the OP_SorterOpen instruction
96472 ** will be converted into a Noop.
96473 */
96474 sAggInfo.sortingIdx = pParse->nTab++;
96475 pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
96476 addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
96477 sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
96478 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
96479
96480 /* Initialize memory locations used by GROUP BY aggregate processing
96481 */
@@ -96270,15 +96552,18 @@
96552 j++;
96553 }
96554 }
96555 regRecord = sqlite3GetTempReg(pParse);
96556 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
96557 sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
96558 sqlite3ReleaseTempReg(pParse, regRecord);
96559 sqlite3ReleaseTempRange(pParse, regBase, nCol);
96560 sqlite3WhereEnd(pWInfo);
96561 sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
96562 sortOut = sqlite3GetTempReg(pParse);
96563 sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
96564 sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
96565 VdbeComment((v, "GROUP BY sort"));
96566 sAggInfo.useSortingIdx = 1;
96567 sqlite3ExprCacheClear(pParse);
96568 }
96569
@@ -96287,13 +96572,17 @@
96572 ** Then compare the current GROUP BY terms against the GROUP BY terms
96573 ** from the previous row currently stored in a0, a1, a2...
96574 */
96575 addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
96576 sqlite3ExprCacheClear(pParse);
96577 if( groupBySort ){
96578 sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
96579 }
96580 for(j=0; j<pGroupBy->nExpr; j++){
96581 if( groupBySort ){
96582 sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
96583 if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
96584 }else{
96585 sAggInfo.directMode = 1;
96586 sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
96587 }
96588 }
@@ -96328,14 +96617,14 @@
96617 VdbeComment((v, "indicate data in accumulator"));
96618
96619 /* End of the loop
96620 */
96621 if( groupBySort ){
96622 sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
96623 }else{
96624 sqlite3WhereEnd(pWInfo);
96625 sqlite3VdbeChangeToNoop(v, addrSortingIdx);
96626 }
96627
96628 /* Output the final row of result
96629 */
96630 sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
@@ -100517,15 +100806,23 @@
100806 return mask;
100807 }
100808 static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
100809 Bitmask mask = 0;
100810 while( pS ){
100811 SrcList *pSrc = pS->pSrc;
100812 mask |= exprListTableUsage(pMaskSet, pS->pEList);
100813 mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
100814 mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
100815 mask |= exprTableUsage(pMaskSet, pS->pWhere);
100816 mask |= exprTableUsage(pMaskSet, pS->pHaving);
100817 if( ALWAYS(pSrc!=0) ){
100818 int i;
100819 for(i=0; i<pSrc->nSrc; i++){
100820 mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
100821 mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
100822 }
100823 }
100824 pS = pS->pPrior;
100825 }
100826 return mask;
100827 }
100828
@@ -102044,12 +102341,11 @@
102341 /* Generate code to skip over the creation and initialization of the
102342 ** transient index on 2nd and subsequent iterations of the loop. */
102343 v = pParse->pVdbe;
102344 assert( v!=0 );
102345 regIsInit = ++pParse->nMem;
102346 addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
 
102347
102348 /* Count the number of columns that will be added to the index
102349 ** and used to match WHERE clause constraints */
102350 nColumn = 0;
102351 pTable = pSrc->pTab;
@@ -115981,11 +116277,41 @@
116277 char *aOut;
116278 int bFirstOut = 0;
116279
116280 *paOut = 0;
116281 *pnOut = 0;
116282
116283 /* Allocate space for the output. Both the input and output doclists
116284 ** are delta encoded. If they are in ascending order (bDescDoclist==0),
116285 ** then the first docid in each list is simply encoded as a varint. For
116286 ** each subsequent docid, the varint stored is the difference between the
116287 ** current and previous docid (a positive number - since the list is in
116288 ** ascending order).
116289 **
116290 ** The first docid written to the output is therefore encoded using the
116291 ** same number of bytes as it is in whichever of the input lists it is
116292 ** read from. And each subsequent docid read from the same input list
116293 ** consumes either the same or less bytes as it did in the input (since
116294 ** the difference between it and the previous value in the output must
116295 ** be a positive value less than or equal to the delta value read from
116296 ** the input list). The same argument applies to all but the first docid
116297 ** read from the 'other' list. And to the contents of all position lists
116298 ** that will be copied and merged from the input to the output.
116299 **
116300 ** However, if the first docid copied to the output is a negative number,
116301 ** then the encoding of the first docid from the 'other' input list may
116302 ** be larger in the output than it was in the input (since the delta value
116303 ** may be a larger positive integer than the actual docid).
116304 **
116305 ** The space required to store the output is therefore the sum of the
116306 ** sizes of the two inputs, plus enough space for exactly one of the input
116307 ** docids to grow.
116308 **
116309 ** A symetric argument may be made if the doclists are in descending
116310 ** order.
116311 */
116312 aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
116313 if( !aOut ) return SQLITE_NOMEM;
116314
116315 p = aOut;
116316 fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
116317 fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
@@ -116008,10 +116334,11 @@
116334 }
116335 }
116336
116337 *paOut = aOut;
116338 *pnOut = (p-aOut);
116339 assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
116340 return SQLITE_OK;
116341 }
116342
116343 /*
116344 ** This function does a "phrase" merge of two doclists. In a phrase merge,
116345
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110110
#define SQLITE_VERSION "3.7.8"
111111
#define SQLITE_VERSION_NUMBER 3007008
112
-#define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
112
+#define SQLITE_SOURCE_ID "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
118118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.8"
111 #define SQLITE_VERSION_NUMBER 3007008
112 #define SQLITE_SOURCE_ID "2011-08-29 11:56:14 639cc85a911454bffdcccb33f2976c683953ae64"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
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-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
+11 -11
--- src/stash.c
+++ src/stash.c
@@ -89,11 +89,11 @@
8989
int rid = db_column_int(&q, 3);
9090
const char *zName = db_column_text(&q, 4);
9191
const char *zOrig = db_column_text(&q, 5);
9292
char *zPath = mprintf("%s%s", g.zLocalRoot, zName);
9393
Blob content;
94
- int isNewLink = file_islink(zPath);
94
+ int isNewLink = file_wd_islink(zPath);
9595
9696
db_bind_int(&ins, ":rid", rid);
9797
db_bind_int(&ins, ":isadd", rid==0);
9898
db_bind_int(&ins, ":isrm", deleted);
9999
db_bind_int(&ins, ":isexe", db_column_int(&q, 1));
@@ -200,18 +200,18 @@
200200
undo_save(zNew);
201201
blob_zero(&delta);
202202
if( rid==0 ){
203203
db_ephemeral_blob(&q, 6, &delta);
204204
blob_write_to_file(&delta, zNPath);
205
- file_setexe(zNPath, isExec);
205
+ file_wd_setexe(zNPath, isExec);
206206
fossil_print("ADD %s\n", zNew);
207207
}else if( isRemoved ){
208208
fossil_print("DELETE %s\n", zOrig);
209209
file_delete(zOPath);
210210
}else{
211211
Blob a, b, out, disk;
212
- int isNewLink = file_islink(zOPath);
212
+ int isNewLink = file_wd_islink(zOPath);
213213
db_ephemeral_blob(&q, 6, &delta);
214214
if( isNewLink ){
215215
blob_read_link(&disk, zOPath);
216216
}else{
217217
blob_read_from_file(&disk, zOPath);
@@ -218,31 +218,31 @@
218218
}
219219
content_get(rid, &a);
220220
blob_delta_apply(&a, &delta, &b);
221221
if( blob_compare(&disk, &a)==0 && isLink == isNewLink ){
222222
if( isLink || isNewLink ){
223
- unlink(zNPath);
223
+ file_delete(zNPath);
224224
}
225225
if( isLink ){
226
- create_symlink(blob_str(&b), zNPath);
226
+ symlink_create(blob_str(&b), zNPath);
227227
}else{
228228
blob_write_to_file(&b, zNPath);
229229
}
230
- file_setexe(zNPath, isExec);
230
+ file_wd_setexe(zNPath, isExec);
231231
fossil_print("UPDATE %s\n", zNew);
232232
}else{
233233
int rc;
234234
if( isLink || isNewLink ){
235235
rc = -1;
236236
blob_zero(&b); /* because we reset it later */
237
- //TODO(dchest): write something to disk?
237
+ fossil_print("***** Cannot merge symlink %s\n", zNew);
238238
}else{
239239
rc = merge_3way(&a, zOPath, &b, &out);
240240
blob_write_to_file(&out, zNPath);
241
- //blob_reset(&out); //XXX(dchest): Need this?
241
+ blob_reset(&out);
242
+ file_wd_setexe(zNPath, isExec);
242243
}
243
- file_setexe(zNPath, isExec);
244244
if( rc ){
245245
fossil_print("CONFLICT %s\n", zNew);
246246
nConflict++;
247247
}else{
248248
fossil_print("MERGE %s\n", zNew);
@@ -290,20 +290,20 @@
290290
fossil_print("ADDED %s\n", zNew);
291291
diff_print_index(zNew);
292292
diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
293293
}else if( isRemoved ){
294294
fossil_print("DELETE %s\n", zOrig);
295
- if( file_islink(zOPath) ){
295
+ if( file_wd_islink(zOPath) ){
296296
blob_read_link(&delta, zOPath);
297297
}else{
298298
blob_read_from_file(&delta, zOPath);
299299
}
300300
diff_print_index(zNew);
301301
diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
302302
}else{
303303
Blob a, b, disk;
304
- int isOrigLink = file_islink(zOPath);
304
+ int isOrigLink = file_wd_islink(zOPath);
305305
db_ephemeral_blob(&q, 6, &delta);
306306
if( isOrigLink ){
307307
blob_read_link(&disk, zOPath);
308308
}else{
309309
blob_read_from_file(&disk, zOPath);
310310
--- src/stash.c
+++ src/stash.c
@@ -89,11 +89,11 @@
89 int rid = db_column_int(&q, 3);
90 const char *zName = db_column_text(&q, 4);
91 const char *zOrig = db_column_text(&q, 5);
92 char *zPath = mprintf("%s%s", g.zLocalRoot, zName);
93 Blob content;
94 int isNewLink = file_islink(zPath);
95
96 db_bind_int(&ins, ":rid", rid);
97 db_bind_int(&ins, ":isadd", rid==0);
98 db_bind_int(&ins, ":isrm", deleted);
99 db_bind_int(&ins, ":isexe", db_column_int(&q, 1));
@@ -200,18 +200,18 @@
200 undo_save(zNew);
201 blob_zero(&delta);
202 if( rid==0 ){
203 db_ephemeral_blob(&q, 6, &delta);
204 blob_write_to_file(&delta, zNPath);
205 file_setexe(zNPath, isExec);
206 fossil_print("ADD %s\n", zNew);
207 }else if( isRemoved ){
208 fossil_print("DELETE %s\n", zOrig);
209 file_delete(zOPath);
210 }else{
211 Blob a, b, out, disk;
212 int isNewLink = file_islink(zOPath);
213 db_ephemeral_blob(&q, 6, &delta);
214 if( isNewLink ){
215 blob_read_link(&disk, zOPath);
216 }else{
217 blob_read_from_file(&disk, zOPath);
@@ -218,31 +218,31 @@
218 }
219 content_get(rid, &a);
220 blob_delta_apply(&a, &delta, &b);
221 if( blob_compare(&disk, &a)==0 && isLink == isNewLink ){
222 if( isLink || isNewLink ){
223 unlink(zNPath);
224 }
225 if( isLink ){
226 create_symlink(blob_str(&b), zNPath);
227 }else{
228 blob_write_to_file(&b, zNPath);
229 }
230 file_setexe(zNPath, isExec);
231 fossil_print("UPDATE %s\n", zNew);
232 }else{
233 int rc;
234 if( isLink || isNewLink ){
235 rc = -1;
236 blob_zero(&b); /* because we reset it later */
237 //TODO(dchest): write something to disk?
238 }else{
239 rc = merge_3way(&a, zOPath, &b, &out);
240 blob_write_to_file(&out, zNPath);
241 //blob_reset(&out); //XXX(dchest): Need this?
 
242 }
243 file_setexe(zNPath, isExec);
244 if( rc ){
245 fossil_print("CONFLICT %s\n", zNew);
246 nConflict++;
247 }else{
248 fossil_print("MERGE %s\n", zNew);
@@ -290,20 +290,20 @@
290 fossil_print("ADDED %s\n", zNew);
291 diff_print_index(zNew);
292 diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
293 }else if( isRemoved ){
294 fossil_print("DELETE %s\n", zOrig);
295 if( file_islink(zOPath) ){
296 blob_read_link(&delta, zOPath);
297 }else{
298 blob_read_from_file(&delta, zOPath);
299 }
300 diff_print_index(zNew);
301 diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
302 }else{
303 Blob a, b, disk;
304 int isOrigLink = file_islink(zOPath);
305 db_ephemeral_blob(&q, 6, &delta);
306 if( isOrigLink ){
307 blob_read_link(&disk, zOPath);
308 }else{
309 blob_read_from_file(&disk, zOPath);
310
--- src/stash.c
+++ src/stash.c
@@ -89,11 +89,11 @@
89 int rid = db_column_int(&q, 3);
90 const char *zName = db_column_text(&q, 4);
91 const char *zOrig = db_column_text(&q, 5);
92 char *zPath = mprintf("%s%s", g.zLocalRoot, zName);
93 Blob content;
94 int isNewLink = file_wd_islink(zPath);
95
96 db_bind_int(&ins, ":rid", rid);
97 db_bind_int(&ins, ":isadd", rid==0);
98 db_bind_int(&ins, ":isrm", deleted);
99 db_bind_int(&ins, ":isexe", db_column_int(&q, 1));
@@ -200,18 +200,18 @@
200 undo_save(zNew);
201 blob_zero(&delta);
202 if( rid==0 ){
203 db_ephemeral_blob(&q, 6, &delta);
204 blob_write_to_file(&delta, zNPath);
205 file_wd_setexe(zNPath, isExec);
206 fossil_print("ADD %s\n", zNew);
207 }else if( isRemoved ){
208 fossil_print("DELETE %s\n", zOrig);
209 file_delete(zOPath);
210 }else{
211 Blob a, b, out, disk;
212 int isNewLink = file_wd_islink(zOPath);
213 db_ephemeral_blob(&q, 6, &delta);
214 if( isNewLink ){
215 blob_read_link(&disk, zOPath);
216 }else{
217 blob_read_from_file(&disk, zOPath);
@@ -218,31 +218,31 @@
218 }
219 content_get(rid, &a);
220 blob_delta_apply(&a, &delta, &b);
221 if( blob_compare(&disk, &a)==0 && isLink == isNewLink ){
222 if( isLink || isNewLink ){
223 file_delete(zNPath);
224 }
225 if( isLink ){
226 symlink_create(blob_str(&b), zNPath);
227 }else{
228 blob_write_to_file(&b, zNPath);
229 }
230 file_wd_setexe(zNPath, isExec);
231 fossil_print("UPDATE %s\n", zNew);
232 }else{
233 int rc;
234 if( isLink || isNewLink ){
235 rc = -1;
236 blob_zero(&b); /* because we reset it later */
237 fossil_print("***** Cannot merge symlink %s\n", zNew);
238 }else{
239 rc = merge_3way(&a, zOPath, &b, &out);
240 blob_write_to_file(&out, zNPath);
241 blob_reset(&out);
242 file_wd_setexe(zNPath, isExec);
243 }
 
244 if( rc ){
245 fossil_print("CONFLICT %s\n", zNew);
246 nConflict++;
247 }else{
248 fossil_print("MERGE %s\n", zNew);
@@ -290,20 +290,20 @@
290 fossil_print("ADDED %s\n", zNew);
291 diff_print_index(zNew);
292 diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
293 }else if( isRemoved ){
294 fossil_print("DELETE %s\n", zOrig);
295 if( file_wd_islink(zOPath) ){
296 blob_read_link(&delta, zOPath);
297 }else{
298 blob_read_from_file(&delta, zOPath);
299 }
300 diff_print_index(zNew);
301 diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
302 }else{
303 Blob a, b, disk;
304 int isOrigLink = file_wd_islink(zOPath);
305 db_ephemeral_blob(&q, 6, &delta);
306 if( isOrigLink ){
307 blob_read_link(&disk, zOPath);
308 }else{
309 blob_read_from_file(&disk, zOPath);
310
+55 -55
--- src/stat.c
+++ src/stat.c
@@ -30,82 +30,82 @@
3030
void stat_page(void){
3131
i64 t, fsize;
3232
int n, m;
3333
int szMax, szAvg;
3434
const char *zDb;
35
+ int brief;
3536
char zBuf[100];
3637
3738
login_check_credentials();
38
- if( !g.okRead ){ login_needed(); return; }
39
+ if( !g.perm.Read ){ login_needed(); return; }
40
+ brief = P("brief")!=0;
3941
style_header("Repository Statistics");
4042
@ <table class="label-value">
4143
@ <tr><th>Repository&nbsp;Size:</th><td>
4244
fsize = file_size(g.zRepositoryName);
4345
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", fsize);
4446
@ %s(zBuf) bytes
4547
@ </td></tr>
46
- @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
47
- n = db_int(0, "SELECT count(*) FROM blob");
48
- m = db_int(0, "SELECT count(*) FROM delta");
49
- @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
50
- @ </td></tr>
51
- if( n>0 ){
52
- int a, b;
53
- Stmt q;
54
- @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
55
- db_prepare(&q, "SELECT total(size), avg(size), max(size)"
56
- " FROM blob WHERE size>0");
57
- db_step(&q);
58
- t = db_column_int64(&q, 0);
59
- szAvg = db_column_int(&q, 1);
60
- szMax = db_column_int(&q, 2);
61
- db_finalize(&q);
62
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
63
- @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
64
- @ </td></tr>
65
- @ <tr><th>Compression&nbsp;Ratio:</th><td>
66
- if( t/fsize < 5 ){
67
- b = 10;
68
- fsize /= 10;
69
- }else{
70
- b = 1;
71
- }
72
- a = t/fsize;
73
- @ %d(a):%d(b)
74
- @ </td></tr>
75
- }
76
- @ <tr><th>Number&nbsp;Of&nbsp;Check-ins:</th><td>
77
- n = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
78
- @ %d(n)
79
- @ </td></tr>
80
- @ <tr><th>Number&nbsp;Of&nbsp;Files:</th><td>
81
- n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
82
- @ %d(n)
83
- @ </td></tr>
84
- @ <tr><th>Number&nbsp;Of&nbsp;Wiki&nbsp;Pages:</th><td>
85
- n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
86
- " WHERE +tagname GLOB 'wiki-*'");
87
- @ %d(n)
88
- @ </td></tr>
89
- @ <tr><th>Number&nbsp;Of&nbsp;Tickets:</th><td>
90
- n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
91
- " WHERE +tagname GLOB 'tkt-*'");
92
- @ %d(n)
93
- @ </td></tr>
48
+ if( !brief ){
49
+ @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
50
+ n = db_int(0, "SELECT count(*) FROM blob");
51
+ m = db_int(0, "SELECT count(*) FROM delta");
52
+ @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
53
+ @ </td></tr>
54
+ if( n>0 ){
55
+ int a, b;
56
+ Stmt q;
57
+ @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
58
+ db_prepare(&q, "SELECT total(size), avg(size), max(size)"
59
+ " FROM blob WHERE size>0");
60
+ db_step(&q);
61
+ t = db_column_int64(&q, 0);
62
+ szAvg = db_column_int(&q, 1);
63
+ szMax = db_column_int(&q, 2);
64
+ db_finalize(&q);
65
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
66
+ @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
67
+ @ </td></tr>
68
+ @ <tr><th>Compression&nbsp;Ratio:</th><td>
69
+ if( t/fsize < 5 ){
70
+ b = 10;
71
+ fsize /= 10;
72
+ }else{
73
+ b = 1;
74
+ }
75
+ a = t/fsize;
76
+ @ %d(a):%d(b)
77
+ @ </td></tr>
78
+ }
79
+ @ <tr><th>Number&nbsp;Of&nbsp;Check-ins:</th><td>
80
+ n = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
81
+ @ %d(n)
82
+ @ </td></tr>
83
+ @ <tr><th>Number&nbsp;Of&nbsp;Files:</th><td>
84
+ n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
85
+ @ %d(n)
86
+ @ </td></tr>
87
+ @ <tr><th>Number&nbsp;Of&nbsp;Wiki&nbsp;Pages:</th><td>
88
+ n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
89
+ " WHERE +tagname GLOB 'wiki-*'");
90
+ @ %d(n)
91
+ @ </td></tr>
92
+ @ <tr><th>Number&nbsp;Of&nbsp;Tickets:</th><td>
93
+ n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
94
+ " WHERE +tagname GLOB 'tkt-*'");
95
+ @ %d(n)
96
+ @ </td></tr>
97
+ }
9498
@ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
9599
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
96100
" + 0.99");
97101
@ %d(n) days
98102
sqlite3_snprintf(sizeof(zBuf), zBuf, "%.2f", n/365.24);
99103
@ or approximately %s(zBuf) years
100104
@ </td></tr>
101
- @ <tr><th>Project&nbsp;ID:</th><td>
102
- @ %h(db_get("project-code",""))
103
- @ </td></tr>
104
- @ <tr><th>Server&nbsp;ID:</th><td>
105
- @ %h(db_get("server-code",""))
106
- @ </td></tr>
105
+ @ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
106
+ @ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
107107
108108
@ <tr><th>Fossil&nbsp;Version:</th><td>
109109
@ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
110110
@ (%h(COMPILER_NAME))
111111
@ </td></tr>
112112
--- src/stat.c
+++ src/stat.c
@@ -30,82 +30,82 @@
30 void stat_page(void){
31 i64 t, fsize;
32 int n, m;
33 int szMax, szAvg;
34 const char *zDb;
 
35 char zBuf[100];
36
37 login_check_credentials();
38 if( !g.okRead ){ login_needed(); return; }
 
39 style_header("Repository Statistics");
40 @ <table class="label-value">
41 @ <tr><th>Repository&nbsp;Size:</th><td>
42 fsize = file_size(g.zRepositoryName);
43 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", fsize);
44 @ %s(zBuf) bytes
45 @ </td></tr>
46 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
47 n = db_int(0, "SELECT count(*) FROM blob");
48 m = db_int(0, "SELECT count(*) FROM delta");
49 @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
50 @ </td></tr>
51 if( n>0 ){
52 int a, b;
53 Stmt q;
54 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
55 db_prepare(&q, "SELECT total(size), avg(size), max(size)"
56 " FROM blob WHERE size>0");
57 db_step(&q);
58 t = db_column_int64(&q, 0);
59 szAvg = db_column_int(&q, 1);
60 szMax = db_column_int(&q, 2);
61 db_finalize(&q);
62 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
63 @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
64 @ </td></tr>
65 @ <tr><th>Compression&nbsp;Ratio:</th><td>
66 if( t/fsize < 5 ){
67 b = 10;
68 fsize /= 10;
69 }else{
70 b = 1;
71 }
72 a = t/fsize;
73 @ %d(a):%d(b)
74 @ </td></tr>
75 }
76 @ <tr><th>Number&nbsp;Of&nbsp;Check-ins:</th><td>
77 n = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
78 @ %d(n)
79 @ </td></tr>
80 @ <tr><th>Number&nbsp;Of&nbsp;Files:</th><td>
81 n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
82 @ %d(n)
83 @ </td></tr>
84 @ <tr><th>Number&nbsp;Of&nbsp;Wiki&nbsp;Pages:</th><td>
85 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
86 " WHERE +tagname GLOB 'wiki-*'");
87 @ %d(n)
88 @ </td></tr>
89 @ <tr><th>Number&nbsp;Of&nbsp;Tickets:</th><td>
90 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
91 " WHERE +tagname GLOB 'tkt-*'");
92 @ %d(n)
93 @ </td></tr>
 
 
94 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
95 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
96 " + 0.99");
97 @ %d(n) days
98 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.2f", n/365.24);
99 @ or approximately %s(zBuf) years
100 @ </td></tr>
101 @ <tr><th>Project&nbsp;ID:</th><td>
102 @ %h(db_get("project-code",""))
103 @ </td></tr>
104 @ <tr><th>Server&nbsp;ID:</th><td>
105 @ %h(db_get("server-code",""))
106 @ </td></tr>
107
108 @ <tr><th>Fossil&nbsp;Version:</th><td>
109 @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
110 @ (%h(COMPILER_NAME))
111 @ </td></tr>
112
--- src/stat.c
+++ src/stat.c
@@ -30,82 +30,82 @@
30 void stat_page(void){
31 i64 t, fsize;
32 int n, m;
33 int szMax, szAvg;
34 const char *zDb;
35 int brief;
36 char zBuf[100];
37
38 login_check_credentials();
39 if( !g.perm.Read ){ login_needed(); return; }
40 brief = P("brief")!=0;
41 style_header("Repository Statistics");
42 @ <table class="label-value">
43 @ <tr><th>Repository&nbsp;Size:</th><td>
44 fsize = file_size(g.zRepositoryName);
45 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", fsize);
46 @ %s(zBuf) bytes
47 @ </td></tr>
48 if( !brief ){
49 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
50 n = db_int(0, "SELECT count(*) FROM blob");
51 m = db_int(0, "SELECT count(*) FROM delta");
52 @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
53 @ </td></tr>
54 if( n>0 ){
55 int a, b;
56 Stmt q;
57 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
58 db_prepare(&q, "SELECT total(size), avg(size), max(size)"
59 " FROM blob WHERE size>0");
60 db_step(&q);
61 t = db_column_int64(&q, 0);
62 szAvg = db_column_int(&q, 1);
63 szMax = db_column_int(&q, 2);
64 db_finalize(&q);
65 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
66 @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
67 @ </td></tr>
68 @ <tr><th>Compression&nbsp;Ratio:</th><td>
69 if( t/fsize < 5 ){
70 b = 10;
71 fsize /= 10;
72 }else{
73 b = 1;
74 }
75 a = t/fsize;
76 @ %d(a):%d(b)
77 @ </td></tr>
78 }
79 @ <tr><th>Number&nbsp;Of&nbsp;Check-ins:</th><td>
80 n = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
81 @ %d(n)
82 @ </td></tr>
83 @ <tr><th>Number&nbsp;Of&nbsp;Files:</th><td>
84 n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
85 @ %d(n)
86 @ </td></tr>
87 @ <tr><th>Number&nbsp;Of&nbsp;Wiki&nbsp;Pages:</th><td>
88 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
89 " WHERE +tagname GLOB 'wiki-*'");
90 @ %d(n)
91 @ </td></tr>
92 @ <tr><th>Number&nbsp;Of&nbsp;Tickets:</th><td>
93 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
94 " WHERE +tagname GLOB 'tkt-*'");
95 @ %d(n)
96 @ </td></tr>
97 }
98 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
99 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
100 " + 0.99");
101 @ %d(n) days
102 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.2f", n/365.24);
103 @ or approximately %s(zBuf) years
104 @ </td></tr>
105 @ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
106 @ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
 
 
 
 
107
108 @ <tr><th>Fossil&nbsp;Version:</th><td>
109 @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
110 @ (%h(COMPILER_NAME))
111 @ </td></tr>
112
+2 -1
--- src/style.c
+++ src/style.c
@@ -805,10 +805,11 @@
805805
void page_test_env(void){
806806
char c;
807807
int i;
808808
char zCap[30];
809809
login_check_credentials();
810
+ if( !g.perm.Admin && !g.perm.Setup ){ login_needed(); return; }
810811
style_header("Environment Test");
811812
#if !defined(_WIN32)
812813
@ uid=%d(getuid()), gid=%d(getgid())<br />
813814
#endif
814815
@ g.zBaseURL = %h(g.zBaseURL)<br />
@@ -820,11 +821,11 @@
820821
@ g.userUid = %d(g.userUid)<br />
821822
@ g.zLogin = %h(g.zLogin)<br />
822823
@ capabilities = %s(zCap)<br />
823824
@ <hr>
824825
cgi_print_all();
825
- if( g.okSetup ){
826
+ if( g.perm.Setup ){
826827
const char *zRedir = P("redirect");
827828
if( zRedir ) cgi_redirect(zRedir);
828829
}
829830
style_footer();
830831
}
831832
--- src/style.c
+++ src/style.c
@@ -805,10 +805,11 @@
805 void page_test_env(void){
806 char c;
807 int i;
808 char zCap[30];
809 login_check_credentials();
 
810 style_header("Environment Test");
811 #if !defined(_WIN32)
812 @ uid=%d(getuid()), gid=%d(getgid())<br />
813 #endif
814 @ g.zBaseURL = %h(g.zBaseURL)<br />
@@ -820,11 +821,11 @@
820 @ g.userUid = %d(g.userUid)<br />
821 @ g.zLogin = %h(g.zLogin)<br />
822 @ capabilities = %s(zCap)<br />
823 @ <hr>
824 cgi_print_all();
825 if( g.okSetup ){
826 const char *zRedir = P("redirect");
827 if( zRedir ) cgi_redirect(zRedir);
828 }
829 style_footer();
830 }
831
--- src/style.c
+++ src/style.c
@@ -805,10 +805,11 @@
805 void page_test_env(void){
806 char c;
807 int i;
808 char zCap[30];
809 login_check_credentials();
810 if( !g.perm.Admin && !g.perm.Setup ){ login_needed(); return; }
811 style_header("Environment Test");
812 #if !defined(_WIN32)
813 @ uid=%d(getuid()), gid=%d(getgid())<br />
814 #endif
815 @ g.zBaseURL = %h(g.zBaseURL)<br />
@@ -820,11 +821,11 @@
821 @ g.userUid = %d(g.userUid)<br />
822 @ g.zLogin = %h(g.zLogin)<br />
823 @ capabilities = %s(zCap)<br />
824 @ <hr>
825 cgi_print_all();
826 if( g.perm.Setup ){
827 const char *zRedir = P("redirect");
828 if( zRedir ) cgi_redirect(zRedir);
829 }
830 style_footer();
831 }
832
+3 -3
--- src/tag.c
+++ src/tag.c
@@ -529,11 +529,11 @@
529529
*/
530530
void taglist_page(void){
531531
Stmt q;
532532
533533
login_check_credentials();
534
- if( !g.okRead ){
534
+ if( !g.perm.Read ){
535535
login_needed();
536536
}
537537
login_anonymous_available();
538538
style_header("Tags");
539539
style_submenu_element("Timeline", "Timeline", "tagtimeline");
@@ -548,11 +548,11 @@
548548
" ORDER BY tagname"
549549
);
550550
@ <ul>
551551
while( db_step(&q)==SQLITE_ROW ){
552552
const char *zName = db_column_text(&q, 0);
553
- if( g.okHistory ){
553
+ if( g.perm.History ){
554554
@ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)">
555555
@ %h(zName)</a></li>
556556
}else{
557557
@ <li><span class="tagDsp">%h(zName)</span></li>
558558
}
@@ -567,11 +567,11 @@
567567
*/
568568
void tagtimeline_page(void){
569569
Stmt q;
570570
571571
login_check_credentials();
572
- if( !g.okRead ){ login_needed(); return; }
572
+ if( !g.perm.Read ){ login_needed(); return; }
573573
574574
style_header("Tagged Check-ins");
575575
style_submenu_element("List", "List", "taglist");
576576
login_anonymous_available();
577577
@ <h2>Check-ins with non-propagating tags:</h2>
578578
--- src/tag.c
+++ src/tag.c
@@ -529,11 +529,11 @@
529 */
530 void taglist_page(void){
531 Stmt q;
532
533 login_check_credentials();
534 if( !g.okRead ){
535 login_needed();
536 }
537 login_anonymous_available();
538 style_header("Tags");
539 style_submenu_element("Timeline", "Timeline", "tagtimeline");
@@ -548,11 +548,11 @@
548 " ORDER BY tagname"
549 );
550 @ <ul>
551 while( db_step(&q)==SQLITE_ROW ){
552 const char *zName = db_column_text(&q, 0);
553 if( g.okHistory ){
554 @ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)">
555 @ %h(zName)</a></li>
556 }else{
557 @ <li><span class="tagDsp">%h(zName)</span></li>
558 }
@@ -567,11 +567,11 @@
567 */
568 void tagtimeline_page(void){
569 Stmt q;
570
571 login_check_credentials();
572 if( !g.okRead ){ login_needed(); return; }
573
574 style_header("Tagged Check-ins");
575 style_submenu_element("List", "List", "taglist");
576 login_anonymous_available();
577 @ <h2>Check-ins with non-propagating tags:</h2>
578
--- src/tag.c
+++ src/tag.c
@@ -529,11 +529,11 @@
529 */
530 void taglist_page(void){
531 Stmt q;
532
533 login_check_credentials();
534 if( !g.perm.Read ){
535 login_needed();
536 }
537 login_anonymous_available();
538 style_header("Tags");
539 style_submenu_element("Timeline", "Timeline", "tagtimeline");
@@ -548,11 +548,11 @@
548 " ORDER BY tagname"
549 );
550 @ <ul>
551 while( db_step(&q)==SQLITE_ROW ){
552 const char *zName = db_column_text(&q, 0);
553 if( g.perm.History ){
554 @ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)">
555 @ %h(zName)</a></li>
556 }else{
557 @ <li><span class="tagDsp">%h(zName)</span></li>
558 }
@@ -567,11 +567,11 @@
567 */
568 void tagtimeline_page(void){
569 Stmt q;
570
571 login_check_credentials();
572 if( !g.perm.Read ){ login_needed(); return; }
573
574 style_header("Tagged Check-ins");
575 style_submenu_element("List", "List", "taglist");
576 login_anonymous_available();
577 @ <h2>Check-ins with non-propagating tags:</h2>
578
+3 -3
--- src/tar.c
+++ src/tar.c
@@ -416,11 +416,11 @@
416416
417417
418418
/*
419419
** COMMAND: test-tarball
420420
**
421
-** Generate a GZIP-compresssed tarball in the file given by the first argument
421
+** Generate a GZIP-compressed tarball in the file given by the first argument
422422
** that contains files given in the second and subsequent arguments.
423423
*/
424424
void test_tarball_cmd(void){
425425
int i;
426426
Blob zip;
@@ -432,11 +432,11 @@
432432
tar_begin();
433433
for(i=3; i<g.argc; i++){
434434
blob_zero(&file);
435435
blob_read_from_file(&file, g.argv[i]);
436436
tar_add_file(g.argv[i], &file,
437
- file_perm(g.argv[i]), file_mtime(g.argv[i]));
437
+ file_wd_perm(g.argv[i]), file_wd_mtime(g.argv[i]));
438438
blob_reset(&file);
439439
}
440440
tar_finish(&zip);
441441
blob_write_to_file(&zip, g.argv[2]);
442442
}
@@ -572,11 +572,11 @@
572572
char *zName, *zRid;
573573
int nName, nRid;
574574
Blob tarball;
575575
576576
login_check_credentials();
577
- if( !g.okZip ){ login_needed(); return; }
577
+ if( !g.perm.Zip ){ login_needed(); return; }
578578
zName = mprintf("%s", PD("name",""));
579579
nName = strlen(zName);
580580
zRid = mprintf("%s", PD("uuid",""));
581581
nRid = strlen(zRid);
582582
if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){
583583
--- src/tar.c
+++ src/tar.c
@@ -416,11 +416,11 @@
416
417
418 /*
419 ** COMMAND: test-tarball
420 **
421 ** Generate a GZIP-compresssed tarball in the file given by the first argument
422 ** that contains files given in the second and subsequent arguments.
423 */
424 void test_tarball_cmd(void){
425 int i;
426 Blob zip;
@@ -432,11 +432,11 @@
432 tar_begin();
433 for(i=3; i<g.argc; i++){
434 blob_zero(&file);
435 blob_read_from_file(&file, g.argv[i]);
436 tar_add_file(g.argv[i], &file,
437 file_perm(g.argv[i]), file_mtime(g.argv[i]));
438 blob_reset(&file);
439 }
440 tar_finish(&zip);
441 blob_write_to_file(&zip, g.argv[2]);
442 }
@@ -572,11 +572,11 @@
572 char *zName, *zRid;
573 int nName, nRid;
574 Blob tarball;
575
576 login_check_credentials();
577 if( !g.okZip ){ login_needed(); return; }
578 zName = mprintf("%s", PD("name",""));
579 nName = strlen(zName);
580 zRid = mprintf("%s", PD("uuid",""));
581 nRid = strlen(zRid);
582 if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){
583
--- src/tar.c
+++ src/tar.c
@@ -416,11 +416,11 @@
416
417
418 /*
419 ** COMMAND: test-tarball
420 **
421 ** Generate a GZIP-compressed tarball in the file given by the first argument
422 ** that contains files given in the second and subsequent arguments.
423 */
424 void test_tarball_cmd(void){
425 int i;
426 Blob zip;
@@ -432,11 +432,11 @@
432 tar_begin();
433 for(i=3; i<g.argc; i++){
434 blob_zero(&file);
435 blob_read_from_file(&file, g.argv[i]);
436 tar_add_file(g.argv[i], &file,
437 file_wd_perm(g.argv[i]), file_wd_mtime(g.argv[i]));
438 blob_reset(&file);
439 }
440 tar_finish(&zip);
441 blob_write_to_file(&zip, g.argv[2]);
442 }
@@ -572,11 +572,11 @@
572 char *zName, *zRid;
573 int nName, nRid;
574 Blob tarball;
575
576 login_check_credentials();
577 if( !g.perm.Zip ){ login_needed(); return; }
578 zName = mprintf("%s", PD("name",""));
579 nName = strlen(zName);
580 zRid = mprintf("%s", PD("uuid",""));
581 nRid = strlen(zRid);
582 if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){
583
+47 -37
--- src/timeline.c
+++ src/timeline.c
@@ -47,11 +47,11 @@
4747
** Generate a hyperlink to a version.
4848
*/
4949
void hyperlink_to_uuid(const char *zUuid){
5050
char z[UUID_SIZE+1];
5151
shorten_uuid(z, zUuid);
52
- if( g.okHistory ){
52
+ if( g.perm.History ){
5353
@ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a>
5454
}else{
5555
@ <span class="timelineHistDsp">[%s(z)]</span>
5656
}
5757
}
@@ -58,11 +58,11 @@
5858
5959
/*
6060
** Generate a hyperlink to a diff between two versions.
6161
*/
6262
void hyperlink_to_diff(const char *zV1, const char *zV2){
63
- if( g.okHistory ){
63
+ if( g.perm.History ){
6464
if( zV2==0 ){
6565
@ <a href="%s(g.zTop)/diff?v2=%s(zV1)">[diff]</a>
6666
}else{
6767
@ <a href="%s(g.zTop)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a>
6868
}
@@ -72,11 +72,11 @@
7272
/*
7373
** Generate a hyperlink to a date & time.
7474
*/
7575
void hyperlink_to_date(const char *zDate, const char *zSuffix){
7676
if( zSuffix==0 ) zSuffix = "";
77
- if( g.okHistory ){
77
+ if( g.perm.History ){
7878
@ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix)
7979
}else{
8080
@ %s(zDate)%s(zSuffix)
8181
}
8282
}
@@ -86,11 +86,11 @@
8686
** events by that user. If the date+time is specified, then the timeline
8787
** is centered on that date+time.
8888
*/
8989
void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
9090
if( zSuf==0 ) zSuf = "";
91
- if( g.okHistory ){
91
+ if( g.perm.History ){
9292
if( zD && zD[0] ){
9393
@ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf)
9494
}else{
9595
@ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
9696
}
@@ -350,11 +350,11 @@
350350
351351
/* Generate the "user: USERNAME" at the end of the comment, together
352352
** with a hyperlink to another timeline for that user.
353353
*/
354354
if( zTagList && zTagList[0]==0 ) zTagList = 0;
355
- if( g.okHistory && fossil_strcmp(zUser, zThisUser)!=0 ){
355
+ if( g.perm.History && fossil_strcmp(zUser, zThisUser)!=0 ){
356356
char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd",
357357
g.zTop, zUser, zDate);
358358
@ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051")
359359
fossil_free(zLink);
360360
}else{
@@ -363,11 +363,11 @@
363363
364364
/* Generate the "tags: TAGLIST" at the end of the comment, together
365365
** with hyperlinks to the tag list.
366366
*/
367367
if( zTagList ){
368
- if( g.okHistory ){
368
+ if( g.perm.History ){
369369
int i;
370370
const char *z = zTagList;
371371
Blob links;
372372
blob_zero(&links);
373373
while( z && z[0] ){
@@ -394,44 +394,54 @@
394394
if( xExtra ){
395395
xExtra(rid);
396396
}
397397
398398
/* Generate the file-change list if requested */
399
- if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.okHistory ){
399
+ if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.History ){
400400
int inUl = 0;
401401
if( !fchngQueryInit ){
402402
db_prepare(&fchngQuery,
403403
"SELECT (pid==0) AS isnew,"
404404
" (fid==0) AS isdel,"
405405
" (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
406406
" (SELECT uuid FROM blob WHERE rid=fid),"
407
- " (SELECT uuid FROM blob WHERE rid=pid)"
407
+ " (SELECT uuid FROM blob WHERE rid=pid),"
408
+ " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
408409
" FROM mlink"
409
- " WHERE mid=:mid AND pid!=fid"
410
+ " WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
410411
" ORDER BY 3 /*sort*/"
411412
);
412413
fchngQueryInit = 1;
413414
}
414415
db_bind_int(&fchngQuery, ":mid", rid);
415416
while( db_step(&fchngQuery)==SQLITE_ROW ){
416417
const char *zFilename = db_column_text(&fchngQuery, 2);
417418
int isNew = db_column_int(&fchngQuery, 0);
418419
int isDel = db_column_int(&fchngQuery, 1);
420
+ const char *zOldName = db_column_text(&fchngQuery, 5);
419421
const char *zOld = db_column_text(&fchngQuery, 4);
420422
const char *zNew = db_column_text(&fchngQuery, 3);
421423
if( !inUl ){
422424
@ <ul class="filelist">
423425
inUl = 1;
424426
}
425427
if( isNew ){
426428
@ <li> %h(zFilename) (new file) &nbsp;
427
- @ <a href="%s(g.zTop)/artifact/%S(zNew)" target="diffwindow">[view]
428
- @ </a></li>
429
+ @ <a href="%s(g.zTop)/artifact/%S(zNew)"
430
+ @ target="diffwindow">[view]</a></li>
429431
}else if( isDel ){
430432
@ <li> %h(zFilename) (deleted)</li>
433
+ }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
434
+ @ <li> %h(zOldName) &rarr; %h(zFilename)
435
+ @ <a href="%s(g.zTop)/artifact/%S(zNew)"
436
+ @ target="diffwindow">[view]</a></li>
431437
}else{
432
- @ <li> %h(zFilename) &nbsp;
438
+ if( zOldName!=0 ){
439
+ @ <li> %h(zOldName) &rarr; %h(zFilename)
440
+ }else{
441
+ @ <li> %h(zFilename) &nbsp;
442
+ }
433443
@ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)"
434444
@ target="diffwindow">[diff]</a></li>
435445
}
436446
}
437447
db_reset(&fchngQuery);
@@ -886,15 +896,15 @@
886896
int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
887897
888898
/* To view the timeline, must have permission to read project data.
889899
*/
890900
login_check_credentials();
891
- if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){ login_needed(); return; }
892
- if( zTagName && g.okRead ){
901
+ if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
902
+ if( zTagName && g.perm.Read ){
893903
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
894904
zThisTag = zTagName;
895
- }else if( zBrName && g.okRead ){
905
+ }else if( zBrName && g.perm.Read ){
896906
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
897907
zThisTag = zBrName;
898908
}else{
899909
tagid = 0;
900910
}
@@ -920,19 +930,19 @@
920930
if( P("fc")!=0 || P("detail")!=0 ){
921931
tmFlags |= TIMELINE_FCHANGES;
922932
url_add_parameter(&url, "fc", 0);
923933
}
924934
if( !useDividers ) url_add_parameter(&url, "nd", 0);
925
- if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.okRead ){
935
+ if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
926936
/* If from= and to= are present, display all nodes on a path connecting
927937
** the two */
928938
PathNode *p = 0;
929939
const char *zFrom = 0;
930940
const char *zTo = 0;
931941
932942
if( from_rid && to_rid ){
933
- p = path_shortest(from_rid, to_rid, noMerge);
943
+ p = path_shortest(from_rid, to_rid, noMerge, 0);
934944
zFrom = P("from");
935945
zTo = P("to");
936946
}else{
937947
if( path_common_ancestor(me_rid, you_rid) ){
938948
p = path_first();
@@ -946,24 +956,24 @@
946956
p = p->u.pTo;
947957
}
948958
blob_append(&sql, ")", -1);
949959
path_reset();
950960
blob_append(&desc, "All nodes on the path from ", -1);
951
- if( g.okHistory ){
961
+ if( g.perm.History ){
952962
blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>", g.zTop,zFrom,zFrom);
953963
}else{
954964
blob_appendf(&desc, "[%h]", zFrom);
955965
}
956966
blob_append(&desc, " and ", -1);
957
- if( g.okHistory ){
967
+ if( g.perm.History ){
958968
blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.", g.zTop, zTo, zTo);
959969
}else{
960970
blob_appendf(&desc, "[%h].", zTo);
961971
}
962972
tmFlags |= TIMELINE_DISJOINT;
963973
db_multi_exec("%s", blob_str(&sql));
964
- }else if( (p_rid || d_rid) && g.okRead ){
974
+ }else if( (p_rid || d_rid) && g.perm.Read ){
965975
/* If p= or d= is present, ignore all other parameters other than n= */
966976
char *zUuid;
967977
int np, nd;
968978
969979
if( p_rid && d_rid ){
@@ -995,17 +1005,17 @@
9951005
blob_appendf(&desc, "%d ancestors", np);
9961006
db_multi_exec("%s", blob_str(&sql));
9971007
}
9981008
if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
9991009
}
1000
- if( g.okHistory ){
1010
+ if( g.perm.History ){
10011011
blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>",
10021012
g.zTop, zUuid, zUuid);
10031013
}else{
10041014
blob_appendf(&desc, " of check-in [%.10s]", zUuid);
10051015
}
1006
- }else if( f_rid && g.okRead ){
1016
+ }else if( f_rid && g.perm.Read ){
10071017
/* If f= is present, ignore all other parameters other than n= */
10081018
char *zUuid;
10091019
db_multi_exec(
10101020
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
10111021
"INSERT INTO ok VALUES(%d);"
@@ -1016,11 +1026,11 @@
10161026
blob_appendf(&sql, " AND event.objid IN ok");
10171027
db_multi_exec("%s", blob_str(&sql));
10181028
if( useDividers ) timeline_add_dividers(0, f_rid);
10191029
blob_appendf(&desc, "Parents and children of check-in ");
10201030
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1021
- if( g.okHistory ){
1031
+ if( g.perm.History ){
10221032
blob_appendf(&desc, "<a href='%s/info/%s'>[%.10s]</a>",
10231033
g.zTop, zUuid, zUuid);
10241034
}else{
10251035
blob_appendf(&desc, "[%.10s]", zUuid);
10261036
}
@@ -1061,30 +1071,30 @@
10611071
}else{
10621072
url_add_parameter(&url, "t", zTagName);
10631073
}
10641074
blob_appendf(&sql, ")");
10651075
}
1066
- if( (zType[0]=='w' && !g.okRdWiki)
1067
- || (zType[0]=='t' && !g.okRdTkt)
1068
- || (zType[0]=='e' && !g.okRdWiki)
1069
- || (zType[0]=='c' && !g.okRead)
1076
+ if( (zType[0]=='w' && !g.perm.RdWiki)
1077
+ || (zType[0]=='t' && !g.perm.RdTkt)
1078
+ || (zType[0]=='e' && !g.perm.RdWiki)
1079
+ || (zType[0]=='c' && !g.perm.Read)
10701080
){
10711081
zType = "all";
10721082
}
10731083
if( zType[0]=='a' ){
1074
- if( !g.okRead || !g.okRdWiki || !g.okRdTkt ){
1084
+ if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){
10751085
char cSep = '(';
10761086
blob_appendf(&sql, " AND event.type IN ");
1077
- if( g.okRead ){
1087
+ if( g.perm.Read ){
10781088
blob_appendf(&sql, "%c'ci'", cSep);
10791089
cSep = ',';
10801090
}
1081
- if( g.okRdWiki ){
1091
+ if( g.perm.RdWiki ){
10821092
blob_appendf(&sql, "%c'w','e'", cSep);
10831093
cSep = ',';
10841094
}
1085
- if( g.okRdTkt ){
1095
+ if( g.perm.RdTkt ){
10861096
blob_appendf(&sql, "%c't'", cSep);
10871097
cSep = ',';
10881098
}
10891099
blob_appendf(&sql, ")");
10901100
}
@@ -1190,11 +1200,11 @@
11901200
blob_appendf(&desc, " occurring around %h.<br />", zCirca);
11911201
}
11921202
if( zSearch ){
11931203
blob_appendf(&desc, " matching \"%h\"", zSearch);
11941204
}
1195
- if( g.okHistory ){
1205
+ if( g.perm.History ){
11961206
if( zAfter || n==nEntry ){
11971207
zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
11981208
timeline_submenu(&url, "Older", "b", zDate, "a");
11991209
free(zDate);
12001210
}
@@ -1204,20 +1214,20 @@
12041214
free(zDate);
12051215
}else if( tagid==0 ){
12061216
if( zType[0]!='a' ){
12071217
timeline_submenu(&url, "All Types", "y", "all", 0);
12081218
}
1209
- if( zType[0]!='w' && g.okRdWiki ){
1219
+ if( zType[0]!='w' && g.perm.RdWiki ){
12101220
timeline_submenu(&url, "Wiki Only", "y", "w", 0);
12111221
}
1212
- if( zType[0]!='c' && g.okRead ){
1222
+ if( zType[0]!='c' && g.perm.Read ){
12131223
timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
12141224
}
1215
- if( zType[0]!='t' && g.okRdTkt ){
1225
+ if( zType[0]!='t' && g.perm.RdTkt ){
12161226
timeline_submenu(&url, "Tickets Only", "y", "t", 0);
12171227
}
1218
- if( zType[0]!='e' && g.okRdWiki ){
1228
+ if( zType[0]!='e' && g.perm.RdWiki ){
12191229
timeline_submenu(&url, "Events Only", "y", "e", 0);
12201230
}
12211231
}
12221232
if( nEntry>20 ){
12231233
timeline_submenu(&url, "20 Entries", "n", "20", 0);
@@ -1592,11 +1602,11 @@
15921602
*/
15931603
void test_timewarp_page(void){
15941604
Stmt q;
15951605
15961606
login_check_credentials();
1597
- if( !g.okRead || !g.okHistory ){ login_needed(); return; }
1607
+ if( !g.perm.Read || !g.perm.History ){ login_needed(); return; }
15981608
style_header("Instances of timewarp");
15991609
@ <ul>
16001610
db_prepare(&q,
16011611
"SELECT blob.uuid "
16021612
" FROM plink p, plink c, blob"
16031613
--- src/timeline.c
+++ src/timeline.c
@@ -47,11 +47,11 @@
47 ** Generate a hyperlink to a version.
48 */
49 void hyperlink_to_uuid(const char *zUuid){
50 char z[UUID_SIZE+1];
51 shorten_uuid(z, zUuid);
52 if( g.okHistory ){
53 @ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a>
54 }else{
55 @ <span class="timelineHistDsp">[%s(z)]</span>
56 }
57 }
@@ -58,11 +58,11 @@
58
59 /*
60 ** Generate a hyperlink to a diff between two versions.
61 */
62 void hyperlink_to_diff(const char *zV1, const char *zV2){
63 if( g.okHistory ){
64 if( zV2==0 ){
65 @ <a href="%s(g.zTop)/diff?v2=%s(zV1)">[diff]</a>
66 }else{
67 @ <a href="%s(g.zTop)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a>
68 }
@@ -72,11 +72,11 @@
72 /*
73 ** Generate a hyperlink to a date & time.
74 */
75 void hyperlink_to_date(const char *zDate, const char *zSuffix){
76 if( zSuffix==0 ) zSuffix = "";
77 if( g.okHistory ){
78 @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix)
79 }else{
80 @ %s(zDate)%s(zSuffix)
81 }
82 }
@@ -86,11 +86,11 @@
86 ** events by that user. If the date+time is specified, then the timeline
87 ** is centered on that date+time.
88 */
89 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
90 if( zSuf==0 ) zSuf = "";
91 if( g.okHistory ){
92 if( zD && zD[0] ){
93 @ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf)
94 }else{
95 @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
96 }
@@ -350,11 +350,11 @@
350
351 /* Generate the "user: USERNAME" at the end of the comment, together
352 ** with a hyperlink to another timeline for that user.
353 */
354 if( zTagList && zTagList[0]==0 ) zTagList = 0;
355 if( g.okHistory && fossil_strcmp(zUser, zThisUser)!=0 ){
356 char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd",
357 g.zTop, zUser, zDate);
358 @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051")
359 fossil_free(zLink);
360 }else{
@@ -363,11 +363,11 @@
363
364 /* Generate the "tags: TAGLIST" at the end of the comment, together
365 ** with hyperlinks to the tag list.
366 */
367 if( zTagList ){
368 if( g.okHistory ){
369 int i;
370 const char *z = zTagList;
371 Blob links;
372 blob_zero(&links);
373 while( z && z[0] ){
@@ -394,44 +394,54 @@
394 if( xExtra ){
395 xExtra(rid);
396 }
397
398 /* Generate the file-change list if requested */
399 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.okHistory ){
400 int inUl = 0;
401 if( !fchngQueryInit ){
402 db_prepare(&fchngQuery,
403 "SELECT (pid==0) AS isnew,"
404 " (fid==0) AS isdel,"
405 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
406 " (SELECT uuid FROM blob WHERE rid=fid),"
407 " (SELECT uuid FROM blob WHERE rid=pid)"
 
408 " FROM mlink"
409 " WHERE mid=:mid AND pid!=fid"
410 " ORDER BY 3 /*sort*/"
411 );
412 fchngQueryInit = 1;
413 }
414 db_bind_int(&fchngQuery, ":mid", rid);
415 while( db_step(&fchngQuery)==SQLITE_ROW ){
416 const char *zFilename = db_column_text(&fchngQuery, 2);
417 int isNew = db_column_int(&fchngQuery, 0);
418 int isDel = db_column_int(&fchngQuery, 1);
 
419 const char *zOld = db_column_text(&fchngQuery, 4);
420 const char *zNew = db_column_text(&fchngQuery, 3);
421 if( !inUl ){
422 @ <ul class="filelist">
423 inUl = 1;
424 }
425 if( isNew ){
426 @ <li> %h(zFilename) (new file) &nbsp;
427 @ <a href="%s(g.zTop)/artifact/%S(zNew)" target="diffwindow">[view]
428 @ </a></li>
429 }else if( isDel ){
430 @ <li> %h(zFilename) (deleted)</li>
 
 
 
 
431 }else{
432 @ <li> %h(zFilename) &nbsp;
 
 
 
 
433 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)"
434 @ target="diffwindow">[diff]</a></li>
435 }
436 }
437 db_reset(&fchngQuery);
@@ -886,15 +896,15 @@
886 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
887
888 /* To view the timeline, must have permission to read project data.
889 */
890 login_check_credentials();
891 if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){ login_needed(); return; }
892 if( zTagName && g.okRead ){
893 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
894 zThisTag = zTagName;
895 }else if( zBrName && g.okRead ){
896 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
897 zThisTag = zBrName;
898 }else{
899 tagid = 0;
900 }
@@ -920,19 +930,19 @@
920 if( P("fc")!=0 || P("detail")!=0 ){
921 tmFlags |= TIMELINE_FCHANGES;
922 url_add_parameter(&url, "fc", 0);
923 }
924 if( !useDividers ) url_add_parameter(&url, "nd", 0);
925 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.okRead ){
926 /* If from= and to= are present, display all nodes on a path connecting
927 ** the two */
928 PathNode *p = 0;
929 const char *zFrom = 0;
930 const char *zTo = 0;
931
932 if( from_rid && to_rid ){
933 p = path_shortest(from_rid, to_rid, noMerge);
934 zFrom = P("from");
935 zTo = P("to");
936 }else{
937 if( path_common_ancestor(me_rid, you_rid) ){
938 p = path_first();
@@ -946,24 +956,24 @@
946 p = p->u.pTo;
947 }
948 blob_append(&sql, ")", -1);
949 path_reset();
950 blob_append(&desc, "All nodes on the path from ", -1);
951 if( g.okHistory ){
952 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>", g.zTop,zFrom,zFrom);
953 }else{
954 blob_appendf(&desc, "[%h]", zFrom);
955 }
956 blob_append(&desc, " and ", -1);
957 if( g.okHistory ){
958 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.", g.zTop, zTo, zTo);
959 }else{
960 blob_appendf(&desc, "[%h].", zTo);
961 }
962 tmFlags |= TIMELINE_DISJOINT;
963 db_multi_exec("%s", blob_str(&sql));
964 }else if( (p_rid || d_rid) && g.okRead ){
965 /* If p= or d= is present, ignore all other parameters other than n= */
966 char *zUuid;
967 int np, nd;
968
969 if( p_rid && d_rid ){
@@ -995,17 +1005,17 @@
995 blob_appendf(&desc, "%d ancestors", np);
996 db_multi_exec("%s", blob_str(&sql));
997 }
998 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
999 }
1000 if( g.okHistory ){
1001 blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>",
1002 g.zTop, zUuid, zUuid);
1003 }else{
1004 blob_appendf(&desc, " of check-in [%.10s]", zUuid);
1005 }
1006 }else if( f_rid && g.okRead ){
1007 /* If f= is present, ignore all other parameters other than n= */
1008 char *zUuid;
1009 db_multi_exec(
1010 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
1011 "INSERT INTO ok VALUES(%d);"
@@ -1016,11 +1026,11 @@
1016 blob_appendf(&sql, " AND event.objid IN ok");
1017 db_multi_exec("%s", blob_str(&sql));
1018 if( useDividers ) timeline_add_dividers(0, f_rid);
1019 blob_appendf(&desc, "Parents and children of check-in ");
1020 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1021 if( g.okHistory ){
1022 blob_appendf(&desc, "<a href='%s/info/%s'>[%.10s]</a>",
1023 g.zTop, zUuid, zUuid);
1024 }else{
1025 blob_appendf(&desc, "[%.10s]", zUuid);
1026 }
@@ -1061,30 +1071,30 @@
1061 }else{
1062 url_add_parameter(&url, "t", zTagName);
1063 }
1064 blob_appendf(&sql, ")");
1065 }
1066 if( (zType[0]=='w' && !g.okRdWiki)
1067 || (zType[0]=='t' && !g.okRdTkt)
1068 || (zType[0]=='e' && !g.okRdWiki)
1069 || (zType[0]=='c' && !g.okRead)
1070 ){
1071 zType = "all";
1072 }
1073 if( zType[0]=='a' ){
1074 if( !g.okRead || !g.okRdWiki || !g.okRdTkt ){
1075 char cSep = '(';
1076 blob_appendf(&sql, " AND event.type IN ");
1077 if( g.okRead ){
1078 blob_appendf(&sql, "%c'ci'", cSep);
1079 cSep = ',';
1080 }
1081 if( g.okRdWiki ){
1082 blob_appendf(&sql, "%c'w','e'", cSep);
1083 cSep = ',';
1084 }
1085 if( g.okRdTkt ){
1086 blob_appendf(&sql, "%c't'", cSep);
1087 cSep = ',';
1088 }
1089 blob_appendf(&sql, ")");
1090 }
@@ -1190,11 +1200,11 @@
1190 blob_appendf(&desc, " occurring around %h.<br />", zCirca);
1191 }
1192 if( zSearch ){
1193 blob_appendf(&desc, " matching \"%h\"", zSearch);
1194 }
1195 if( g.okHistory ){
1196 if( zAfter || n==nEntry ){
1197 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1198 timeline_submenu(&url, "Older", "b", zDate, "a");
1199 free(zDate);
1200 }
@@ -1204,20 +1214,20 @@
1204 free(zDate);
1205 }else if( tagid==0 ){
1206 if( zType[0]!='a' ){
1207 timeline_submenu(&url, "All Types", "y", "all", 0);
1208 }
1209 if( zType[0]!='w' && g.okRdWiki ){
1210 timeline_submenu(&url, "Wiki Only", "y", "w", 0);
1211 }
1212 if( zType[0]!='c' && g.okRead ){
1213 timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
1214 }
1215 if( zType[0]!='t' && g.okRdTkt ){
1216 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
1217 }
1218 if( zType[0]!='e' && g.okRdWiki ){
1219 timeline_submenu(&url, "Events Only", "y", "e", 0);
1220 }
1221 }
1222 if( nEntry>20 ){
1223 timeline_submenu(&url, "20 Entries", "n", "20", 0);
@@ -1592,11 +1602,11 @@
1592 */
1593 void test_timewarp_page(void){
1594 Stmt q;
1595
1596 login_check_credentials();
1597 if( !g.okRead || !g.okHistory ){ login_needed(); return; }
1598 style_header("Instances of timewarp");
1599 @ <ul>
1600 db_prepare(&q,
1601 "SELECT blob.uuid "
1602 " FROM plink p, plink c, blob"
1603
--- src/timeline.c
+++ src/timeline.c
@@ -47,11 +47,11 @@
47 ** Generate a hyperlink to a version.
48 */
49 void hyperlink_to_uuid(const char *zUuid){
50 char z[UUID_SIZE+1];
51 shorten_uuid(z, zUuid);
52 if( g.perm.History ){
53 @ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a>
54 }else{
55 @ <span class="timelineHistDsp">[%s(z)]</span>
56 }
57 }
@@ -58,11 +58,11 @@
58
59 /*
60 ** Generate a hyperlink to a diff between two versions.
61 */
62 void hyperlink_to_diff(const char *zV1, const char *zV2){
63 if( g.perm.History ){
64 if( zV2==0 ){
65 @ <a href="%s(g.zTop)/diff?v2=%s(zV1)">[diff]</a>
66 }else{
67 @ <a href="%s(g.zTop)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a>
68 }
@@ -72,11 +72,11 @@
72 /*
73 ** Generate a hyperlink to a date & time.
74 */
75 void hyperlink_to_date(const char *zDate, const char *zSuffix){
76 if( zSuffix==0 ) zSuffix = "";
77 if( g.perm.History ){
78 @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix)
79 }else{
80 @ %s(zDate)%s(zSuffix)
81 }
82 }
@@ -86,11 +86,11 @@
86 ** events by that user. If the date+time is specified, then the timeline
87 ** is centered on that date+time.
88 */
89 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
90 if( zSuf==0 ) zSuf = "";
91 if( g.perm.History ){
92 if( zD && zD[0] ){
93 @ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf)
94 }else{
95 @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
96 }
@@ -350,11 +350,11 @@
350
351 /* Generate the "user: USERNAME" at the end of the comment, together
352 ** with a hyperlink to another timeline for that user.
353 */
354 if( zTagList && zTagList[0]==0 ) zTagList = 0;
355 if( g.perm.History && fossil_strcmp(zUser, zThisUser)!=0 ){
356 char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd",
357 g.zTop, zUser, zDate);
358 @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051")
359 fossil_free(zLink);
360 }else{
@@ -363,11 +363,11 @@
363
364 /* Generate the "tags: TAGLIST" at the end of the comment, together
365 ** with hyperlinks to the tag list.
366 */
367 if( zTagList ){
368 if( g.perm.History ){
369 int i;
370 const char *z = zTagList;
371 Blob links;
372 blob_zero(&links);
373 while( z && z[0] ){
@@ -394,44 +394,54 @@
394 if( xExtra ){
395 xExtra(rid);
396 }
397
398 /* Generate the file-change list if requested */
399 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.History ){
400 int inUl = 0;
401 if( !fchngQueryInit ){
402 db_prepare(&fchngQuery,
403 "SELECT (pid==0) AS isnew,"
404 " (fid==0) AS isdel,"
405 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
406 " (SELECT uuid FROM blob WHERE rid=fid),"
407 " (SELECT uuid FROM blob WHERE rid=pid),"
408 " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
409 " FROM mlink"
410 " WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
411 " ORDER BY 3 /*sort*/"
412 );
413 fchngQueryInit = 1;
414 }
415 db_bind_int(&fchngQuery, ":mid", rid);
416 while( db_step(&fchngQuery)==SQLITE_ROW ){
417 const char *zFilename = db_column_text(&fchngQuery, 2);
418 int isNew = db_column_int(&fchngQuery, 0);
419 int isDel = db_column_int(&fchngQuery, 1);
420 const char *zOldName = db_column_text(&fchngQuery, 5);
421 const char *zOld = db_column_text(&fchngQuery, 4);
422 const char *zNew = db_column_text(&fchngQuery, 3);
423 if( !inUl ){
424 @ <ul class="filelist">
425 inUl = 1;
426 }
427 if( isNew ){
428 @ <li> %h(zFilename) (new file) &nbsp;
429 @ <a href="%s(g.zTop)/artifact/%S(zNew)"
430 @ target="diffwindow">[view]</a></li>
431 }else if( isDel ){
432 @ <li> %h(zFilename) (deleted)</li>
433 }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
434 @ <li> %h(zOldName) &rarr; %h(zFilename)
435 @ <a href="%s(g.zTop)/artifact/%S(zNew)"
436 @ target="diffwindow">[view]</a></li>
437 }else{
438 if( zOldName!=0 ){
439 @ <li> %h(zOldName) &rarr; %h(zFilename)
440 }else{
441 @ <li> %h(zFilename) &nbsp;
442 }
443 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)"
444 @ target="diffwindow">[diff]</a></li>
445 }
446 }
447 db_reset(&fchngQuery);
@@ -886,15 +896,15 @@
896 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
897
898 /* To view the timeline, must have permission to read project data.
899 */
900 login_check_credentials();
901 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
902 if( zTagName && g.perm.Read ){
903 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
904 zThisTag = zTagName;
905 }else if( zBrName && g.perm.Read ){
906 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
907 zThisTag = zBrName;
908 }else{
909 tagid = 0;
910 }
@@ -920,19 +930,19 @@
930 if( P("fc")!=0 || P("detail")!=0 ){
931 tmFlags |= TIMELINE_FCHANGES;
932 url_add_parameter(&url, "fc", 0);
933 }
934 if( !useDividers ) url_add_parameter(&url, "nd", 0);
935 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
936 /* If from= and to= are present, display all nodes on a path connecting
937 ** the two */
938 PathNode *p = 0;
939 const char *zFrom = 0;
940 const char *zTo = 0;
941
942 if( from_rid && to_rid ){
943 p = path_shortest(from_rid, to_rid, noMerge, 0);
944 zFrom = P("from");
945 zTo = P("to");
946 }else{
947 if( path_common_ancestor(me_rid, you_rid) ){
948 p = path_first();
@@ -946,24 +956,24 @@
956 p = p->u.pTo;
957 }
958 blob_append(&sql, ")", -1);
959 path_reset();
960 blob_append(&desc, "All nodes on the path from ", -1);
961 if( g.perm.History ){
962 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>", g.zTop,zFrom,zFrom);
963 }else{
964 blob_appendf(&desc, "[%h]", zFrom);
965 }
966 blob_append(&desc, " and ", -1);
967 if( g.perm.History ){
968 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.", g.zTop, zTo, zTo);
969 }else{
970 blob_appendf(&desc, "[%h].", zTo);
971 }
972 tmFlags |= TIMELINE_DISJOINT;
973 db_multi_exec("%s", blob_str(&sql));
974 }else if( (p_rid || d_rid) && g.perm.Read ){
975 /* If p= or d= is present, ignore all other parameters other than n= */
976 char *zUuid;
977 int np, nd;
978
979 if( p_rid && d_rid ){
@@ -995,17 +1005,17 @@
1005 blob_appendf(&desc, "%d ancestors", np);
1006 db_multi_exec("%s", blob_str(&sql));
1007 }
1008 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
1009 }
1010 if( g.perm.History ){
1011 blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>",
1012 g.zTop, zUuid, zUuid);
1013 }else{
1014 blob_appendf(&desc, " of check-in [%.10s]", zUuid);
1015 }
1016 }else if( f_rid && g.perm.Read ){
1017 /* If f= is present, ignore all other parameters other than n= */
1018 char *zUuid;
1019 db_multi_exec(
1020 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
1021 "INSERT INTO ok VALUES(%d);"
@@ -1016,11 +1026,11 @@
1026 blob_appendf(&sql, " AND event.objid IN ok");
1027 db_multi_exec("%s", blob_str(&sql));
1028 if( useDividers ) timeline_add_dividers(0, f_rid);
1029 blob_appendf(&desc, "Parents and children of check-in ");
1030 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1031 if( g.perm.History ){
1032 blob_appendf(&desc, "<a href='%s/info/%s'>[%.10s]</a>",
1033 g.zTop, zUuid, zUuid);
1034 }else{
1035 blob_appendf(&desc, "[%.10s]", zUuid);
1036 }
@@ -1061,30 +1071,30 @@
1071 }else{
1072 url_add_parameter(&url, "t", zTagName);
1073 }
1074 blob_appendf(&sql, ")");
1075 }
1076 if( (zType[0]=='w' && !g.perm.RdWiki)
1077 || (zType[0]=='t' && !g.perm.RdTkt)
1078 || (zType[0]=='e' && !g.perm.RdWiki)
1079 || (zType[0]=='c' && !g.perm.Read)
1080 ){
1081 zType = "all";
1082 }
1083 if( zType[0]=='a' ){
1084 if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){
1085 char cSep = '(';
1086 blob_appendf(&sql, " AND event.type IN ");
1087 if( g.perm.Read ){
1088 blob_appendf(&sql, "%c'ci'", cSep);
1089 cSep = ',';
1090 }
1091 if( g.perm.RdWiki ){
1092 blob_appendf(&sql, "%c'w','e'", cSep);
1093 cSep = ',';
1094 }
1095 if( g.perm.RdTkt ){
1096 blob_appendf(&sql, "%c't'", cSep);
1097 cSep = ',';
1098 }
1099 blob_appendf(&sql, ")");
1100 }
@@ -1190,11 +1200,11 @@
1200 blob_appendf(&desc, " occurring around %h.<br />", zCirca);
1201 }
1202 if( zSearch ){
1203 blob_appendf(&desc, " matching \"%h\"", zSearch);
1204 }
1205 if( g.perm.History ){
1206 if( zAfter || n==nEntry ){
1207 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1208 timeline_submenu(&url, "Older", "b", zDate, "a");
1209 free(zDate);
1210 }
@@ -1204,20 +1214,20 @@
1214 free(zDate);
1215 }else if( tagid==0 ){
1216 if( zType[0]!='a' ){
1217 timeline_submenu(&url, "All Types", "y", "all", 0);
1218 }
1219 if( zType[0]!='w' && g.perm.RdWiki ){
1220 timeline_submenu(&url, "Wiki Only", "y", "w", 0);
1221 }
1222 if( zType[0]!='c' && g.perm.Read ){
1223 timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
1224 }
1225 if( zType[0]!='t' && g.perm.RdTkt ){
1226 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
1227 }
1228 if( zType[0]!='e' && g.perm.RdWiki ){
1229 timeline_submenu(&url, "Events Only", "y", "e", 0);
1230 }
1231 }
1232 if( nEntry>20 ){
1233 timeline_submenu(&url, "20 Entries", "n", "20", 0);
@@ -1592,11 +1602,11 @@
1602 */
1603 void test_timewarp_page(void){
1604 Stmt q;
1605
1606 login_check_credentials();
1607 if( !g.perm.Read || !g.perm.History ){ login_needed(); return; }
1608 style_header("Instances of timewarp");
1609 @ <ul>
1610 db_prepare(&q,
1611 "SELECT blob.uuid "
1612 " FROM plink p, plink c, blob"
1613
+12 -13
--- src/tkt.c
+++ src/tkt.c
@@ -89,11 +89,11 @@
8989
**
9090
** Only load those fields which do not already exist as
9191
** variables.
9292
**
9393
** Fields of the TICKET table that begin with "private_" are
94
-** expanded using the db_reveal() function. If g.okRdAddr is
94
+** expanded using the db_reveal() function. If g.perm.RdAddr is
9595
** true, then the db_reveal() function will decode the content
9696
** using the CONCEALED table so that the content legable.
9797
** Otherwise, db_reveal() is a no-op and the content remains
9898
** obscured.
9999
*/
@@ -292,28 +292,28 @@
292292
const char *zScript;
293293
char *zFullName;
294294
const char *zUuid = PD("name","");
295295
296296
login_check_credentials();
297
- if( !g.okRdTkt ){ login_needed(); return; }
298
- if( g.okWrTkt || g.okApndTkt ){
297
+ if( !g.perm.RdTkt ){ login_needed(); return; }
298
+ if( g.perm.WrTkt || g.perm.ApndTkt ){
299299
style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
300300
g.zTop, PD("name",""));
301301
}
302
- if( g.okHistory ){
302
+ if( g.perm.History ){
303303
style_submenu_element("History", "History Of This Ticket",
304304
"%s/tkthistory/%T", g.zTop, zUuid);
305305
style_submenu_element("Timeline", "Timeline Of This Ticket",
306306
"%s/tkttimeline/%T", g.zTop, zUuid);
307307
style_submenu_element("Check-ins", "Check-ins Of This Ticket",
308308
"%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
309309
}
310
- if( g.okNewTkt ){
310
+ if( g.perm.NewTkt ){
311311
style_submenu_element("New Ticket", "Create a new ticket",
312312
"%s/tktnew", g.zTop);
313313
}
314
- if( g.okApndTkt && g.okAttach ){
314
+ if( g.perm.ApndTkt && g.perm.Attach ){
315315
style_submenu_element("Attach", "Add An Attachment",
316316
"%s/attachadd?tkt=%T&amp;from=%s/tktview/%t",
317317
g.zTop, zUuid, g.zTop, zUuid);
318318
}
319319
style_header("View Ticket");
@@ -345,19 +345,19 @@
345345
@ <hr /><h2>Attachments:</h2>
346346
@ <ul>
347347
}
348348
cnt++;
349349
@ <li>
350
- if( g.okRead && g.okHistory ){
350
+ if( g.perm.Read && g.perm.History ){
351351
@ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(zFile)">
352352
@ %h(zFile)</a>
353353
}else{
354354
@ %h(zFile)
355355
}
356356
@ added by %h(zUser) on
357357
hyperlink_to_date(zDate, ".");
358
- if( g.okWrTkt && g.okAttach ){
358
+ if( g.perm.WrTkt && g.perm.Attach ){
359359
@ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
360360
}
361361
@ </li>
362362
}
363363
if( cnt ){
@@ -510,11 +510,11 @@
510510
void tktnew_page(void){
511511
const char *zScript;
512512
char *zNewUuid = 0;
513513
514514
login_check_credentials();
515
- if( !g.okNewTkt ){ login_needed(); return; }
515
+ if( !g.perm.NewTkt ){ login_needed(); return; }
516516
if( P("cancel") ){
517517
cgi_redirect("home");
518518
}
519519
style_header("New Ticket");
520520
if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1);
@@ -556,11 +556,11 @@
556556
int nName;
557557
const char *zName;
558558
int nRec;
559559
560560
login_check_credentials();
561
- if( !g.okApndTkt && !g.okWrTkt ){ login_needed(); return; }
561
+ if( !g.perm.ApndTkt && !g.perm.WrTkt ){ login_needed(); return; }
562562
zName = P("name");
563563
if( P("cancel") ){
564564
cgi_redirectf("tktview?name=%T", zName);
565565
}
566566
style_header("Edit Ticket");
@@ -651,11 +651,11 @@
651651
int tagid;
652652
char zGlobPattern[50];
653653
const char *zType;
654654
655655
login_check_credentials();
656
- if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
656
+ if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; }
657657
zUuid = PD("name","");
658658
zType = PD("y","a");
659659
if( zType[0]!='c' ){
660660
style_submenu_element("Check-ins", "Check-ins",
661661
"%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
@@ -725,11 +725,11 @@
725725
char *zTitle;
726726
const char *zUuid;
727727
int tagid;
728728
729729
login_check_credentials();
730
- if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
730
+ if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; }
731731
zUuid = PD("name","");
732732
zTitle = mprintf("History Of Ticket %h", zUuid);
733733
style_submenu_element("Status", "Status",
734734
"%s/info/%s", g.zTop, zUuid);
735735
style_submenu_element("Check-ins", "Check-ins",
@@ -1011,11 +1011,10 @@
10111011
}
10121012
10131013
/* we just handle history separately here, does not get out */
10141014
if( eCmd==history ){
10151015
Stmt q;
1016
- char *zTitle;
10171016
int tagid;
10181017
10191018
if ( i != g.argc ){
10201019
fossil_fatal("no other parameters expected to %s!",g.argv[2]);
10211020
}
10221021
--- src/tkt.c
+++ src/tkt.c
@@ -89,11 +89,11 @@
89 **
90 ** Only load those fields which do not already exist as
91 ** variables.
92 **
93 ** Fields of the TICKET table that begin with "private_" are
94 ** expanded using the db_reveal() function. If g.okRdAddr is
95 ** true, then the db_reveal() function will decode the content
96 ** using the CONCEALED table so that the content legable.
97 ** Otherwise, db_reveal() is a no-op and the content remains
98 ** obscured.
99 */
@@ -292,28 +292,28 @@
292 const char *zScript;
293 char *zFullName;
294 const char *zUuid = PD("name","");
295
296 login_check_credentials();
297 if( !g.okRdTkt ){ login_needed(); return; }
298 if( g.okWrTkt || g.okApndTkt ){
299 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
300 g.zTop, PD("name",""));
301 }
302 if( g.okHistory ){
303 style_submenu_element("History", "History Of This Ticket",
304 "%s/tkthistory/%T", g.zTop, zUuid);
305 style_submenu_element("Timeline", "Timeline Of This Ticket",
306 "%s/tkttimeline/%T", g.zTop, zUuid);
307 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
308 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
309 }
310 if( g.okNewTkt ){
311 style_submenu_element("New Ticket", "Create a new ticket",
312 "%s/tktnew", g.zTop);
313 }
314 if( g.okApndTkt && g.okAttach ){
315 style_submenu_element("Attach", "Add An Attachment",
316 "%s/attachadd?tkt=%T&amp;from=%s/tktview/%t",
317 g.zTop, zUuid, g.zTop, zUuid);
318 }
319 style_header("View Ticket");
@@ -345,19 +345,19 @@
345 @ <hr /><h2>Attachments:</h2>
346 @ <ul>
347 }
348 cnt++;
349 @ <li>
350 if( g.okRead && g.okHistory ){
351 @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(zFile)">
352 @ %h(zFile)</a>
353 }else{
354 @ %h(zFile)
355 }
356 @ added by %h(zUser) on
357 hyperlink_to_date(zDate, ".");
358 if( g.okWrTkt && g.okAttach ){
359 @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
360 }
361 @ </li>
362 }
363 if( cnt ){
@@ -510,11 +510,11 @@
510 void tktnew_page(void){
511 const char *zScript;
512 char *zNewUuid = 0;
513
514 login_check_credentials();
515 if( !g.okNewTkt ){ login_needed(); return; }
516 if( P("cancel") ){
517 cgi_redirect("home");
518 }
519 style_header("New Ticket");
520 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1);
@@ -556,11 +556,11 @@
556 int nName;
557 const char *zName;
558 int nRec;
559
560 login_check_credentials();
561 if( !g.okApndTkt && !g.okWrTkt ){ login_needed(); return; }
562 zName = P("name");
563 if( P("cancel") ){
564 cgi_redirectf("tktview?name=%T", zName);
565 }
566 style_header("Edit Ticket");
@@ -651,11 +651,11 @@
651 int tagid;
652 char zGlobPattern[50];
653 const char *zType;
654
655 login_check_credentials();
656 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
657 zUuid = PD("name","");
658 zType = PD("y","a");
659 if( zType[0]!='c' ){
660 style_submenu_element("Check-ins", "Check-ins",
661 "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
@@ -725,11 +725,11 @@
725 char *zTitle;
726 const char *zUuid;
727 int tagid;
728
729 login_check_credentials();
730 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
731 zUuid = PD("name","");
732 zTitle = mprintf("History Of Ticket %h", zUuid);
733 style_submenu_element("Status", "Status",
734 "%s/info/%s", g.zTop, zUuid);
735 style_submenu_element("Check-ins", "Check-ins",
@@ -1011,11 +1011,10 @@
1011 }
1012
1013 /* we just handle history separately here, does not get out */
1014 if( eCmd==history ){
1015 Stmt q;
1016 char *zTitle;
1017 int tagid;
1018
1019 if ( i != g.argc ){
1020 fossil_fatal("no other parameters expected to %s!",g.argv[2]);
1021 }
1022
--- src/tkt.c
+++ src/tkt.c
@@ -89,11 +89,11 @@
89 **
90 ** Only load those fields which do not already exist as
91 ** variables.
92 **
93 ** Fields of the TICKET table that begin with "private_" are
94 ** expanded using the db_reveal() function. If g.perm.RdAddr is
95 ** true, then the db_reveal() function will decode the content
96 ** using the CONCEALED table so that the content legable.
97 ** Otherwise, db_reveal() is a no-op and the content remains
98 ** obscured.
99 */
@@ -292,28 +292,28 @@
292 const char *zScript;
293 char *zFullName;
294 const char *zUuid = PD("name","");
295
296 login_check_credentials();
297 if( !g.perm.RdTkt ){ login_needed(); return; }
298 if( g.perm.WrTkt || g.perm.ApndTkt ){
299 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
300 g.zTop, PD("name",""));
301 }
302 if( g.perm.History ){
303 style_submenu_element("History", "History Of This Ticket",
304 "%s/tkthistory/%T", g.zTop, zUuid);
305 style_submenu_element("Timeline", "Timeline Of This Ticket",
306 "%s/tkttimeline/%T", g.zTop, zUuid);
307 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
308 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
309 }
310 if( g.perm.NewTkt ){
311 style_submenu_element("New Ticket", "Create a new ticket",
312 "%s/tktnew", g.zTop);
313 }
314 if( g.perm.ApndTkt && g.perm.Attach ){
315 style_submenu_element("Attach", "Add An Attachment",
316 "%s/attachadd?tkt=%T&amp;from=%s/tktview/%t",
317 g.zTop, zUuid, g.zTop, zUuid);
318 }
319 style_header("View Ticket");
@@ -345,19 +345,19 @@
345 @ <hr /><h2>Attachments:</h2>
346 @ <ul>
347 }
348 cnt++;
349 @ <li>
350 if( g.perm.Read && g.perm.History ){
351 @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(zFile)">
352 @ %h(zFile)</a>
353 }else{
354 @ %h(zFile)
355 }
356 @ added by %h(zUser) on
357 hyperlink_to_date(zDate, ".");
358 if( g.perm.WrTkt && g.perm.Attach ){
359 @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
360 }
361 @ </li>
362 }
363 if( cnt ){
@@ -510,11 +510,11 @@
510 void tktnew_page(void){
511 const char *zScript;
512 char *zNewUuid = 0;
513
514 login_check_credentials();
515 if( !g.perm.NewTkt ){ login_needed(); return; }
516 if( P("cancel") ){
517 cgi_redirect("home");
518 }
519 style_header("New Ticket");
520 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1);
@@ -556,11 +556,11 @@
556 int nName;
557 const char *zName;
558 int nRec;
559
560 login_check_credentials();
561 if( !g.perm.ApndTkt && !g.perm.WrTkt ){ login_needed(); return; }
562 zName = P("name");
563 if( P("cancel") ){
564 cgi_redirectf("tktview?name=%T", zName);
565 }
566 style_header("Edit Ticket");
@@ -651,11 +651,11 @@
651 int tagid;
652 char zGlobPattern[50];
653 const char *zType;
654
655 login_check_credentials();
656 if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; }
657 zUuid = PD("name","");
658 zType = PD("y","a");
659 if( zType[0]!='c' ){
660 style_submenu_element("Check-ins", "Check-ins",
661 "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
@@ -725,11 +725,11 @@
725 char *zTitle;
726 const char *zUuid;
727 int tagid;
728
729 login_check_credentials();
730 if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; }
731 zUuid = PD("name","");
732 zTitle = mprintf("History Of Ticket %h", zUuid);
733 style_submenu_element("Status", "Status",
734 "%s/info/%s", g.zTop, zUuid);
735 style_submenu_element("Check-ins", "Check-ins",
@@ -1011,11 +1011,10 @@
1011 }
1012
1013 /* we just handle history separately here, does not get out */
1014 if( eCmd==history ){
1015 Stmt q;
 
1016 int tagid;
1017
1018 if ( i != g.argc ){
1019 fossil_fatal("no other parameters expected to %s!",g.argv[2]);
1020 }
1021
+3 -3
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -26,11 +26,11 @@
2626
** Main sub-menu for configuring the ticketing system.
2727
** WEBPAGE: tktsetup
2828
*/
2929
void tktsetup_page(void){
3030
login_check_credentials();
31
- if( !g.okSetup ){
31
+ if( !g.perm.Setup ){
3232
login_needed();
3333
}
3434
3535
style_header("Ticket Setup");
3636
@ <table border="0" cellspacing="20">
@@ -102,11 +102,11 @@
102102
){
103103
const char *z;
104104
int isSubmit;
105105
106106
login_check_credentials();
107
- if( !g.okSetup ){
107
+ if( !g.perm.Setup ){
108108
login_needed();
109109
}
110110
if( P("setup") ){
111111
cgi_redirect("tktsetup");
112112
}
@@ -690,11 +690,11 @@
690690
/*
691691
** WEBPAGE: tktsetup_timeline
692692
*/
693693
void tktsetup_timeline_page(void){
694694
login_check_credentials();
695
- if( !g.okSetup ){
695
+ if( !g.perm.Setup ){
696696
login_needed();
697697
}
698698
699699
if( P("setup") ){
700700
cgi_redirect("tktsetup");
701701
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -26,11 +26,11 @@
26 ** Main sub-menu for configuring the ticketing system.
27 ** WEBPAGE: tktsetup
28 */
29 void tktsetup_page(void){
30 login_check_credentials();
31 if( !g.okSetup ){
32 login_needed();
33 }
34
35 style_header("Ticket Setup");
36 @ <table border="0" cellspacing="20">
@@ -102,11 +102,11 @@
102 ){
103 const char *z;
104 int isSubmit;
105
106 login_check_credentials();
107 if( !g.okSetup ){
108 login_needed();
109 }
110 if( P("setup") ){
111 cgi_redirect("tktsetup");
112 }
@@ -690,11 +690,11 @@
690 /*
691 ** WEBPAGE: tktsetup_timeline
692 */
693 void tktsetup_timeline_page(void){
694 login_check_credentials();
695 if( !g.okSetup ){
696 login_needed();
697 }
698
699 if( P("setup") ){
700 cgi_redirect("tktsetup");
701
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -26,11 +26,11 @@
26 ** Main sub-menu for configuring the ticketing system.
27 ** WEBPAGE: tktsetup
28 */
29 void tktsetup_page(void){
30 login_check_credentials();
31 if( !g.perm.Setup ){
32 login_needed();
33 }
34
35 style_header("Ticket Setup");
36 @ <table border="0" cellspacing="20">
@@ -102,11 +102,11 @@
102 ){
103 const char *z;
104 int isSubmit;
105
106 login_check_credentials();
107 if( !g.perm.Setup ){
108 login_needed();
109 }
110 if( P("setup") ){
111 cgi_redirect("tktsetup");
112 }
@@ -690,11 +690,11 @@
690 /*
691 ** WEBPAGE: tktsetup_timeline
692 */
693 void tktsetup_timeline_page(void){
694 login_check_credentials();
695 if( !g.perm.Setup ){
696 login_needed();
697 }
698
699 if( P("setup") ){
700 cgi_redirect("tktsetup");
701
+12 -10
--- src/undo.c
+++ src/undo.c
@@ -45,19 +45,19 @@
4545
int old_link;
4646
Blob current;
4747
Blob new;
4848
zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
4949
old_link = db_column_int(&q, 3);
50
- new_link = file_islink(zFullname);
51
- new_exists = file_size(zFullname)>=0;
50
+ new_link = file_wd_islink(zFullname);
51
+ new_exists = file_wd_size(zFullname)>=0;
5252
if( new_exists ){
5353
if( new_link ){
5454
blob_read_link(&current, zFullname);
5555
}else{
5656
blob_read_from_file(&current, zFullname);
5757
}
58
- new_exe = file_isexe(zFullname);
58
+ new_exe = file_wd_isexe(zFullname);
5959
}else{
6060
blob_zero(&current);
6161
new_exe = 0;
6262
}
6363
blob_zero(&new);
@@ -71,18 +71,18 @@
7171
fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
7272
}else{
7373
fossil_print("NEW %s\n", zPathname);
7474
}
7575
if( new_exists && (new_link || old_link) ){
76
- unlink(zFullname);
76
+ file_delete(zFullname);
7777
}
78
- if( new_link ){
79
- create_symlink(blob_str(&new), zFullname);
78
+ if( old_link ){
79
+ symlink_create(blob_str(&new), zFullname);
8080
}else{
8181
blob_write_to_file(&new, zFullname);
8282
}
83
- file_setexe(zFullname, old_exe);
83
+ file_wd_setexe(zFullname, old_exe);
8484
}else{
8585
fossil_print("DELETE %s\n", zPathname);
8686
file_delete(zFullname);
8787
}
8888
blob_reset(&new);
@@ -270,15 +270,17 @@
270270
int isLink;
271271
Stmt q;
272272
273273
if( !undoActive ) return;
274274
zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
275
- existsFlag = file_size(zFullname)>=0;
275
+ existsFlag = file_wd_size(zFullname)>=0;
276
+ isLink = file_wd_islink(zFullname);
276277
db_prepare(&q,
277
- "INSERT OR IGNORE INTO undo(pathname,redoflag,existsflag,isExe,isLink,content)"
278
+ "INSERT OR IGNORE INTO"
279
+ " undo(pathname,redoflag,existsflag,isExe,isLink,content)"
278280
" VALUES(%Q,0,%d,%d,%d,:c)",
279
- zPathname, existsFlag, file_isexe(zFullname), file_islink(zFullname)
281
+ zPathname, existsFlag, file_wd_isexe(zFullname), isLink
280282
);
281283
if( existsFlag ){
282284
if( isLink ){
283285
blob_read_link(&content, zFullname);
284286
}else{
285287
--- src/undo.c
+++ src/undo.c
@@ -45,19 +45,19 @@
45 int old_link;
46 Blob current;
47 Blob new;
48 zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
49 old_link = db_column_int(&q, 3);
50 new_link = file_islink(zFullname);
51 new_exists = file_size(zFullname)>=0;
52 if( new_exists ){
53 if( new_link ){
54 blob_read_link(&current, zFullname);
55 }else{
56 blob_read_from_file(&current, zFullname);
57 }
58 new_exe = file_isexe(zFullname);
59 }else{
60 blob_zero(&current);
61 new_exe = 0;
62 }
63 blob_zero(&new);
@@ -71,18 +71,18 @@
71 fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
72 }else{
73 fossil_print("NEW %s\n", zPathname);
74 }
75 if( new_exists && (new_link || old_link) ){
76 unlink(zFullname);
77 }
78 if( new_link ){
79 create_symlink(blob_str(&new), zFullname);
80 }else{
81 blob_write_to_file(&new, zFullname);
82 }
83 file_setexe(zFullname, old_exe);
84 }else{
85 fossil_print("DELETE %s\n", zPathname);
86 file_delete(zFullname);
87 }
88 blob_reset(&new);
@@ -270,15 +270,17 @@
270 int isLink;
271 Stmt q;
272
273 if( !undoActive ) return;
274 zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
275 existsFlag = file_size(zFullname)>=0;
 
276 db_prepare(&q,
277 "INSERT OR IGNORE INTO undo(pathname,redoflag,existsflag,isExe,isLink,content)"
 
278 " VALUES(%Q,0,%d,%d,%d,:c)",
279 zPathname, existsFlag, file_isexe(zFullname), file_islink(zFullname)
280 );
281 if( existsFlag ){
282 if( isLink ){
283 blob_read_link(&content, zFullname);
284 }else{
285
--- src/undo.c
+++ src/undo.c
@@ -45,19 +45,19 @@
45 int old_link;
46 Blob current;
47 Blob new;
48 zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
49 old_link = db_column_int(&q, 3);
50 new_link = file_wd_islink(zFullname);
51 new_exists = file_wd_size(zFullname)>=0;
52 if( new_exists ){
53 if( new_link ){
54 blob_read_link(&current, zFullname);
55 }else{
56 blob_read_from_file(&current, zFullname);
57 }
58 new_exe = file_wd_isexe(zFullname);
59 }else{
60 blob_zero(&current);
61 new_exe = 0;
62 }
63 blob_zero(&new);
@@ -71,18 +71,18 @@
71 fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
72 }else{
73 fossil_print("NEW %s\n", zPathname);
74 }
75 if( new_exists && (new_link || old_link) ){
76 file_delete(zFullname);
77 }
78 if( old_link ){
79 symlink_create(blob_str(&new), zFullname);
80 }else{
81 blob_write_to_file(&new, zFullname);
82 }
83 file_wd_setexe(zFullname, old_exe);
84 }else{
85 fossil_print("DELETE %s\n", zPathname);
86 file_delete(zFullname);
87 }
88 blob_reset(&new);
@@ -270,15 +270,17 @@
270 int isLink;
271 Stmt q;
272
273 if( !undoActive ) return;
274 zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
275 existsFlag = file_wd_size(zFullname)>=0;
276 isLink = file_wd_islink(zFullname);
277 db_prepare(&q,
278 "INSERT OR IGNORE INTO"
279 " undo(pathname,redoflag,existsflag,isExe,isLink,content)"
280 " VALUES(%Q,0,%d,%d,%d,:c)",
281 zPathname, existsFlag, file_wd_isexe(zFullname), isLink
282 );
283 if( existsFlag ){
284 if( isLink ){
285 blob_read_link(&content, zFullname);
286 }else{
287
+30 -31
--- src/update.c
+++ src/update.c
@@ -223,11 +223,11 @@
223223
);
224224
225225
/* Compute file name changes on V->T. Record name changes in files that
226226
** have changed locally.
227227
*/
228
- find_filename_changes(vid, tid, &nChng, &aChng);
228
+ find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
229229
if( nChng ){
230230
for(i=0; i<nChng; i++){
231231
db_multi_exec(
232232
"UPDATE fv"
233233
" SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
@@ -303,11 +303,11 @@
303303
blob_append(&sql, "DELETE FROM fv WHERE ", -1);
304304
zSep = "";
305305
for(i=3; i<g.argc; i++){
306306
file_tree_name(g.argv[i], &treename, 1);
307307
if( file_isdir(g.argv[i])==1 ){
308
- if( blob_size(&treename) != 1 || blob_str(&treename)[0] != '.' ){
308
+ if( blob_size(&treename) != 1 || blob_str(&treename)[0] != '.' ){
309309
blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename);
310310
}else{
311311
blob_reset(&sql);
312312
break;
313313
}
@@ -367,11 +367,11 @@
367367
}else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
368368
/* The file is unedited. Change it to the target version */
369369
undo_save(zName);
370370
fossil_print("UPDATE %s\n", zName);
371371
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
372
- }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
372
+ }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){
373373
/* The file missing from the local check-out. Restore it to the
374374
** version that appears in the target. */
375375
fossil_print("UPDATE %s\n", zName);
376376
undo_save(zName);
377377
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
@@ -398,36 +398,35 @@
398398
if( nameChng ){
399399
fossil_print("MERGE %s -> %s\n", zName, zNewName);
400400
}else{
401401
fossil_print("MERGE %s\n", zName);
402402
}
403
- if( islinkv || islinkt /* || file_islink(zFullPath) */ ){
404
- //if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath);
403
+ if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){
405404
fossil_print("***** Cannot merge symlink %s\n", zNewName);
406405
nConflict++;
407406
}else{
408
- undo_save(zName);
409
- content_get(ridt, &t);
410
- content_get(ridv, &v);
411
- rc = merge_3way(&v, zFullPath, &t, &r);
412
- if( rc>=0 ){
413
- if( !nochangeFlag ){
414
- blob_write_to_file(&r, zFullNewPath);
415
- file_setexe(zFullNewPath, isexe);
416
- }
417
- if( rc>0 ){
418
- fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
419
- nConflict++;
420
- }
421
- }else{
422
- if( !nochangeFlag ){
423
- blob_write_to_file(&t, zFullNewPath);
424
- file_setexe(zFullNewPath, isexe);
425
- }
426
- fossil_print("***** Cannot merge binary file %s\n", zNewName);
427
- nConflict++;
428
- }
407
+ undo_save(zName);
408
+ content_get(ridt, &t);
409
+ content_get(ridv, &v);
410
+ rc = merge_3way(&v, zFullPath, &t, &r);
411
+ if( rc>=0 ){
412
+ if( !nochangeFlag ){
413
+ blob_write_to_file(&r, zFullNewPath);
414
+ file_wd_setexe(zFullNewPath, isexe);
415
+ }
416
+ if( rc>0 ){
417
+ fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
418
+ nConflict++;
419
+ }
420
+ }else{
421
+ if( !nochangeFlag ){
422
+ blob_write_to_file(&t, zFullNewPath);
423
+ file_wd_setexe(zFullNewPath, isexe);
424
+ }
425
+ fossil_print("***** Cannot merge binary file %s\n", zNewName);
426
+ nConflict++;
427
+ }
429428
}
430429
if( nameChng && !nochangeFlag ) file_delete(zFullPath);
431430
blob_reset(&v);
432431
blob_reset(&t);
433432
blob_reset(&r);
@@ -669,21 +668,21 @@
669668
}
670669
db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
671670
}else{
672671
sqlite3_int64 mtime;
673672
undo_save(zFile);
674
- if( file_size(zFull)>=0 && (isLink || file_islink(zFull)) ){
675
- unlink(zFull);
673
+ if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){
674
+ file_delete(zFull);
676675
}
677676
if( isLink ){
678
- create_symlink(blob_str(&record), zFull);
677
+ symlink_create(blob_str(&record), zFull);
679678
}else{
680679
blob_write_to_file(&record, zFull);
681680
}
682
- file_setexe(zFull, isExe);
681
+ file_wd_setexe(zFull, isExe);
683682
fossil_print("REVERTED: %s\n", zFile);
684
- mtime = file_mtime(zFull);
683
+ mtime = file_wd_mtime(zFull);
685684
db_multi_exec(
686685
"UPDATE vfile"
687686
" SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d, mrid=rid,"
688687
" pathname=coalesce(origname,pathname), origname=NULL"
689688
" WHERE pathname=%Q",
690689
--- src/update.c
+++ src/update.c
@@ -223,11 +223,11 @@
223 );
224
225 /* Compute file name changes on V->T. Record name changes in files that
226 ** have changed locally.
227 */
228 find_filename_changes(vid, tid, &nChng, &aChng);
229 if( nChng ){
230 for(i=0; i<nChng; i++){
231 db_multi_exec(
232 "UPDATE fv"
233 " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
@@ -303,11 +303,11 @@
303 blob_append(&sql, "DELETE FROM fv WHERE ", -1);
304 zSep = "";
305 for(i=3; i<g.argc; i++){
306 file_tree_name(g.argv[i], &treename, 1);
307 if( file_isdir(g.argv[i])==1 ){
308 if( blob_size(&treename) != 1 || blob_str(&treename)[0] != '.' ){
309 blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename);
310 }else{
311 blob_reset(&sql);
312 break;
313 }
@@ -367,11 +367,11 @@
367 }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
368 /* The file is unedited. Change it to the target version */
369 undo_save(zName);
370 fossil_print("UPDATE %s\n", zName);
371 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
372 }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
373 /* The file missing from the local check-out. Restore it to the
374 ** version that appears in the target. */
375 fossil_print("UPDATE %s\n", zName);
376 undo_save(zName);
377 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
@@ -398,36 +398,35 @@
398 if( nameChng ){
399 fossil_print("MERGE %s -> %s\n", zName, zNewName);
400 }else{
401 fossil_print("MERGE %s\n", zName);
402 }
403 if( islinkv || islinkt /* || file_islink(zFullPath) */ ){
404 //if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath);
405 fossil_print("***** Cannot merge symlink %s\n", zNewName);
406 nConflict++;
407 }else{
408 undo_save(zName);
409 content_get(ridt, &t);
410 content_get(ridv, &v);
411 rc = merge_3way(&v, zFullPath, &t, &r);
412 if( rc>=0 ){
413 if( !nochangeFlag ){
414 blob_write_to_file(&r, zFullNewPath);
415 file_setexe(zFullNewPath, isexe);
416 }
417 if( rc>0 ){
418 fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
419 nConflict++;
420 }
421 }else{
422 if( !nochangeFlag ){
423 blob_write_to_file(&t, zFullNewPath);
424 file_setexe(zFullNewPath, isexe);
425 }
426 fossil_print("***** Cannot merge binary file %s\n", zNewName);
427 nConflict++;
428 }
429 }
430 if( nameChng && !nochangeFlag ) file_delete(zFullPath);
431 blob_reset(&v);
432 blob_reset(&t);
433 blob_reset(&r);
@@ -669,21 +668,21 @@
669 }
670 db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
671 }else{
672 sqlite3_int64 mtime;
673 undo_save(zFile);
674 if( file_size(zFull)>=0 && (isLink || file_islink(zFull)) ){
675 unlink(zFull);
676 }
677 if( isLink ){
678 create_symlink(blob_str(&record), zFull);
679 }else{
680 blob_write_to_file(&record, zFull);
681 }
682 file_setexe(zFull, isExe);
683 fossil_print("REVERTED: %s\n", zFile);
684 mtime = file_mtime(zFull);
685 db_multi_exec(
686 "UPDATE vfile"
687 " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d, mrid=rid,"
688 " pathname=coalesce(origname,pathname), origname=NULL"
689 " WHERE pathname=%Q",
690
--- src/update.c
+++ src/update.c
@@ -223,11 +223,11 @@
223 );
224
225 /* Compute file name changes on V->T. Record name changes in files that
226 ** have changed locally.
227 */
228 find_filename_changes(vid, tid, 1, &nChng, &aChng, debugFlag ? "V->T": 0);
229 if( nChng ){
230 for(i=0; i<nChng; i++){
231 db_multi_exec(
232 "UPDATE fv"
233 " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
@@ -303,11 +303,11 @@
303 blob_append(&sql, "DELETE FROM fv WHERE ", -1);
304 zSep = "";
305 for(i=3; i<g.argc; i++){
306 file_tree_name(g.argv[i], &treename, 1);
307 if( file_isdir(g.argv[i])==1 ){
308 if( blob_size(&treename) != 1 || blob_str(&treename)[0] != '.' ){
309 blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename);
310 }else{
311 blob_reset(&sql);
312 break;
313 }
@@ -367,11 +367,11 @@
367 }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
368 /* The file is unedited. Change it to the target version */
369 undo_save(zName);
370 fossil_print("UPDATE %s\n", zName);
371 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
372 }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){
373 /* The file missing from the local check-out. Restore it to the
374 ** version that appears in the target. */
375 fossil_print("UPDATE %s\n", zName);
376 undo_save(zName);
377 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
@@ -398,36 +398,35 @@
398 if( nameChng ){
399 fossil_print("MERGE %s -> %s\n", zName, zNewName);
400 }else{
401 fossil_print("MERGE %s\n", zName);
402 }
403 if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){
 
404 fossil_print("***** Cannot merge symlink %s\n", zNewName);
405 nConflict++;
406 }else{
407 undo_save(zName);
408 content_get(ridt, &t);
409 content_get(ridv, &v);
410 rc = merge_3way(&v, zFullPath, &t, &r);
411 if( rc>=0 ){
412 if( !nochangeFlag ){
413 blob_write_to_file(&r, zFullNewPath);
414 file_wd_setexe(zFullNewPath, isexe);
415 }
416 if( rc>0 ){
417 fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
418 nConflict++;
419 }
420 }else{
421 if( !nochangeFlag ){
422 blob_write_to_file(&t, zFullNewPath);
423 file_wd_setexe(zFullNewPath, isexe);
424 }
425 fossil_print("***** Cannot merge binary file %s\n", zNewName);
426 nConflict++;
427 }
428 }
429 if( nameChng && !nochangeFlag ) file_delete(zFullPath);
430 blob_reset(&v);
431 blob_reset(&t);
432 blob_reset(&r);
@@ -669,21 +668,21 @@
668 }
669 db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
670 }else{
671 sqlite3_int64 mtime;
672 undo_save(zFile);
673 if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){
674 file_delete(zFull);
675 }
676 if( isLink ){
677 symlink_create(blob_str(&record), zFull);
678 }else{
679 blob_write_to_file(&record, zFull);
680 }
681 file_wd_setexe(zFull, isExe);
682 fossil_print("REVERTED: %s\n", zFile);
683 mtime = file_wd_mtime(zFull);
684 db_multi_exec(
685 "UPDATE vfile"
686 " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d, mrid=rid,"
687 " pathname=coalesce(origname,pathname), origname=NULL"
688 " WHERE pathname=%Q",
689
+1 -1
--- src/user.c
+++ src/user.c
@@ -393,11 +393,11 @@
393393
Stmt q;
394394
int cnt = 0;
395395
int rc;
396396
397397
login_check_credentials();
398
- if( !g.okAdmin ){ login_needed(); return; }
398
+ if( !g.perm.Admin ){ login_needed(); return; }
399399
create_accesslog_table();
400400
401401
if( P("delall") && P("delallbtn") ){
402402
db_multi_exec("DELETE FROM accesslog");
403403
cgi_redirectf("%s/access_log?y=%d&n=%d&o=%o", g.zTop, y, n, skip);
404404
--- src/user.c
+++ src/user.c
@@ -393,11 +393,11 @@
393 Stmt q;
394 int cnt = 0;
395 int rc;
396
397 login_check_credentials();
398 if( !g.okAdmin ){ login_needed(); return; }
399 create_accesslog_table();
400
401 if( P("delall") && P("delallbtn") ){
402 db_multi_exec("DELETE FROM accesslog");
403 cgi_redirectf("%s/access_log?y=%d&n=%d&o=%o", g.zTop, y, n, skip);
404
--- src/user.c
+++ src/user.c
@@ -393,11 +393,11 @@
393 Stmt q;
394 int cnt = 0;
395 int rc;
396
397 login_check_credentials();
398 if( !g.perm.Admin ){ login_needed(); return; }
399 create_accesslog_table();
400
401 if( P("delall") && P("delallbtn") ){
402 db_multi_exec("DELETE FROM accesslog");
403 cgi_redirectf("%s/access_log?y=%d&n=%d&o=%o", g.zTop, y, n, skip);
404
+13 -13
--- src/vfile.c
+++ src/vfile.c
@@ -166,11 +166,11 @@
166166
isDeleted = db_column_int(&q, 3);
167167
oldChnged = db_column_int(&q, 4);
168168
oldMtime = db_column_int64(&q, 7);
169169
if( isDeleted ){
170170
chnged = 1;
171
- }else if( !file_isfile_or_link(zName) && file_size(0)>=0 ){
171
+ }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){
172172
if( notFileIsFatal ){
173173
fossil_warning("not an ordinary file: %s", zName);
174174
nErr++;
175175
}
176176
chnged = 1;
@@ -179,12 +179,12 @@
179179
}else if( rid==0 ){
180180
chnged = 1;
181181
}
182182
if( chnged!=1 ){
183183
i64 origSize = db_column_int64(&q, 6);
184
- currentMtime = file_mtime(0);
185
- if( origSize!=file_size(0) ){
184
+ currentMtime = file_wd_mtime(0);
185
+ if( origSize!=file_wd_size(0) ){
186186
/* A file size change is definitive - the file has changed. No
187187
** need to check the sha1sum */
188188
chnged = 1;
189189
}
190190
}
@@ -247,17 +247,17 @@
247247
isExe = db_column_int(&q, 3);
248248
isLink = db_column_int(&q, 4);
249249
content_get(rid, &content);
250250
if( file_is_the_same(&content, zName) ){
251251
blob_reset(&content);
252
- if( file_setexe(zName, isExe) ){
252
+ if( file_wd_setexe(zName, isExe) ){
253253
db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
254
- file_mtime(zName), id);
254
+ file_wd_mtime(zName), id);
255255
}
256256
continue;
257257
}
258
- if( promptFlag && file_size(zName)>=0 ){
258
+ if( promptFlag && file_wd_size(zName)>=0 ){
259259
Blob ans;
260260
char *zMsg;
261261
char cReply;
262262
zMsg = mprintf("overwrite %s (a=always/y/N)? ", zName);
263263
prompt_user(zMsg, &ans);
@@ -276,22 +276,22 @@
276276
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
277277
if( file_isdir(zName) == 1 ){
278278
/*TODO(dchest): remove directories? */
279279
fossil_fatal("%s is directory, cannot overwrite\n", zName);
280280
}
281
- if( file_size(zName)>=0 && (isLink || file_islink(zName)) ){
281
+ if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){
282282
file_delete(zName);
283283
}
284284
if( isLink ){
285
- create_symlink(blob_str(&content), zName);
285
+ symlink_create(blob_str(&content), zName);
286286
}else{
287287
blob_write_to_file(&content, zName);
288288
}
289
- file_setexe(zName, isExe);
289
+ file_wd_setexe(zName, isExe);
290290
blob_reset(&content);
291291
db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
292
- file_mtime(zName), id);
292
+ file_wd_mtime(zName), id);
293293
}
294294
db_finalize(&q);
295295
}
296296
297297
@@ -393,11 +393,11 @@
393393
/* do nothing */
394394
}else if( file_isdir(zPath)==1 ){
395395
if( !vfile_top_of_checkout(zPath) ){
396396
vfile_scan(pPath, nPrefix, allFlag, pIgnore);
397397
}
398
- }else if( file_isfile_or_link(zPath) ){
398
+ }else if( file_wd_isfile_or_link(zPath) ){
399399
db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
400400
db_step(&ins);
401401
db_reset(&ins);
402402
}
403403
blob_resize(pPath, origSize);
@@ -452,11 +452,11 @@
452452
const char *zName = db_column_text(&q, 1);
453453
int isSelected = db_column_int(&q, 3);
454454
455455
if( isSelected ){
456456
md5sum_step_text(zName, -1);
457
- if( file_islink(zFullpath) ){
457
+ if( file_wd_islink(zFullpath) ){
458458
/* Instead of file content, use link destination path */
459459
Blob pathBuf;
460460
461461
sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n",
462462
blob_read_link(&pathBuf, zFullpath));
@@ -524,11 +524,11 @@
524524
const char *zFullpath = db_column_text(&q, 0);
525525
const char *zName = db_column_text(&q, 1);
526526
int rid = db_column_int(&q, 2);
527527
528528
blob_zero(&disk);
529
- if( file_islink(zFullpath) ){
529
+ if( file_wd_islink(zFullpath) ){
530530
rc = blob_read_link(&disk, zFullpath);
531531
}else{
532532
rc = blob_read_from_file(&disk, zFullpath);
533533
}
534534
if( rc<0 ){
535535
--- src/vfile.c
+++ src/vfile.c
@@ -166,11 +166,11 @@
166 isDeleted = db_column_int(&q, 3);
167 oldChnged = db_column_int(&q, 4);
168 oldMtime = db_column_int64(&q, 7);
169 if( isDeleted ){
170 chnged = 1;
171 }else if( !file_isfile_or_link(zName) && file_size(0)>=0 ){
172 if( notFileIsFatal ){
173 fossil_warning("not an ordinary file: %s", zName);
174 nErr++;
175 }
176 chnged = 1;
@@ -179,12 +179,12 @@
179 }else if( rid==0 ){
180 chnged = 1;
181 }
182 if( chnged!=1 ){
183 i64 origSize = db_column_int64(&q, 6);
184 currentMtime = file_mtime(0);
185 if( origSize!=file_size(0) ){
186 /* A file size change is definitive - the file has changed. No
187 ** need to check the sha1sum */
188 chnged = 1;
189 }
190 }
@@ -247,17 +247,17 @@
247 isExe = db_column_int(&q, 3);
248 isLink = db_column_int(&q, 4);
249 content_get(rid, &content);
250 if( file_is_the_same(&content, zName) ){
251 blob_reset(&content);
252 if( file_setexe(zName, isExe) ){
253 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
254 file_mtime(zName), id);
255 }
256 continue;
257 }
258 if( promptFlag && file_size(zName)>=0 ){
259 Blob ans;
260 char *zMsg;
261 char cReply;
262 zMsg = mprintf("overwrite %s (a=always/y/N)? ", zName);
263 prompt_user(zMsg, &ans);
@@ -276,22 +276,22 @@
276 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
277 if( file_isdir(zName) == 1 ){
278 /*TODO(dchest): remove directories? */
279 fossil_fatal("%s is directory, cannot overwrite\n", zName);
280 }
281 if( file_size(zName)>=0 && (isLink || file_islink(zName)) ){
282 file_delete(zName);
283 }
284 if( isLink ){
285 create_symlink(blob_str(&content), zName);
286 }else{
287 blob_write_to_file(&content, zName);
288 }
289 file_setexe(zName, isExe);
290 blob_reset(&content);
291 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
292 file_mtime(zName), id);
293 }
294 db_finalize(&q);
295 }
296
297
@@ -393,11 +393,11 @@
393 /* do nothing */
394 }else if( file_isdir(zPath)==1 ){
395 if( !vfile_top_of_checkout(zPath) ){
396 vfile_scan(pPath, nPrefix, allFlag, pIgnore);
397 }
398 }else if( file_isfile_or_link(zPath) ){
399 db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
400 db_step(&ins);
401 db_reset(&ins);
402 }
403 blob_resize(pPath, origSize);
@@ -452,11 +452,11 @@
452 const char *zName = db_column_text(&q, 1);
453 int isSelected = db_column_int(&q, 3);
454
455 if( isSelected ){
456 md5sum_step_text(zName, -1);
457 if( file_islink(zFullpath) ){
458 /* Instead of file content, use link destination path */
459 Blob pathBuf;
460
461 sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n",
462 blob_read_link(&pathBuf, zFullpath));
@@ -524,11 +524,11 @@
524 const char *zFullpath = db_column_text(&q, 0);
525 const char *zName = db_column_text(&q, 1);
526 int rid = db_column_int(&q, 2);
527
528 blob_zero(&disk);
529 if( file_islink(zFullpath) ){
530 rc = blob_read_link(&disk, zFullpath);
531 }else{
532 rc = blob_read_from_file(&disk, zFullpath);
533 }
534 if( rc<0 ){
535
--- src/vfile.c
+++ src/vfile.c
@@ -166,11 +166,11 @@
166 isDeleted = db_column_int(&q, 3);
167 oldChnged = db_column_int(&q, 4);
168 oldMtime = db_column_int64(&q, 7);
169 if( isDeleted ){
170 chnged = 1;
171 }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){
172 if( notFileIsFatal ){
173 fossil_warning("not an ordinary file: %s", zName);
174 nErr++;
175 }
176 chnged = 1;
@@ -179,12 +179,12 @@
179 }else if( rid==0 ){
180 chnged = 1;
181 }
182 if( chnged!=1 ){
183 i64 origSize = db_column_int64(&q, 6);
184 currentMtime = file_wd_mtime(0);
185 if( origSize!=file_wd_size(0) ){
186 /* A file size change is definitive - the file has changed. No
187 ** need to check the sha1sum */
188 chnged = 1;
189 }
190 }
@@ -247,17 +247,17 @@
247 isExe = db_column_int(&q, 3);
248 isLink = db_column_int(&q, 4);
249 content_get(rid, &content);
250 if( file_is_the_same(&content, zName) ){
251 blob_reset(&content);
252 if( file_wd_setexe(zName, isExe) ){
253 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
254 file_wd_mtime(zName), id);
255 }
256 continue;
257 }
258 if( promptFlag && file_wd_size(zName)>=0 ){
259 Blob ans;
260 char *zMsg;
261 char cReply;
262 zMsg = mprintf("overwrite %s (a=always/y/N)? ", zName);
263 prompt_user(zMsg, &ans);
@@ -276,22 +276,22 @@
276 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
277 if( file_isdir(zName) == 1 ){
278 /*TODO(dchest): remove directories? */
279 fossil_fatal("%s is directory, cannot overwrite\n", zName);
280 }
281 if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){
282 file_delete(zName);
283 }
284 if( isLink ){
285 symlink_create(blob_str(&content), zName);
286 }else{
287 blob_write_to_file(&content, zName);
288 }
289 file_wd_setexe(zName, isExe);
290 blob_reset(&content);
291 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
292 file_wd_mtime(zName), id);
293 }
294 db_finalize(&q);
295 }
296
297
@@ -393,11 +393,11 @@
393 /* do nothing */
394 }else if( file_isdir(zPath)==1 ){
395 if( !vfile_top_of_checkout(zPath) ){
396 vfile_scan(pPath, nPrefix, allFlag, pIgnore);
397 }
398 }else if( file_wd_isfile_or_link(zPath) ){
399 db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
400 db_step(&ins);
401 db_reset(&ins);
402 }
403 blob_resize(pPath, origSize);
@@ -452,11 +452,11 @@
452 const char *zName = db_column_text(&q, 1);
453 int isSelected = db_column_int(&q, 3);
454
455 if( isSelected ){
456 md5sum_step_text(zName, -1);
457 if( file_wd_islink(zFullpath) ){
458 /* Instead of file content, use link destination path */
459 Blob pathBuf;
460
461 sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n",
462 blob_read_link(&pathBuf, zFullpath));
@@ -524,11 +524,11 @@
524 const char *zFullpath = db_column_text(&q, 0);
525 const char *zName = db_column_text(&q, 1);
526 int rid = db_column_int(&q, 2);
527
528 blob_zero(&disk);
529 if( file_wd_islink(zFullpath) ){
530 rc = blob_read_link(&disk, zFullpath);
531 }else{
532 rc = blob_read_from_file(&disk, zFullpath);
533 }
534 if( rc<0 ){
535
+19 -19
--- src/wiki.c
+++ src/wiki.c
@@ -90,11 +90,11 @@
9090
if( fossil_strcmp(zIndexPage, zPathInfo)==0 ) zIndexPage = 0;
9191
}
9292
if( zIndexPage ){
9393
cgi_redirectf("%s/%s", g.zTop, zIndexPage);
9494
}
95
- if( !g.okRdWiki ){
95
+ if( !g.perm.RdWiki ){
9696
cgi_redirectf("%s/login?g=%s/home", g.zTop, g.zTop);
9797
}
9898
if( zPageName ){
9999
login_check_credentials();
100100
g.zExtra = zPageName;
@@ -135,11 +135,11 @@
135135
char *zBody = mprintf("%s","<i>Empty Page</i>");
136136
Stmt q;
137137
int cnt = 0;
138138
139139
login_check_credentials();
140
- if( !g.okRdWiki ){ login_needed(); return; }
140
+ if( !g.perm.RdWiki ){ login_needed(); return; }
141141
zPageName = P("name");
142142
if( zPageName==0 ){
143143
style_header("Wiki");
144144
@ <ul>
145145
{ char *zHomePageName = db_get("project-name",0);
@@ -152,13 +152,13 @@
152152
@ pages. </li>
153153
@ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for
154154
@ wiki.</li>
155155
@ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a>
156156
@ to experiment.</li>
157
- if( g.okNewWiki ){
157
+ if( g.perm.NewWiki ){
158158
@ <li> Create a <a href="%s(g.zTop)/wikinew">new wiki page</a>.</li>
159
- if( g.okWrite ){
159
+ if( g.perm.Write ){
160160
@ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li>
161161
}
162162
}
163163
@ <li> <a href="%s(g.zTop)/wcontent">List of All Wiki Pages</a>
164164
@ available on this server.</li>
@@ -186,24 +186,24 @@
186186
if( pWiki ){
187187
zBody = pWiki->zWiki;
188188
}
189189
}
190190
if( !g.isHome ){
191
- if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
191
+ if( (rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki) ){
192192
style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
193193
g.zTop, zPageName);
194194
}
195
- if( rid && g.okApndWiki && g.okAttach ){
195
+ if( rid && g.perm.ApndWiki && g.perm.Attach ){
196196
style_submenu_element("Attach", "Add An Attachment",
197197
"%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T",
198198
g.zTop, zPageName, g.zTop, zPageName);
199199
}
200
- if( rid && g.okApndWiki ){
200
+ if( rid && g.perm.ApndWiki ){
201201
style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
202202
g.zTop, zPageName);
203203
}
204
- if( g.okHistory ){
204
+ if( g.perm.History ){
205205
style_submenu_element("History", "History", "%s/whistory?name=%T",
206206
g.zTop, zPageName);
207207
}
208208
}
209209
style_header(zPageName);
@@ -225,19 +225,19 @@
225225
@ <hr /><h2>Attachments:</h2>
226226
@ <ul>
227227
}
228228
cnt++;
229229
@ <li>
230
- if( g.okHistory && g.okRead ){
230
+ if( g.perm.History && g.perm.Read ){
231231
@ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
232232
@ %h(zFile)</a>
233233
}else{
234
- @ <li>%h(zFile)
234
+ @ %h(zFile)
235235
}
236236
@ added by %h(zUser) on
237237
hyperlink_to_date(zDate, ".");
238
- if( g.okWrWiki && g.okAttach ){
238
+ if( g.perm.WrWiki && g.perm.Attach ){
239239
@ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
240240
}
241241
@ </li>
242242
}
243243
if( cnt ){
@@ -271,11 +271,11 @@
271271
login_check_credentials();
272272
zPageName = PD("name","");
273273
if( check_name(zPageName) ) return;
274274
isSandbox = is_sandbox(zPageName);
275275
if( isSandbox ){
276
- if( !g.okWrWiki ){
276
+ if( !g.perm.WrWiki ){
277277
login_needed();
278278
return;
279279
}
280280
if( zBody==0 ){
281281
zBody = db_get("sandbox","");
@@ -286,11 +286,11 @@
286286
"SELECT rid FROM tagxref"
287287
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
288288
" ORDER BY mtime DESC", zTag
289289
);
290290
free(zTag);
291
- if( (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){
291
+ if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
292292
login_needed();
293293
return;
294294
}
295295
if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
296296
zBody = pWiki->zWiki;
@@ -375,11 +375,11 @@
375375
** to the wikiedit screen for that new page.
376376
*/
377377
void wikinew_page(void){
378378
const char *zName;
379379
login_check_credentials();
380
- if( !g.okNewWiki ){
380
+ if( !g.perm.NewWiki ){
381381
login_needed();
382382
return;
383383
}
384384
zName = PD("name","");
385385
if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
@@ -450,11 +450,11 @@
450450
if( !rid ){
451451
fossil_redirect_home();
452452
return;
453453
}
454454
}
455
- if( !g.okApndWiki ){
455
+ if( !g.perm.ApndWiki ){
456456
login_needed();
457457
return;
458458
}
459459
if( P("submit")!=0 && P("r")!=0 && P("u")!=0 ){
460460
char *zDate;
@@ -560,11 +560,11 @@
560560
Stmt q;
561561
char *zTitle;
562562
char *zSQL;
563563
const char *zPageName;
564564
login_check_credentials();
565
- if( !g.okHistory ){ login_needed(); return; }
565
+ if( !g.perm.History ){ login_needed(); return; }
566566
zPageName = PD("name","");
567567
zTitle = mprintf("History Of %s", zPageName);
568568
style_header(zTitle);
569569
free(zTitle);
570570
@@ -596,11 +596,11 @@
596596
Manifest *pW1, *pW2 = 0;
597597
Blob w1, w2, d;
598598
599599
login_check_credentials();
600600
rid1 = atoi(PD("a","0"));
601
- if( !g.okHistory ){ login_needed(); return; }
601
+ if( !g.perm.History ){ login_needed(); return; }
602602
if( rid1==0 ) fossil_redirect_home();
603603
rid2 = atoi(PD("b","0"));
604604
zPageName = PD("name","");
605605
zTitle = mprintf("Changes To %s", zPageName);
606606
style_header(zTitle);
@@ -642,11 +642,11 @@
642642
void wcontent_page(void){
643643
Stmt q;
644644
int showAll = P("all")!=0;
645645
646646
login_check_credentials();
647
- if( !g.okRdWiki ){ login_needed(); return; }
647
+ if( !g.perm.RdWiki ){ login_needed(); return; }
648648
style_header("Available Wiki Pages");
649649
if( showAll ){
650650
style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop);
651651
}else{
652652
style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop);
@@ -681,11 +681,11 @@
681681
*/
682682
void wfind_page(void){
683683
Stmt q;
684684
const char * zTitle;
685685
login_check_credentials();
686
- if( !g.okRdWiki ){ login_needed(); return; }
686
+ if( !g.perm.RdWiki ){ login_needed(); return; }
687687
zTitle = PD("title","*");
688688
style_header("Wiki Pages Found");
689689
@ <ul>
690690
db_prepare(&q,
691691
"SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
692692
--- src/wiki.c
+++ src/wiki.c
@@ -90,11 +90,11 @@
90 if( fossil_strcmp(zIndexPage, zPathInfo)==0 ) zIndexPage = 0;
91 }
92 if( zIndexPage ){
93 cgi_redirectf("%s/%s", g.zTop, zIndexPage);
94 }
95 if( !g.okRdWiki ){
96 cgi_redirectf("%s/login?g=%s/home", g.zTop, g.zTop);
97 }
98 if( zPageName ){
99 login_check_credentials();
100 g.zExtra = zPageName;
@@ -135,11 +135,11 @@
135 char *zBody = mprintf("%s","<i>Empty Page</i>");
136 Stmt q;
137 int cnt = 0;
138
139 login_check_credentials();
140 if( !g.okRdWiki ){ login_needed(); return; }
141 zPageName = P("name");
142 if( zPageName==0 ){
143 style_header("Wiki");
144 @ <ul>
145 { char *zHomePageName = db_get("project-name",0);
@@ -152,13 +152,13 @@
152 @ pages. </li>
153 @ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for
154 @ wiki.</li>
155 @ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a>
156 @ to experiment.</li>
157 if( g.okNewWiki ){
158 @ <li> Create a <a href="%s(g.zTop)/wikinew">new wiki page</a>.</li>
159 if( g.okWrite ){
160 @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li>
161 }
162 }
163 @ <li> <a href="%s(g.zTop)/wcontent">List of All Wiki Pages</a>
164 @ available on this server.</li>
@@ -186,24 +186,24 @@
186 if( pWiki ){
187 zBody = pWiki->zWiki;
188 }
189 }
190 if( !g.isHome ){
191 if( (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){
192 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
193 g.zTop, zPageName);
194 }
195 if( rid && g.okApndWiki && g.okAttach ){
196 style_submenu_element("Attach", "Add An Attachment",
197 "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T",
198 g.zTop, zPageName, g.zTop, zPageName);
199 }
200 if( rid && g.okApndWiki ){
201 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
202 g.zTop, zPageName);
203 }
204 if( g.okHistory ){
205 style_submenu_element("History", "History", "%s/whistory?name=%T",
206 g.zTop, zPageName);
207 }
208 }
209 style_header(zPageName);
@@ -225,19 +225,19 @@
225 @ <hr /><h2>Attachments:</h2>
226 @ <ul>
227 }
228 cnt++;
229 @ <li>
230 if( g.okHistory && g.okRead ){
231 @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
232 @ %h(zFile)</a>
233 }else{
234 @ <li>%h(zFile)
235 }
236 @ added by %h(zUser) on
237 hyperlink_to_date(zDate, ".");
238 if( g.okWrWiki && g.okAttach ){
239 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
240 }
241 @ </li>
242 }
243 if( cnt ){
@@ -271,11 +271,11 @@
271 login_check_credentials();
272 zPageName = PD("name","");
273 if( check_name(zPageName) ) return;
274 isSandbox = is_sandbox(zPageName);
275 if( isSandbox ){
276 if( !g.okWrWiki ){
277 login_needed();
278 return;
279 }
280 if( zBody==0 ){
281 zBody = db_get("sandbox","");
@@ -286,11 +286,11 @@
286 "SELECT rid FROM tagxref"
287 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
288 " ORDER BY mtime DESC", zTag
289 );
290 free(zTag);
291 if( (rid && !g.okWrWiki) || (!rid && !g.okNewWiki) ){
292 login_needed();
293 return;
294 }
295 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
296 zBody = pWiki->zWiki;
@@ -375,11 +375,11 @@
375 ** to the wikiedit screen for that new page.
376 */
377 void wikinew_page(void){
378 const char *zName;
379 login_check_credentials();
380 if( !g.okNewWiki ){
381 login_needed();
382 return;
383 }
384 zName = PD("name","");
385 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
@@ -450,11 +450,11 @@
450 if( !rid ){
451 fossil_redirect_home();
452 return;
453 }
454 }
455 if( !g.okApndWiki ){
456 login_needed();
457 return;
458 }
459 if( P("submit")!=0 && P("r")!=0 && P("u")!=0 ){
460 char *zDate;
@@ -560,11 +560,11 @@
560 Stmt q;
561 char *zTitle;
562 char *zSQL;
563 const char *zPageName;
564 login_check_credentials();
565 if( !g.okHistory ){ login_needed(); return; }
566 zPageName = PD("name","");
567 zTitle = mprintf("History Of %s", zPageName);
568 style_header(zTitle);
569 free(zTitle);
570
@@ -596,11 +596,11 @@
596 Manifest *pW1, *pW2 = 0;
597 Blob w1, w2, d;
598
599 login_check_credentials();
600 rid1 = atoi(PD("a","0"));
601 if( !g.okHistory ){ login_needed(); return; }
602 if( rid1==0 ) fossil_redirect_home();
603 rid2 = atoi(PD("b","0"));
604 zPageName = PD("name","");
605 zTitle = mprintf("Changes To %s", zPageName);
606 style_header(zTitle);
@@ -642,11 +642,11 @@
642 void wcontent_page(void){
643 Stmt q;
644 int showAll = P("all")!=0;
645
646 login_check_credentials();
647 if( !g.okRdWiki ){ login_needed(); return; }
648 style_header("Available Wiki Pages");
649 if( showAll ){
650 style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop);
651 }else{
652 style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop);
@@ -681,11 +681,11 @@
681 */
682 void wfind_page(void){
683 Stmt q;
684 const char * zTitle;
685 login_check_credentials();
686 if( !g.okRdWiki ){ login_needed(); return; }
687 zTitle = PD("title","*");
688 style_header("Wiki Pages Found");
689 @ <ul>
690 db_prepare(&q,
691 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
692
--- src/wiki.c
+++ src/wiki.c
@@ -90,11 +90,11 @@
90 if( fossil_strcmp(zIndexPage, zPathInfo)==0 ) zIndexPage = 0;
91 }
92 if( zIndexPage ){
93 cgi_redirectf("%s/%s", g.zTop, zIndexPage);
94 }
95 if( !g.perm.RdWiki ){
96 cgi_redirectf("%s/login?g=%s/home", g.zTop, g.zTop);
97 }
98 if( zPageName ){
99 login_check_credentials();
100 g.zExtra = zPageName;
@@ -135,11 +135,11 @@
135 char *zBody = mprintf("%s","<i>Empty Page</i>");
136 Stmt q;
137 int cnt = 0;
138
139 login_check_credentials();
140 if( !g.perm.RdWiki ){ login_needed(); return; }
141 zPageName = P("name");
142 if( zPageName==0 ){
143 style_header("Wiki");
144 @ <ul>
145 { char *zHomePageName = db_get("project-name",0);
@@ -152,13 +152,13 @@
152 @ pages. </li>
153 @ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for
154 @ wiki.</li>
155 @ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a>
156 @ to experiment.</li>
157 if( g.perm.NewWiki ){
158 @ <li> Create a <a href="%s(g.zTop)/wikinew">new wiki page</a>.</li>
159 if( g.perm.Write ){
160 @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li>
161 }
162 }
163 @ <li> <a href="%s(g.zTop)/wcontent">List of All Wiki Pages</a>
164 @ available on this server.</li>
@@ -186,24 +186,24 @@
186 if( pWiki ){
187 zBody = pWiki->zWiki;
188 }
189 }
190 if( !g.isHome ){
191 if( (rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki) ){
192 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
193 g.zTop, zPageName);
194 }
195 if( rid && g.perm.ApndWiki && g.perm.Attach ){
196 style_submenu_element("Attach", "Add An Attachment",
197 "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T",
198 g.zTop, zPageName, g.zTop, zPageName);
199 }
200 if( rid && g.perm.ApndWiki ){
201 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
202 g.zTop, zPageName);
203 }
204 if( g.perm.History ){
205 style_submenu_element("History", "History", "%s/whistory?name=%T",
206 g.zTop, zPageName);
207 }
208 }
209 style_header(zPageName);
@@ -225,19 +225,19 @@
225 @ <hr /><h2>Attachments:</h2>
226 @ <ul>
227 }
228 cnt++;
229 @ <li>
230 if( g.perm.History && g.perm.Read ){
231 @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
232 @ %h(zFile)</a>
233 }else{
234 @ %h(zFile)
235 }
236 @ added by %h(zUser) on
237 hyperlink_to_date(zDate, ".");
238 if( g.perm.WrWiki && g.perm.Attach ){
239 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
240 }
241 @ </li>
242 }
243 if( cnt ){
@@ -271,11 +271,11 @@
271 login_check_credentials();
272 zPageName = PD("name","");
273 if( check_name(zPageName) ) return;
274 isSandbox = is_sandbox(zPageName);
275 if( isSandbox ){
276 if( !g.perm.WrWiki ){
277 login_needed();
278 return;
279 }
280 if( zBody==0 ){
281 zBody = db_get("sandbox","");
@@ -286,11 +286,11 @@
286 "SELECT rid FROM tagxref"
287 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
288 " ORDER BY mtime DESC", zTag
289 );
290 free(zTag);
291 if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
292 login_needed();
293 return;
294 }
295 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
296 zBody = pWiki->zWiki;
@@ -375,11 +375,11 @@
375 ** to the wikiedit screen for that new page.
376 */
377 void wikinew_page(void){
378 const char *zName;
379 login_check_credentials();
380 if( !g.perm.NewWiki ){
381 login_needed();
382 return;
383 }
384 zName = PD("name","");
385 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
@@ -450,11 +450,11 @@
450 if( !rid ){
451 fossil_redirect_home();
452 return;
453 }
454 }
455 if( !g.perm.ApndWiki ){
456 login_needed();
457 return;
458 }
459 if( P("submit")!=0 && P("r")!=0 && P("u")!=0 ){
460 char *zDate;
@@ -560,11 +560,11 @@
560 Stmt q;
561 char *zTitle;
562 char *zSQL;
563 const char *zPageName;
564 login_check_credentials();
565 if( !g.perm.History ){ login_needed(); return; }
566 zPageName = PD("name","");
567 zTitle = mprintf("History Of %s", zPageName);
568 style_header(zTitle);
569 free(zTitle);
570
@@ -596,11 +596,11 @@
596 Manifest *pW1, *pW2 = 0;
597 Blob w1, w2, d;
598
599 login_check_credentials();
600 rid1 = atoi(PD("a","0"));
601 if( !g.perm.History ){ login_needed(); return; }
602 if( rid1==0 ) fossil_redirect_home();
603 rid2 = atoi(PD("b","0"));
604 zPageName = PD("name","");
605 zTitle = mprintf("Changes To %s", zPageName);
606 style_header(zTitle);
@@ -642,11 +642,11 @@
642 void wcontent_page(void){
643 Stmt q;
644 int showAll = P("all")!=0;
645
646 login_check_credentials();
647 if( !g.perm.RdWiki ){ login_needed(); return; }
648 style_header("Available Wiki Pages");
649 if( showAll ){
650 style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop);
651 }else{
652 style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop);
@@ -681,11 +681,11 @@
681 */
682 void wfind_page(void){
683 Stmt q;
684 const char * zTitle;
685 login_check_credentials();
686 if( !g.perm.RdWiki ){ login_needed(); return; }
687 zTitle = PD("title","*");
688 style_header("Wiki Pages Found");
689 @ <ul>
690 db_prepare(&q,
691 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
692
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1043,17 +1043,17 @@
10431043
|| strncmp(zTarget, "mailto:", 7)==0
10441044
){
10451045
blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
10461046
/* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
10471047
}else if( zTarget[0]=='/' ){
1048
- if( 1 /* g.okHistory */ ){
1048
+ if( 1 /* g.perm.History */ ){
10491049
blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
10501050
}else{
10511051
zTerm = "";
10521052
}
10531053
}else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1054
- if( 1 /* g.okHistory */ ){
1054
+ if( 1 /* g.perm.History */ ){
10551055
blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
10561056
}else{
10571057
zTerm = "";
10581058
}
10591059
}else if( is_valid_uuid(zTarget) ){
@@ -1061,11 +1061,11 @@
10611061
if( is_ticket(zTarget, &isClosed) ){
10621062
/* Special display processing for tickets. Display the hyperlink
10631063
** as crossed out if the ticket is closed.
10641064
*/
10651065
if( isClosed ){
1066
- if( g.okHistory ){
1066
+ if( g.perm.History ){
10671067
blob_appendf(p->pOut,
10681068
"<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[",
10691069
g.zTop, zTarget
10701070
);
10711071
zTerm = "]</span></a>";
@@ -1072,11 +1072,11 @@
10721072
}else{
10731073
blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">[");
10741074
zTerm = "]</span>";
10751075
}
10761076
}else{
1077
- if( g.okHistory ){
1077
+ if( g.perm.History ){
10781078
blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[",
10791079
g.zTop, zTarget
10801080
);
10811081
zTerm = "]</a>";
10821082
}else{
@@ -1085,11 +1085,11 @@
10851085
}
10861086
}
10871087
}else if( !in_this_repo(zTarget) ){
10881088
blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
10891089
zTerm = "]</span>";
1090
- }else if( g.okHistory ){
1090
+ }else if( g.perm.History ){
10911091
blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget);
10921092
zTerm = "]</a>";
10931093
}
10941094
}else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
10951095
&& db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
10961096
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1043,17 +1043,17 @@
1043 || strncmp(zTarget, "mailto:", 7)==0
1044 ){
1045 blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
1046 /* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
1047 }else if( zTarget[0]=='/' ){
1048 if( 1 /* g.okHistory */ ){
1049 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
1050 }else{
1051 zTerm = "";
1052 }
1053 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1054 if( 1 /* g.okHistory */ ){
1055 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
1056 }else{
1057 zTerm = "";
1058 }
1059 }else if( is_valid_uuid(zTarget) ){
@@ -1061,11 +1061,11 @@
1061 if( is_ticket(zTarget, &isClosed) ){
1062 /* Special display processing for tickets. Display the hyperlink
1063 ** as crossed out if the ticket is closed.
1064 */
1065 if( isClosed ){
1066 if( g.okHistory ){
1067 blob_appendf(p->pOut,
1068 "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[",
1069 g.zTop, zTarget
1070 );
1071 zTerm = "]</span></a>";
@@ -1072,11 +1072,11 @@
1072 }else{
1073 blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">[");
1074 zTerm = "]</span>";
1075 }
1076 }else{
1077 if( g.okHistory ){
1078 blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[",
1079 g.zTop, zTarget
1080 );
1081 zTerm = "]</a>";
1082 }else{
@@ -1085,11 +1085,11 @@
1085 }
1086 }
1087 }else if( !in_this_repo(zTarget) ){
1088 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
1089 zTerm = "]</span>";
1090 }else if( g.okHistory ){
1091 blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget);
1092 zTerm = "]</a>";
1093 }
1094 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
1095 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
1096
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1043,17 +1043,17 @@
1043 || strncmp(zTarget, "mailto:", 7)==0
1044 ){
1045 blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
1046 /* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
1047 }else if( zTarget[0]=='/' ){
1048 if( 1 /* g.perm.History */ ){
1049 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
1050 }else{
1051 zTerm = "";
1052 }
1053 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1054 if( 1 /* g.perm.History */ ){
1055 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
1056 }else{
1057 zTerm = "";
1058 }
1059 }else if( is_valid_uuid(zTarget) ){
@@ -1061,11 +1061,11 @@
1061 if( is_ticket(zTarget, &isClosed) ){
1062 /* Special display processing for tickets. Display the hyperlink
1063 ** as crossed out if the ticket is closed.
1064 */
1065 if( isClosed ){
1066 if( g.perm.History ){
1067 blob_appendf(p->pOut,
1068 "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[",
1069 g.zTop, zTarget
1070 );
1071 zTerm = "]</span></a>";
@@ -1072,11 +1072,11 @@
1072 }else{
1073 blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">[");
1074 zTerm = "]</span>";
1075 }
1076 }else{
1077 if( g.perm.History ){
1078 blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[",
1079 g.zTop, zTarget
1080 );
1081 zTerm = "]</a>";
1082 }else{
@@ -1085,11 +1085,11 @@
1085 }
1086 }
1087 }else if( !in_this_repo(zTarget) ){
1088 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
1089 zTerm = "]</span>";
1090 }else if( g.perm.History ){
1091 blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget);
1092 zTerm = "]</a>";
1093 }
1094 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
1095 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
1096
+17 -16
--- src/xfer.c
+++ src/xfer.c
@@ -129,11 +129,11 @@
129129
blob_extract(pXfer->pIn, n, &content);
130130
if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
131131
/* Ignore files that have been shunned */
132132
return;
133133
}
134
- if( isPriv && !g.okPrivate ){
134
+ if( isPriv && !g.perm.Private ){
135135
/* Do not accept private files if not authorized */
136136
return;
137137
}
138138
if( cloneFlag ){
139139
if( pXfer->nToken==4 ){
@@ -227,11 +227,11 @@
227227
|| (pXfer->nToken==5 && !blob_is_uuid(&pXfer->aToken[2]))
228228
){
229229
blob_appendf(&pXfer->err, "malformed cfile line");
230230
return;
231231
}
232
- if( isPriv && !g.okPrivate ){
232
+ if( isPriv && !g.perm.Private ){
233233
/* Do not accept private files if not authorized */
234234
return;
235235
}
236236
blob_zero(&content);
237237
blob_extract(pXfer->pIn, szC, &content);
@@ -816,10 +816,11 @@
816816
login_set_anon_nobody_capabilities();
817817
login_check_credentials();
818818
memset(&xfer, 0, sizeof(xfer));
819819
blobarray_zero(xfer.aToken, count(xfer.aToken));
820820
cgi_set_content_type(g.zContentType);
821
+ cgi_reset_content();
821822
if( db_schema_is_outofdate() ){
822823
@ error database\sschema\sis\sout-of-date\son\sthe\sserver.
823824
return;
824825
}
825826
blob_zero(&xfer.err);
@@ -907,11 +908,11 @@
907908
&& blob_is_uuid(&xfer.aToken[1])
908909
){
909910
if( isPush ){
910911
if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){
911912
rid_from_uuid(&xfer.aToken[1], 1, 0);
912
- }else if( g.okPrivate ){
913
+ }else if( g.perm.Private ){
913914
rid_from_uuid(&xfer.aToken[1], 1, 1);
914915
}else{
915916
server_private_xfer_not_authorized();
916917
}
917918
}
@@ -940,19 +941,19 @@
940941
nErr++;
941942
break;
942943
}
943944
login_check_credentials();
944945
if( blob_eq(&xfer.aToken[0], "pull") ){
945
- if( !g.okRead ){
946
+ if( !g.perm.Read ){
946947
cgi_reset_content();
947948
@ error not\sauthorized\sto\sread
948949
nErr++;
949950
break;
950951
}
951952
isPull = 1;
952953
}else{
953
- if( !g.okWrite ){
954
+ if( !g.perm.Write ){
954955
if( !isPull ){
955956
cgi_reset_content();
956957
@ error not\sauthorized\sto\swrite
957958
nErr++;
958959
}else{
@@ -969,11 +970,11 @@
969970
** The client knows nothing. Tell all.
970971
*/
971972
if( blob_eq(&xfer.aToken[0], "clone") ){
972973
int iVers;
973974
login_check_credentials();
974
- if( !g.okClone ){
975
+ if( !g.perm.Clone ){
975976
cgi_reset_content();
976977
@ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))
977978
@ error not\sauthorized\sto\sclone
978979
nErr++;
979980
break;
@@ -1013,11 +1014,11 @@
10131014
*/
10141015
if( blob_eq(&xfer.aToken[0], "login")
10151016
&& xfer.nToken==4
10161017
){
10171018
if( disableLogin ){
1018
- g.okRead = g.okWrite = g.okPrivate = g.okAdmin = 1;
1019
+ g.perm.Read = g.perm.Write = g.perm.Private = g.perm.Admin = 1;
10191020
}else{
10201021
if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
10211022
|| check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
10221023
){
10231024
cgi_reset_content();
@@ -1033,17 +1034,17 @@
10331034
** Request a configuration value
10341035
*/
10351036
if( blob_eq(&xfer.aToken[0], "reqconfig")
10361037
&& xfer.nToken==2
10371038
){
1038
- if( g.okRead ){
1039
+ if( g.perm.Read ){
10391040
char *zName = blob_str(&xfer.aToken[1]);
10401041
if( zName[0]=='/' ){
10411042
/* New style configuration transfer */
10421043
int groupMask = configure_name_to_mask(&zName[1], 0);
1043
- if( !g.okAdmin ) groupMask &= ~CONFIGSET_USER;
1044
- if( !g.okRdAddr ) groupMask &= ~CONFIGSET_ADDR;
1044
+ if( !g.perm.Admin ) groupMask &= ~CONFIGSET_USER;
1045
+ if( !g.perm.RdAddr ) groupMask &= ~CONFIGSET_ADDR;
10451046
configure_send_group(xfer.pOut, groupMask, 0);
10461047
}else if( configure_is_exportable(zName) ){
10471048
/* Old style configuration transfer */
10481049
send_legacy_config_card(&xfer, zName);
10491050
}
@@ -1059,11 +1060,11 @@
10591060
&& blob_is_int(&xfer.aToken[2], &size) ){
10601061
const char *zName = blob_str(&xfer.aToken[1]);
10611062
Blob content;
10621063
blob_zero(&content);
10631064
blob_extract(xfer.pIn, size, &content);
1064
- if( !g.okAdmin ){
1065
+ if( !g.perm.Admin ){
10651066
cgi_reset_content();
10661067
@ error not\sauthorized\sto\spush\sconfiguration
10671068
nErr++;
10681069
break;
10691070
}
@@ -1104,11 +1105,11 @@
11041105
**
11051106
** This card indicates that the next "file" or "cfile" will contain
11061107
** private content.
11071108
*/
11081109
if( blob_eq(&xfer.aToken[0], "private") ){
1109
- if( !g.okPrivate ){
1110
+ if( !g.perm.Private ){
11101111
server_private_xfer_not_authorized();
11111112
}else{
11121113
xfer.nextIsPrivate = 1;
11131114
}
11141115
}else
@@ -1127,11 +1128,11 @@
11271128
** it is not automatic with "a" or "s") then this pragma causes
11281129
** private information to be pulled in addition to public records.
11291130
*/
11301131
if( blob_eq(&xfer.aToken[1], "send-private") ){
11311132
login_check_credentials();
1132
- if( !g.okPrivate ){
1133
+ if( !g.perm.Private ){
11331134
server_private_xfer_not_authorized();
11341135
}else{
11351136
xfer.syncPrivate = 1;
11361137
}
11371138
}
@@ -1265,11 +1266,11 @@
12651266
memset(&xfer, 0, sizeof(xfer));
12661267
xfer.pIn = &recv;
12671268
xfer.pOut = &send;
12681269
xfer.mxSend = db_get_int("max-upload", 250000);
12691270
if( privateFlag ){
1270
- g.okPrivate = 1;
1271
+ g.perm.Private = 1;
12711272
xfer.syncPrivate = 1;
12721273
}
12731274
12741275
assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask );
12751276
db_begin_transaction();
@@ -1507,11 +1508,11 @@
15071508
int rid;
15081509
int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1");
15091510
rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
15101511
if( rid>0 ){
15111512
if( !isPriv ) content_make_public(rid);
1512
- }else if( isPriv && !g.okPrivate ){
1513
+ }else if( isPriv && !g.perm.Private ){
15131514
/* ignore private files */
15141515
}else if( pullFlag || cloneFlag ){
15151516
rid = content_new(blob_str(&xfer.aToken[1]), isPriv);
15161517
if( rid ) newPhantom = 1;
15171518
}
@@ -1552,11 +1553,11 @@
15521553
&& blob_is_int(&xfer.aToken[2], &size) ){
15531554
const char *zName = blob_str(&xfer.aToken[1]);
15541555
Blob content;
15551556
blob_zero(&content);
15561557
blob_extract(xfer.pIn, size, &content);
1557
- g.okAdmin = g.okRdAddr = 1;
1558
+ g.perm.Admin = g.perm.RdAddr = 1;
15581559
configure_receive(zName, &content, origConfigRcvMask);
15591560
nCardSent++;
15601561
blob_reset(&content);
15611562
blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
15621563
}else
15631564
--- src/xfer.c
+++ src/xfer.c
@@ -129,11 +129,11 @@
129 blob_extract(pXfer->pIn, n, &content);
130 if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
131 /* Ignore files that have been shunned */
132 return;
133 }
134 if( isPriv && !g.okPrivate ){
135 /* Do not accept private files if not authorized */
136 return;
137 }
138 if( cloneFlag ){
139 if( pXfer->nToken==4 ){
@@ -227,11 +227,11 @@
227 || (pXfer->nToken==5 && !blob_is_uuid(&pXfer->aToken[2]))
228 ){
229 blob_appendf(&pXfer->err, "malformed cfile line");
230 return;
231 }
232 if( isPriv && !g.okPrivate ){
233 /* Do not accept private files if not authorized */
234 return;
235 }
236 blob_zero(&content);
237 blob_extract(pXfer->pIn, szC, &content);
@@ -816,10 +816,11 @@
816 login_set_anon_nobody_capabilities();
817 login_check_credentials();
818 memset(&xfer, 0, sizeof(xfer));
819 blobarray_zero(xfer.aToken, count(xfer.aToken));
820 cgi_set_content_type(g.zContentType);
 
821 if( db_schema_is_outofdate() ){
822 @ error database\sschema\sis\sout-of-date\son\sthe\sserver.
823 return;
824 }
825 blob_zero(&xfer.err);
@@ -907,11 +908,11 @@
907 && blob_is_uuid(&xfer.aToken[1])
908 ){
909 if( isPush ){
910 if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){
911 rid_from_uuid(&xfer.aToken[1], 1, 0);
912 }else if( g.okPrivate ){
913 rid_from_uuid(&xfer.aToken[1], 1, 1);
914 }else{
915 server_private_xfer_not_authorized();
916 }
917 }
@@ -940,19 +941,19 @@
940 nErr++;
941 break;
942 }
943 login_check_credentials();
944 if( blob_eq(&xfer.aToken[0], "pull") ){
945 if( !g.okRead ){
946 cgi_reset_content();
947 @ error not\sauthorized\sto\sread
948 nErr++;
949 break;
950 }
951 isPull = 1;
952 }else{
953 if( !g.okWrite ){
954 if( !isPull ){
955 cgi_reset_content();
956 @ error not\sauthorized\sto\swrite
957 nErr++;
958 }else{
@@ -969,11 +970,11 @@
969 ** The client knows nothing. Tell all.
970 */
971 if( blob_eq(&xfer.aToken[0], "clone") ){
972 int iVers;
973 login_check_credentials();
974 if( !g.okClone ){
975 cgi_reset_content();
976 @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))
977 @ error not\sauthorized\sto\sclone
978 nErr++;
979 break;
@@ -1013,11 +1014,11 @@
1013 */
1014 if( blob_eq(&xfer.aToken[0], "login")
1015 && xfer.nToken==4
1016 ){
1017 if( disableLogin ){
1018 g.okRead = g.okWrite = g.okPrivate = g.okAdmin = 1;
1019 }else{
1020 if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
1021 || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
1022 ){
1023 cgi_reset_content();
@@ -1033,17 +1034,17 @@
1033 ** Request a configuration value
1034 */
1035 if( blob_eq(&xfer.aToken[0], "reqconfig")
1036 && xfer.nToken==2
1037 ){
1038 if( g.okRead ){
1039 char *zName = blob_str(&xfer.aToken[1]);
1040 if( zName[0]=='/' ){
1041 /* New style configuration transfer */
1042 int groupMask = configure_name_to_mask(&zName[1], 0);
1043 if( !g.okAdmin ) groupMask &= ~CONFIGSET_USER;
1044 if( !g.okRdAddr ) groupMask &= ~CONFIGSET_ADDR;
1045 configure_send_group(xfer.pOut, groupMask, 0);
1046 }else if( configure_is_exportable(zName) ){
1047 /* Old style configuration transfer */
1048 send_legacy_config_card(&xfer, zName);
1049 }
@@ -1059,11 +1060,11 @@
1059 && blob_is_int(&xfer.aToken[2], &size) ){
1060 const char *zName = blob_str(&xfer.aToken[1]);
1061 Blob content;
1062 blob_zero(&content);
1063 blob_extract(xfer.pIn, size, &content);
1064 if( !g.okAdmin ){
1065 cgi_reset_content();
1066 @ error not\sauthorized\sto\spush\sconfiguration
1067 nErr++;
1068 break;
1069 }
@@ -1104,11 +1105,11 @@
1104 **
1105 ** This card indicates that the next "file" or "cfile" will contain
1106 ** private content.
1107 */
1108 if( blob_eq(&xfer.aToken[0], "private") ){
1109 if( !g.okPrivate ){
1110 server_private_xfer_not_authorized();
1111 }else{
1112 xfer.nextIsPrivate = 1;
1113 }
1114 }else
@@ -1127,11 +1128,11 @@
1127 ** it is not automatic with "a" or "s") then this pragma causes
1128 ** private information to be pulled in addition to public records.
1129 */
1130 if( blob_eq(&xfer.aToken[1], "send-private") ){
1131 login_check_credentials();
1132 if( !g.okPrivate ){
1133 server_private_xfer_not_authorized();
1134 }else{
1135 xfer.syncPrivate = 1;
1136 }
1137 }
@@ -1265,11 +1266,11 @@
1265 memset(&xfer, 0, sizeof(xfer));
1266 xfer.pIn = &recv;
1267 xfer.pOut = &send;
1268 xfer.mxSend = db_get_int("max-upload", 250000);
1269 if( privateFlag ){
1270 g.okPrivate = 1;
1271 xfer.syncPrivate = 1;
1272 }
1273
1274 assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask );
1275 db_begin_transaction();
@@ -1507,11 +1508,11 @@
1507 int rid;
1508 int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1");
1509 rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
1510 if( rid>0 ){
1511 if( !isPriv ) content_make_public(rid);
1512 }else if( isPriv && !g.okPrivate ){
1513 /* ignore private files */
1514 }else if( pullFlag || cloneFlag ){
1515 rid = content_new(blob_str(&xfer.aToken[1]), isPriv);
1516 if( rid ) newPhantom = 1;
1517 }
@@ -1552,11 +1553,11 @@
1552 && blob_is_int(&xfer.aToken[2], &size) ){
1553 const char *zName = blob_str(&xfer.aToken[1]);
1554 Blob content;
1555 blob_zero(&content);
1556 blob_extract(xfer.pIn, size, &content);
1557 g.okAdmin = g.okRdAddr = 1;
1558 configure_receive(zName, &content, origConfigRcvMask);
1559 nCardSent++;
1560 blob_reset(&content);
1561 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1562 }else
1563
--- src/xfer.c
+++ src/xfer.c
@@ -129,11 +129,11 @@
129 blob_extract(pXfer->pIn, n, &content);
130 if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
131 /* Ignore files that have been shunned */
132 return;
133 }
134 if( isPriv && !g.perm.Private ){
135 /* Do not accept private files if not authorized */
136 return;
137 }
138 if( cloneFlag ){
139 if( pXfer->nToken==4 ){
@@ -227,11 +227,11 @@
227 || (pXfer->nToken==5 && !blob_is_uuid(&pXfer->aToken[2]))
228 ){
229 blob_appendf(&pXfer->err, "malformed cfile line");
230 return;
231 }
232 if( isPriv && !g.perm.Private ){
233 /* Do not accept private files if not authorized */
234 return;
235 }
236 blob_zero(&content);
237 blob_extract(pXfer->pIn, szC, &content);
@@ -816,10 +816,11 @@
816 login_set_anon_nobody_capabilities();
817 login_check_credentials();
818 memset(&xfer, 0, sizeof(xfer));
819 blobarray_zero(xfer.aToken, count(xfer.aToken));
820 cgi_set_content_type(g.zContentType);
821 cgi_reset_content();
822 if( db_schema_is_outofdate() ){
823 @ error database\sschema\sis\sout-of-date\son\sthe\sserver.
824 return;
825 }
826 blob_zero(&xfer.err);
@@ -907,11 +908,11 @@
908 && blob_is_uuid(&xfer.aToken[1])
909 ){
910 if( isPush ){
911 if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){
912 rid_from_uuid(&xfer.aToken[1], 1, 0);
913 }else if( g.perm.Private ){
914 rid_from_uuid(&xfer.aToken[1], 1, 1);
915 }else{
916 server_private_xfer_not_authorized();
917 }
918 }
@@ -940,19 +941,19 @@
941 nErr++;
942 break;
943 }
944 login_check_credentials();
945 if( blob_eq(&xfer.aToken[0], "pull") ){
946 if( !g.perm.Read ){
947 cgi_reset_content();
948 @ error not\sauthorized\sto\sread
949 nErr++;
950 break;
951 }
952 isPull = 1;
953 }else{
954 if( !g.perm.Write ){
955 if( !isPull ){
956 cgi_reset_content();
957 @ error not\sauthorized\sto\swrite
958 nErr++;
959 }else{
@@ -969,11 +970,11 @@
970 ** The client knows nothing. Tell all.
971 */
972 if( blob_eq(&xfer.aToken[0], "clone") ){
973 int iVers;
974 login_check_credentials();
975 if( !g.perm.Clone ){
976 cgi_reset_content();
977 @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))
978 @ error not\sauthorized\sto\sclone
979 nErr++;
980 break;
@@ -1013,11 +1014,11 @@
1014 */
1015 if( blob_eq(&xfer.aToken[0], "login")
1016 && xfer.nToken==4
1017 ){
1018 if( disableLogin ){
1019 g.perm.Read = g.perm.Write = g.perm.Private = g.perm.Admin = 1;
1020 }else{
1021 if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
1022 || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
1023 ){
1024 cgi_reset_content();
@@ -1033,17 +1034,17 @@
1034 ** Request a configuration value
1035 */
1036 if( blob_eq(&xfer.aToken[0], "reqconfig")
1037 && xfer.nToken==2
1038 ){
1039 if( g.perm.Read ){
1040 char *zName = blob_str(&xfer.aToken[1]);
1041 if( zName[0]=='/' ){
1042 /* New style configuration transfer */
1043 int groupMask = configure_name_to_mask(&zName[1], 0);
1044 if( !g.perm.Admin ) groupMask &= ~CONFIGSET_USER;
1045 if( !g.perm.RdAddr ) groupMask &= ~CONFIGSET_ADDR;
1046 configure_send_group(xfer.pOut, groupMask, 0);
1047 }else if( configure_is_exportable(zName) ){
1048 /* Old style configuration transfer */
1049 send_legacy_config_card(&xfer, zName);
1050 }
@@ -1059,11 +1060,11 @@
1060 && blob_is_int(&xfer.aToken[2], &size) ){
1061 const char *zName = blob_str(&xfer.aToken[1]);
1062 Blob content;
1063 blob_zero(&content);
1064 blob_extract(xfer.pIn, size, &content);
1065 if( !g.perm.Admin ){
1066 cgi_reset_content();
1067 @ error not\sauthorized\sto\spush\sconfiguration
1068 nErr++;
1069 break;
1070 }
@@ -1104,11 +1105,11 @@
1105 **
1106 ** This card indicates that the next "file" or "cfile" will contain
1107 ** private content.
1108 */
1109 if( blob_eq(&xfer.aToken[0], "private") ){
1110 if( !g.perm.Private ){
1111 server_private_xfer_not_authorized();
1112 }else{
1113 xfer.nextIsPrivate = 1;
1114 }
1115 }else
@@ -1127,11 +1128,11 @@
1128 ** it is not automatic with "a" or "s") then this pragma causes
1129 ** private information to be pulled in addition to public records.
1130 */
1131 if( blob_eq(&xfer.aToken[1], "send-private") ){
1132 login_check_credentials();
1133 if( !g.perm.Private ){
1134 server_private_xfer_not_authorized();
1135 }else{
1136 xfer.syncPrivate = 1;
1137 }
1138 }
@@ -1265,11 +1266,11 @@
1266 memset(&xfer, 0, sizeof(xfer));
1267 xfer.pIn = &recv;
1268 xfer.pOut = &send;
1269 xfer.mxSend = db_get_int("max-upload", 250000);
1270 if( privateFlag ){
1271 g.perm.Private = 1;
1272 xfer.syncPrivate = 1;
1273 }
1274
1275 assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask );
1276 db_begin_transaction();
@@ -1507,11 +1508,11 @@
1508 int rid;
1509 int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1");
1510 rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
1511 if( rid>0 ){
1512 if( !isPriv ) content_make_public(rid);
1513 }else if( isPriv && !g.perm.Private ){
1514 /* ignore private files */
1515 }else if( pullFlag || cloneFlag ){
1516 rid = content_new(blob_str(&xfer.aToken[1]), isPriv);
1517 if( rid ) newPhantom = 1;
1518 }
@@ -1552,11 +1553,11 @@
1553 && blob_is_int(&xfer.aToken[2], &size) ){
1554 const char *zName = blob_str(&xfer.aToken[1]);
1555 Blob content;
1556 blob_zero(&content);
1557 blob_extract(xfer.pIn, size, &content);
1558 g.perm.Admin = g.perm.RdAddr = 1;
1559 configure_receive(zName, &content, origConfigRcvMask);
1560 nCardSent++;
1561 blob_reset(&content);
1562 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1563 }else
1564
+2 -2
--- src/zip.c
+++ src/zip.c
@@ -291,11 +291,11 @@
291291
}
292292
zip_open();
293293
for(i=3; i<g.argc; i++){
294294
blob_zero(&file);
295295
blob_read_from_file(&file, g.argv[i]);
296
- zip_add_file(g.argv[i], &file, file_perm(g.argv[i]));
296
+ zip_add_file(g.argv[i], &file, file_wd_perm(g.argv[i]));
297297
blob_reset(&file);
298298
}
299299
zip_close(&zip);
300300
blob_write_to_file(&zip, g.argv[2]);
301301
}
@@ -426,11 +426,11 @@
426426
char *zName, *zRid;
427427
int nName, nRid;
428428
Blob zip;
429429
430430
login_check_credentials();
431
- if( !g.okZip ){ login_needed(); return; }
431
+ if( !g.perm.Zip ){ login_needed(); return; }
432432
zName = mprintf("%s", PD("name",""));
433433
nName = strlen(zName);
434434
zRid = mprintf("%s", PD("uuid",""));
435435
nRid = strlen(zRid);
436436
for(nName=strlen(zName)-1; nName>5; nName--){
437437
--- src/zip.c
+++ src/zip.c
@@ -291,11 +291,11 @@
291 }
292 zip_open();
293 for(i=3; i<g.argc; i++){
294 blob_zero(&file);
295 blob_read_from_file(&file, g.argv[i]);
296 zip_add_file(g.argv[i], &file, file_perm(g.argv[i]));
297 blob_reset(&file);
298 }
299 zip_close(&zip);
300 blob_write_to_file(&zip, g.argv[2]);
301 }
@@ -426,11 +426,11 @@
426 char *zName, *zRid;
427 int nName, nRid;
428 Blob zip;
429
430 login_check_credentials();
431 if( !g.okZip ){ login_needed(); return; }
432 zName = mprintf("%s", PD("name",""));
433 nName = strlen(zName);
434 zRid = mprintf("%s", PD("uuid",""));
435 nRid = strlen(zRid);
436 for(nName=strlen(zName)-1; nName>5; nName--){
437
--- src/zip.c
+++ src/zip.c
@@ -291,11 +291,11 @@
291 }
292 zip_open();
293 for(i=3; i<g.argc; i++){
294 blob_zero(&file);
295 blob_read_from_file(&file, g.argv[i]);
296 zip_add_file(g.argv[i], &file, file_wd_perm(g.argv[i]));
297 blob_reset(&file);
298 }
299 zip_close(&zip);
300 blob_write_to_file(&zip, g.argv[2]);
301 }
@@ -426,11 +426,11 @@
426 char *zName, *zRid;
427 int nName, nRid;
428 Blob zip;
429
430 login_check_credentials();
431 if( !g.perm.Zip ){ login_needed(); return; }
432 zName = mprintf("%s", PD("name",""));
433 nName = strlen(zName);
434 zRid = mprintf("%s", PD("uuid",""));
435 nRid = strlen(zRid);
436 for(nName=strlen(zName)-1; nName>5; nName--){
437
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -13,10 +13,16 @@
1313
<li><p>
1414
Click on each of the links in in the
1515
[./graph-test-1.wiki] document and verify that all graphs are
1616
rendered correctly.
1717
18
+<li><p>
19
+Verify correct name-change tracking behavior (no net changes) for:
20
+<blockquote><b>
21
+fossil test-name-changes --debug b120bc8b262ac 374920b20944b
22
+</b></blockquote>
23
+
1824
<li><p>
1925
Compile for all of the following platforms:
2026
<ol type="a">
2127
<li> Linux x86
2228
<li> Linux x86_64
2329
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -13,10 +13,16 @@
13 <li><p>
14 Click on each of the links in in the
15 [./graph-test-1.wiki] document and verify that all graphs are
16 rendered correctly.
17
 
 
 
 
 
 
18 <li><p>
19 Compile for all of the following platforms:
20 <ol type="a">
21 <li> Linux x86
22 <li> Linux x86_64
23
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -13,10 +13,16 @@
13 <li><p>
14 Click on each of the links in in the
15 [./graph-test-1.wiki] document and verify that all graphs are
16 rendered correctly.
17
18 <li><p>
19 Verify correct name-change tracking behavior (no net changes) for:
20 <blockquote><b>
21 fossil test-name-changes --debug b120bc8b262ac 374920b20944b
22 </b></blockquote>
23
24 <li><p>
25 Compile for all of the following platforms:
26 <ol type="a">
27 <li> Linux x86
28 <li> Linux x86_64
29
+5 -7
--- www/build.wiki
+++ www/build.wiki
@@ -28,23 +28,22 @@
2828
<p>Fossil is self-hosting, so you can obtain a ZIP archive containing
2929
a snapshot of the latest version directly from fossil's own fossil
3030
repository. Follow these steps:</p>
3131
3232
<ol>
33
-<li><p>Pointer your web browser at
33
+<li><p>Point your web browser at
3434
<a href="http://www.fossil-scm.org/">
3535
http://www.fossil-scm.org/</a>. Click on the "Login" menu button.</p></li>
3636
3737
<li><p>Log in as anonymous. The password is shown on screen.
3838
The reason for requiring this login is to prevent spiders from
3939
walking the entire website, downloading ZIP archives
4040
of every historical version, and thereby soaking up all our bandwidth.</p></li>
4141
4242
<li><p>Click on the
43
-<a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> or
44
-<a href="http://www.fossil-scm.org/fossil/leaves">Leaves</a> link at
45
-the top of the page.</p></li>
43
+<a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a>
44
+link at the top of the page.</p></li>
4645
4746
<li><p>Select a version of of fossil you want to download. Click on its
4847
link. Note that you must successfully log in as "anonymous" in step 1
4948
above in order to see the link to the detailed version information.</p></li>
5049
@@ -56,13 +55,12 @@
5655
5756
<h2>2.0 Compiling</h2>
5857
5958
<ol>
6059
<li value="6">
61
-<p>Create a directory to hold the source code. Then unarchive the
62
-ZIP or tarball you downloaded into that directory. You should be
63
-in the top-level folder of that directory</p></li>
60
+<p>Unpack the ZIP or tarball you downloaded into that directory then
61
+<b>cd</b> into the directory created.</p></li>
6462
6563
<li><i>(Optional, unix only)</i>
6664
Run <b>./configure</b> to construct a makefile.
6765
6866
<ol type="a">
6967
--- www/build.wiki
+++ www/build.wiki
@@ -28,23 +28,22 @@
28 <p>Fossil is self-hosting, so you can obtain a ZIP archive containing
29 a snapshot of the latest version directly from fossil's own fossil
30 repository. Follow these steps:</p>
31
32 <ol>
33 <li><p>Pointer your web browser at
34 <a href="http://www.fossil-scm.org/">
35 http://www.fossil-scm.org/</a>. Click on the "Login" menu button.</p></li>
36
37 <li><p>Log in as anonymous. The password is shown on screen.
38 The reason for requiring this login is to prevent spiders from
39 walking the entire website, downloading ZIP archives
40 of every historical version, and thereby soaking up all our bandwidth.</p></li>
41
42 <li><p>Click on the
43 <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> or
44 <a href="http://www.fossil-scm.org/fossil/leaves">Leaves</a> link at
45 the top of the page.</p></li>
46
47 <li><p>Select a version of of fossil you want to download. Click on its
48 link. Note that you must successfully log in as "anonymous" in step 1
49 above in order to see the link to the detailed version information.</p></li>
50
@@ -56,13 +55,12 @@
56
57 <h2>2.0 Compiling</h2>
58
59 <ol>
60 <li value="6">
61 <p>Create a directory to hold the source code. Then unarchive the
62 ZIP or tarball you downloaded into that directory. You should be
63 in the top-level folder of that directory</p></li>
64
65 <li><i>(Optional, unix only)</i>
66 Run <b>./configure</b> to construct a makefile.
67
68 <ol type="a">
69
--- www/build.wiki
+++ www/build.wiki
@@ -28,23 +28,22 @@
28 <p>Fossil is self-hosting, so you can obtain a ZIP archive containing
29 a snapshot of the latest version directly from fossil's own fossil
30 repository. Follow these steps:</p>
31
32 <ol>
33 <li><p>Point your web browser at
34 <a href="http://www.fossil-scm.org/">
35 http://www.fossil-scm.org/</a>. Click on the "Login" menu button.</p></li>
36
37 <li><p>Log in as anonymous. The password is shown on screen.
38 The reason for requiring this login is to prevent spiders from
39 walking the entire website, downloading ZIP archives
40 of every historical version, and thereby soaking up all our bandwidth.</p></li>
41
42 <li><p>Click on the
43 <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a>
44 link at the top of the page.</p></li>
 
45
46 <li><p>Select a version of of fossil you want to download. Click on its
47 link. Note that you must successfully log in as "anonymous" in step 1
48 above in order to see the link to the detailed version information.</p></li>
49
@@ -56,13 +55,12 @@
55
56 <h2>2.0 Compiling</h2>
57
58 <ol>
59 <li value="6">
60 <p>Unpack the ZIP or tarball you downloaded into that directory then
61 <b>cd</b> into the directory created.</p></li>
 
62
63 <li><i>(Optional, unix only)</i>
64 Run <b>./configure</b> to construct a makefile.
65
66 <ol type="a">
67
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -21,10 +21,20 @@
2121
repository.</nowiki>
2222
2323
<blockquote>
2424
<i>At [http://tartley.com/?p=1267]</i>
2525
</blockquote>
26
+
27
+<li>Git is not a Prius. Git is a Model T.
28
+Its plumbing and wiring sticks out all over the place.
29
+You have to be a mechanic to operate it successfully or you'll be
30
+stuck on the side of the road when it breaks down.
31
+And it <b>will</b> break down.
32
+
33
+<blockquote>
34
+<i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i>
35
+</blockquote>
2636
2737
<li>We've been using git and github for a few months now, and it's not
2838
intuitive... I'm hoping someone will make a set of standard wrappers/GUI
2939
for making git bearable.
3040
3141
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -21,10 +21,20 @@
21 repository.</nowiki>
22
23 <blockquote>
24 <i>At [http://tartley.com/?p=1267]</i>
25 </blockquote>
 
 
 
 
 
 
 
 
 
 
26
27 <li>We've been using git and github for a few months now, and it's not
28 intuitive... I'm hoping someone will make a set of standard wrappers/GUI
29 for making git bearable.
30
31
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -21,10 +21,20 @@
21 repository.</nowiki>
22
23 <blockquote>
24 <i>At [http://tartley.com/?p=1267]</i>
25 </blockquote>
26
27 <li>Git is not a Prius. Git is a Model T.
28 Its plumbing and wiring sticks out all over the place.
29 You have to be a mechanic to operate it successfully or you'll be
30 stuck on the side of the road when it breaks down.
31 And it <b>will</b> break down.
32
33 <blockquote>
34 <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i>
35 </blockquote>
36
37 <li>We've been using git and github for a few months now, and it's not
38 intuitive... I'm hoping someone will make a set of standard wrappers/GUI
39 for making git bearable.
40
41
--- www/reference.wiki
+++ www/reference.wiki
@@ -94,11 +94,11 @@
9494
<tr>
9595
<td><a href="#checkout">checkout</a>*</td>
9696
<td><a href="#descendants">descendants</a></td>
9797
<td><a href="#mv">mv</a>*</td>
9898
<td><a href="#rm">rm</a>*</td>
99
- <td><a href="#setting">unset</a></td>
99
+ <td><a href="#settings">unset</a></td>
100100
</tr>
101101
<tr>
102102
<td><a href="#commit">ci</a></td>
103103
<td><a href="#diff">diff</a></td>
104104
<td><a href="#new">new</a>*</td>
@@ -114,11 +114,11 @@
114114
</tr>
115115
<tr>
116116
<td><a href="#clone">clone</a></td>
117117
<td><a href="#diff">gdiff</a></td>
118118
<td><a href="#pull">pull</a></td>
119
- <td><a href="#setting">settings</a></td>
119
+ <td><a href="#settings">settings</a></td>
120120
<td><a href="#version">version</a>*</td>
121121
</tr>
122122
<tr>
123123
<td><a href="#close">close</a></td>
124124
<td><a href="#help">help</a></td>
125125
--- www/reference.wiki
+++ www/reference.wiki
@@ -94,11 +94,11 @@
94 <tr>
95 <td><a href="#checkout">checkout</a>*</td>
96 <td><a href="#descendants">descendants</a></td>
97 <td><a href="#mv">mv</a>*</td>
98 <td><a href="#rm">rm</a>*</td>
99 <td><a href="#setting">unset</a></td>
100 </tr>
101 <tr>
102 <td><a href="#commit">ci</a></td>
103 <td><a href="#diff">diff</a></td>
104 <td><a href="#new">new</a>*</td>
@@ -114,11 +114,11 @@
114 </tr>
115 <tr>
116 <td><a href="#clone">clone</a></td>
117 <td><a href="#diff">gdiff</a></td>
118 <td><a href="#pull">pull</a></td>
119 <td><a href="#setting">settings</a></td>
120 <td><a href="#version">version</a>*</td>
121 </tr>
122 <tr>
123 <td><a href="#close">close</a></td>
124 <td><a href="#help">help</a></td>
125
--- www/reference.wiki
+++ www/reference.wiki
@@ -94,11 +94,11 @@
94 <tr>
95 <td><a href="#checkout">checkout</a>*</td>
96 <td><a href="#descendants">descendants</a></td>
97 <td><a href="#mv">mv</a>*</td>
98 <td><a href="#rm">rm</a>*</td>
99 <td><a href="#settings">unset</a></td>
100 </tr>
101 <tr>
102 <td><a href="#commit">ci</a></td>
103 <td><a href="#diff">diff</a></td>
104 <td><a href="#new">new</a>*</td>
@@ -114,11 +114,11 @@
114 </tr>
115 <tr>
116 <td><a href="#clone">clone</a></td>
117 <td><a href="#diff">gdiff</a></td>
118 <td><a href="#pull">pull</a></td>
119 <td><a href="#settings">settings</a></td>
120 <td><a href="#version">version</a>*</td>
121 </tr>
122 <tr>
123 <td><a href="#close">close</a></td>
124 <td><a href="#help">help</a></td>
125
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -8,10 +8,11 @@
88
by Juho Veps&#228;l&#228;inen.
99
* [http://blog.fupps.com/2010/12/04/exploring-the-fossil-dvcs |
1010
Exploring the Fossil DVCS] by Jan-Piet Mens.
1111
* [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html |
1212
Fossil - a sweet spot in the VCS space] by Mike Meyer.
13
+ * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal
1314
1415
<b>See Also:</b>
1516
1617
* [./quotes.wiki | Short Quotes on Fossil, Git, And DVCSes]
1718
@@ -39,11 +40,11 @@
3940
life easier on most of my projects, and being able to move commits to
4041
another branch after the fact and shared-by-default branches are good
4142
features. Also not having a misanthropic command line interface.
4243
</blockquote>
4344
44
-<b>Stephen Beal writes on 2009-01-11:</b>
45
+<b>Stephan Beal writes on 2009-01-11:</b>
4546
4647
<blockquote>
4748
Sometime in late 2007 I came across a link to fossil on
4849
<a href="http://www.sqlite.org/">sqlite.org</a>. It
4950
was a good thing I bookmarked it, because I was never able to find the
@@ -136,12 +137,12 @@
136137
137138
138139
In summary:
139140
140141
I remember my first reaction to fossil being, "this will be an
141
-excellent solution for small projects [like the dozens we've all got
142
+excellent solution for small projects (like the dozens we've all got
142143
sitting on our hard drives but which don't justify the hassle of
143
-version control]." A year of daily use in over 15 source trees has
144
+version control)." A year of daily use in over 15 source trees has
144145
confirmed that, and I continue to heartily recommend fossil to other
145146
developers I know who also have their own collection of "unhosted" pet
146147
projects.
147148
</blockquote>
148149
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -8,10 +8,11 @@
8 by Juho Veps&#228;l&#228;inen.
9 * [http://blog.fupps.com/2010/12/04/exploring-the-fossil-dvcs |
10 Exploring the Fossil DVCS] by Jan-Piet Mens.
11 * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html |
12 Fossil - a sweet spot in the VCS space] by Mike Meyer.
 
13
14 <b>See Also:</b>
15
16 * [./quotes.wiki | Short Quotes on Fossil, Git, And DVCSes]
17
@@ -39,11 +40,11 @@
39 life easier on most of my projects, and being able to move commits to
40 another branch after the fact and shared-by-default branches are good
41 features. Also not having a misanthropic command line interface.
42 </blockquote>
43
44 <b>Stephen Beal writes on 2009-01-11:</b>
45
46 <blockquote>
47 Sometime in late 2007 I came across a link to fossil on
48 <a href="http://www.sqlite.org/">sqlite.org</a>. It
49 was a good thing I bookmarked it, because I was never able to find the
@@ -136,12 +137,12 @@
136
137
138 In summary:
139
140 I remember my first reaction to fossil being, "this will be an
141 excellent solution for small projects [like the dozens we've all got
142 sitting on our hard drives but which don't justify the hassle of
143 version control]." A year of daily use in over 15 source trees has
144 confirmed that, and I continue to heartily recommend fossil to other
145 developers I know who also have their own collection of "unhosted" pet
146 projects.
147 </blockquote>
148
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -8,10 +8,11 @@
8 by Juho Veps&#228;l&#228;inen.
9 * [http://blog.fupps.com/2010/12/04/exploring-the-fossil-dvcs |
10 Exploring the Fossil DVCS] by Jan-Piet Mens.
11 * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html |
12 Fossil - a sweet spot in the VCS space] by Mike Meyer.
13 * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal
14
15 <b>See Also:</b>
16
17 * [./quotes.wiki | Short Quotes on Fossil, Git, And DVCSes]
18
@@ -39,11 +40,11 @@
40 life easier on most of my projects, and being able to move commits to
41 another branch after the fact and shared-by-default branches are good
42 features. Also not having a misanthropic command line interface.
43 </blockquote>
44
45 <b>Stephan Beal writes on 2009-01-11:</b>
46
47 <blockquote>
48 Sometime in late 2007 I came across a link to fossil on
49 <a href="http://www.sqlite.org/">sqlite.org</a>. It
50 was a good thing I bookmarked it, because I was never able to find the
@@ -136,12 +137,12 @@
137
138
139 In summary:
140
141 I remember my first reaction to fossil being, "this will be an
142 excellent solution for small projects (like the dozens we've all got
143 sitting on our hard drives but which don't justify the hassle of
144 version control)." A year of daily use in over 15 source trees has
145 confirmed that, and I continue to heartily recommend fossil to other
146 developers I know who also have their own collection of "unhosted" pet
147 projects.
148 </blockquote>
149
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -59,11 +59,11 @@
5959
Files in the source tree that use the ".wiki" suffix can be accessed
6060
and displayed using special URLs to the fossil server. This allows
6161
project documentation to be stored in the source tree and accessed
6262
online. (Details are described [./embeddeddoc.wiki | separately].)
6363
64
-Some project prefer to store their documentation in wiki. There is nothing
64
+Some projects prefer to store their documentation in wiki. There is nothing
6565
wrong with that. But other projects prefer to keep documentation as part
6666
of the source tree, so that it is versioned along with the source tree and
6767
so that only developers with check-in privileges can change it.
6868
Embedded documentation serves this latter purpose. Both forms of documentation
6969
use the exact same wiki markup language. Some projects may choose to
7070
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -59,11 +59,11 @@
59 Files in the source tree that use the ".wiki" suffix can be accessed
60 and displayed using special URLs to the fossil server. This allows
61 project documentation to be stored in the source tree and accessed
62 online. (Details are described [./embeddeddoc.wiki | separately].)
63
64 Some project prefer to store their documentation in wiki. There is nothing
65 wrong with that. But other projects prefer to keep documentation as part
66 of the source tree, so that it is versioned along with the source tree and
67 so that only developers with check-in privileges can change it.
68 Embedded documentation serves this latter purpose. Both forms of documentation
69 use the exact same wiki markup language. Some projects may choose to
70
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -59,11 +59,11 @@
59 Files in the source tree that use the ".wiki" suffix can be accessed
60 and displayed using special URLs to the fossil server. This allows
61 project documentation to be stored in the source tree and accessed
62 online. (Details are described [./embeddeddoc.wiki | separately].)
63
64 Some projects prefer to store their documentation in wiki. There is nothing
65 wrong with that. But other projects prefer to keep documentation as part
66 of the source tree, so that it is versioned along with the source tree and
67 so that only developers with check-in privileges can change it.
68 Embedded documentation serves this latter purpose. Both forms of documentation
69 use the exact same wiki markup language. Some projects may choose to
70

Keyboard Shortcuts

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