Fossil SCM
merge trunk
Commit
bec0c4f04488b7993b641a68ef6ee5903071369ff2e9750332f7fc7e0f4f8f6b
Parent
28173845f9907dc…
97 files changed
+1
-1
-209
-630
-972
-687
-103
+1
-1
+9
-5
+4
-4
+11
-16
+2
+12
-10
+3
-6
+1
+6
+1
+22
-12
+29
-34
+1
-1
+22
-8
+12
-4
+90
+1
-1
+1
-1
+2
-2
+1
-1
+1
-1
+11
+5
-6
+3
-3
+7
-5
+97
+13
-2
+36
+6
-1
+3
+3
+80
-80
+15
-1
+6
-5
+24
-28
+2
-2
+7
-13
+106
-94
+2
-2
+8
+79
-11
+2
+1415
-233
+14
-13
+1
-2
+5
-2
+1515
-987
+36
-16
+35
-32
+71
-4
+1
-1
+2
-6
+2
-2
+58
-1
+6
-8
+19
-30
+2
-2
+1
-1
+96
-66
+2
-5
+4
-4
+12
-6
+1
-1
+22
-4
+36
+36
+36
+36
+30
+30
+3
-3
+7
-12
+7
-12
+20
-2
+4
-4
+1
-1
+79
-84
+4
-3
+20
+2
-2
+1
+6
+7
-6
+10
-9
+1
-1
+14
-14
+5
-4
+2
-1
+1
-1
+4
-3
~
VERSION
-
compat/zlib/doc/algorithm.txt
-
compat/zlib/doc/rfc1950.txt
-
compat/zlib/doc/rfc1951.txt
-
compat/zlib/doc/rfc1952.txt
-
compat/zlib/doc/txtvsbin.txt
~
src/attach.c
~
src/blob.c
~
src/browse.c
~
src/bundle.c
~
src/cgi.c
~
src/checkin.c
~
src/checkout.c
~
src/clone.c
~
src/config.h
~
src/configure.c
~
src/content.c
~
src/db.c
~
src/diff.c
~
src/diffcmd.c
~
src/doc.c
~
src/encode.c
~
src/event.c
~
src/export.c
~
src/foci.c
~
src/fusefs.c
~
src/graph.c
~
src/hname.c
~
src/http_ssl.c
~
src/import.c
~
src/info.c
~
src/login.c
~
src/main.c
~
src/main.mk
~
src/makeheaders.c
~
src/makemake.tcl
~
src/makemake.tcl
~
src/manifest.c
~
src/md5.c
~
src/mkversion.c
~
src/name.c
~
src/printf.c
~
src/purge.c
~
src/rebuild.c
~
src/schema.c
~
src/setup.c
~
src/sha1.c
~
src/sha1hard.c
~
src/sha3.c
~
src/shell.c
~
src/shun.c
~
src/sitemap.c
~
src/sqlcmd.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stash.c
~
src/stat.c
~
src/tag.c
~
src/tar.c
~
src/timeline.c
~
src/unversioned.c
~
src/verify.c
~
src/vfile.c
~
src/wiki.c
~
src/wikiformat.c
~
src/xfer.c
~
src/zip.c
~
test/json.test
~
test/wiki.test
~
tools/man_page_command_list.tcl
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
win/Makefile.msc
~
www/branching.wiki
~
www/build.wiki
~
www/build.wiki
~
www/changes.wiki
~
www/checkin_names.wiki
~
www/customskin.md
~
www/fileformat.wiki
~
www/fossil-v-git.wiki
~
www/hashpolicy.wiki
~
www/mkdownload.tcl
~
www/mkindex.tcl
~
www/permutedindex.html
~
www/pop.wiki
~
www/selfcheck.wiki
~
www/shunning.wiki
~
www/sync.wiki
~
www/tech_overview.wiki
~
www/theory1.wiki
~
www/webpage-ex.md
~
www/whyusefossil.wiki
M
VERSION
+1
-1
| --- VERSION | ||
| +++ VERSION | ||
| @@ -1,1 +1,1 @@ | ||
| 1 | -1.37 | |
| 1 | +2.1 | |
| 2 | 2 | |
| 3 | 3 | DELETED compat/zlib/doc/algorithm.txt |
| 4 | 4 | DELETED compat/zlib/doc/rfc1950.txt |
| 5 | 5 | DELETED compat/zlib/doc/rfc1951.txt |
| 6 | 6 | DELETED compat/zlib/doc/rfc1952.txt |
| 7 | 7 | DELETED compat/zlib/doc/txtvsbin.txt |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.37 |
| 2 | |
| 3 | ELETED compat/zlib/doc/algorithm.txt |
| 4 | ELETED compat/zlib/doc/rfc1950.txt |
| 5 | ELETED compat/zlib/doc/rfc1951.txt |
| 6 | ELETED compat/zlib/doc/rfc1952.txt |
| 7 | ELETED compat/zlib/doc/txtvsbin.txt |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 2.1 |
| 2 | |
| 3 | ELETED compat/zlib/doc/algorithm.txt |
| 4 | ELETED compat/zlib/doc/rfc1950.txt |
| 5 | ELETED compat/zlib/doc/rfc1951.txt |
| 6 | ELETED compat/zlib/doc/rfc1952.txt |
| 7 | ELETED compat/zlib/doc/txtvsbin.txt |
D
compat/zlib/doc/algorithm.txt
-209
| --- a/compat/zlib/doc/algorithm.txt | ||
| +++ b/compat/zlib/doc/algorithm.txt | ||
| @@ -1,209 +0,0 @@ | ||
| 1 | -1. Compression algorithm (deflate) | |
| 2 | - | |
| 3 | -The deflation algorithm used by gzip (also zip and zlib) is a variation of | |
| 4 | -LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in | |
| 5 | -the input data. The second occurrence of a string is replaced by a | |
| 6 | -pointer to the previous string, in the form of a pair (distance, | |
| 7 | -length). Distances are limited to 32K bytes, and lengths are limited | |
| 8 | -to 258 bytes. When a string does not occur anywhere in the previous | |
| 9 | -32K bytes, it is emitted as a sequence of literal bytes. (In this | |
| 10 | -description, `string' must be taken as an arbitrary sequence of bytes, | |
| 11 | -and is not restricted to printable characters.) | |
| 12 | - | |
| 13 | -Literals or match lengths are compressed with one Huffman tree, and | |
| 14 | -match distances are compressed with another tree. The trees are stored | |
| 15 | -in a compact form at the start of each block. The blocks can have any | |
| 16 | -size (except that the compressed data for one block must fit in | |
| 17 | -available memory). A block is terminated when deflate() determines that | |
| 18 | -it would be useful to start another block with fresh trees. (This is | |
| 19 | -somewhat similar to the behavior of LZW-based _compress_.) | |
| 20 | - | |
| 21 | -Duplicated strings are found using a hash table. All input strings of | |
| 22 | -length 3 are inserted in the hash table. A hash index is computed for | |
| 23 | -the next 3 bytes. If the hash chain for this index is not empty, all | |
| 24 | -strings in the chain are compared with the current input string, and | |
| 25 | -the longest match is selected. | |
| 26 | - | |
| 27 | -The hash chains are searched starting with the most recent strings, to | |
| 28 | -favor small distances and thus take advantage of the Huffman encoding. | |
| 29 | -The hash chains are singly linked. There are no deletions from the | |
| 30 | -hash chains, the algorithm simply discards matches that are too old. | |
| 31 | - | |
| 32 | -To avoid a worst-case situation, very long hash chains are arbitrarily | |
| 33 | -truncated at a certain length, determined by a runtime option (level | |
| 34 | -parameter of deflateInit). So deflate() does not always find the longest | |
| 35 | -possible match but generally finds a match which is long enough. | |
| 36 | - | |
| 37 | -deflate() also defers the selection of matches with a lazy evaluation | |
| 38 | -mechanism. After a match of length N has been found, deflate() searches for | |
| 39 | -a longer match at the next input byte. If a longer match is found, the | |
| 40 | -previous match is truncated to a length of one (thus producing a single | |
| 41 | -literal byte) and the process of lazy evaluation begins again. Otherwise, | |
| 42 | -the original match is kept, and the next match search is attempted only N | |
| 43 | -steps later. | |
| 44 | - | |
| 45 | -The lazy match evaluation is also subject to a runtime parameter. If | |
| 46 | -the current match is long enough, deflate() reduces the search for a longer | |
| 47 | -match, thus speeding up the whole process. If compression ratio is more | |
| 48 | -important than speed, deflate() attempts a complete second search even if | |
| 49 | -the first match is already long enough. | |
| 50 | - | |
| 51 | -The lazy match evaluation is not performed for the fastest compression | |
| 52 | -modes (level parameter 1 to 3). For these fast modes, new strings | |
| 53 | -are inserted in the hash table only when no match was found, or | |
| 54 | -when the match is not too long. This degrades the compression ratio | |
| 55 | -but saves time since there are both fewer insertions and fewer searches. | |
| 56 | - | |
| 57 | - | |
| 58 | -2. Decompression algorithm (inflate) | |
| 59 | - | |
| 60 | -2.1 Introduction | |
| 61 | - | |
| 62 | -The key question is how to represent a Huffman code (or any prefix code) so | |
| 63 | -that you can decode fast. The most important characteristic is that shorter | |
| 64 | -codes are much more common than longer codes, so pay attention to decoding the | |
| 65 | -short codes fast, and let the long codes take longer to decode. | |
| 66 | - | |
| 67 | -inflate() sets up a first level table that covers some number of bits of | |
| 68 | -input less than the length of longest code. It gets that many bits from the | |
| 69 | -stream, and looks it up in the table. The table will tell if the next | |
| 70 | -code is that many bits or less and how many, and if it is, it will tell | |
| 71 | -the value, else it will point to the next level table for which inflate() | |
| 72 | -grabs more bits and tries to decode a longer code. | |
| 73 | - | |
| 74 | -How many bits to make the first lookup is a tradeoff between the time it | |
| 75 | -takes to decode and the time it takes to build the table. If building the | |
| 76 | -table took no time (and if you had infinite memory), then there would only | |
| 77 | -be a first level table to cover all the way to the longest code. However, | |
| 78 | -building the table ends up taking a lot longer for more bits since short | |
| 79 | -codes are replicated many times in such a table. What inflate() does is | |
| 80 | -simply to make the number of bits in the first table a variable, and then | |
| 81 | -to set that variable for the maximum speed. | |
| 82 | - | |
| 83 | -For inflate, which has 286 possible codes for the literal/length tree, the size | |
| 84 | -of the first table is nine bits. Also the distance trees have 30 possible | |
| 85 | -values, and the size of the first table is six bits. Note that for each of | |
| 86 | -those cases, the table ended up one bit longer than the ``average'' code | |
| 87 | -length, i.e. the code length of an approximately flat code which would be a | |
| 88 | -little more than eight bits for 286 symbols and a little less than five bits | |
| 89 | -for 30 symbols. | |
| 90 | - | |
| 91 | - | |
| 92 | -2.2 More details on the inflate table lookup | |
| 93 | - | |
| 94 | -Ok, you want to know what this cleverly obfuscated inflate tree actually | |
| 95 | -looks like. You are correct that it's not a Huffman tree. It is simply a | |
| 96 | -lookup table for the first, let's say, nine bits of a Huffman symbol. The | |
| 97 | -symbol could be as short as one bit or as long as 15 bits. If a particular | |
| 98 | -symbol is shorter than nine bits, then that symbol's translation is duplicated | |
| 99 | -in all those entries that start with that symbol's bits. For example, if the | |
| 100 | -symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a | |
| 101 | -symbol is nine bits long, it appears in the table once. | |
| 102 | - | |
| 103 | -If the symbol is longer than nine bits, then that entry in the table points | |
| 104 | -to another similar table for the remaining bits. Again, there are duplicated | |
| 105 | -entries as needed. The idea is that most of the time the symbol will be short | |
| 106 | -and there will only be one table look up. (That's whole idea behind data | |
| 107 | -compression in the first place.) For the less frequent long symbols, there | |
| 108 | -will be two lookups. If you had a compression method with really long | |
| 109 | -symbols, you could have as many levels of lookups as is efficient. For | |
| 110 | -inflate, two is enough. | |
| 111 | - | |
| 112 | -So a table entry either points to another table (in which case nine bits in | |
| 113 | -the above example are gobbled), or it contains the translation for the symbol | |
| 114 | -and the number of bits to gobble. Then you start again with the next | |
| 115 | -ungobbled bit. | |
| 116 | - | |
| 117 | -You may wonder: why not just have one lookup table for how ever many bits the | |
| 118 | -longest symbol is? The reason is that if you do that, you end up spending | |
| 119 | -more time filling in duplicate symbol entries than you do actually decoding. | |
| 120 | -At least for deflate's output that generates new trees every several 10's of | |
| 121 | -kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code | |
| 122 | -would take too long if you're only decoding several thousand symbols. At the | |
| 123 | -other extreme, you could make a new table for every bit in the code. In fact, | |
| 124 | -that's essentially a Huffman tree. But then you spend too much time | |
| 125 | -traversing the tree while decoding, even for short symbols. | |
| 126 | - | |
| 127 | -So the number of bits for the first lookup table is a trade of the time to | |
| 128 | -fill out the table vs. the time spent looking at the second level and above of | |
| 129 | -the table. | |
| 130 | - | |
| 131 | -Here is an example, scaled down: | |
| 132 | - | |
| 133 | -The code being decoded, with 10 symbols, from 1 to 6 bits long: | |
| 134 | - | |
| 135 | -A: 0 | |
| 136 | -B: 10 | |
| 137 | -C: 1100 | |
| 138 | -D: 11010 | |
| 139 | -E: 11011 | |
| 140 | -F: 11100 | |
| 141 | -G: 11101 | |
| 142 | -H: 11110 | |
| 143 | -I: 111110 | |
| 144 | -J: 111111 | |
| 145 | - | |
| 146 | -Let's make the first table three bits long (eight entries): | |
| 147 | - | |
| 148 | -000: A,1 | |
| 149 | -001: A,1 | |
| 150 | -010: A,1 | |
| 151 | -011: A,1 | |
| 152 | -100: B,2 | |
| 153 | -101: B,2 | |
| 154 | -110: -> table X (gobble 3 bits) | |
| 155 | -111: -> table Y (gobble 3 bits) | |
| 156 | - | |
| 157 | -Each entry is what the bits decode as and how many bits that is, i.e. how | |
| 158 | -many bits to gobble. Or the entry points to another table, with the number of | |
| 159 | -bits to gobble implicit in the size of the table. | |
| 160 | - | |
| 161 | -Table X is two bits long since the longest code starting with 110 is five bits | |
| 162 | -long: | |
| 163 | - | |
| 164 | -00: C,1 | |
| 165 | -01: C,1 | |
| 166 | -10: D,2 | |
| 167 | -11: E,2 | |
| 168 | - | |
| 169 | -Table Y is three bits long since the longest code starting with 111 is six | |
| 170 | -bits long: | |
| 171 | - | |
| 172 | -000: F,2 | |
| 173 | -001: F,2 | |
| 174 | -010: G,2 | |
| 175 | -011: G,2 | |
| 176 | -100: H,2 | |
| 177 | -101: H,2 | |
| 178 | -110: I,3 | |
| 179 | -111: J,3 | |
| 180 | - | |
| 181 | -So what we have here are three tables with a total of 20 entries that had to | |
| 182 | -be constructed. That's compared to 64 entries for a single table. Or | |
| 183 | -compared to 16 entries for a Huffman tree (six two entry tables and one four | |
| 184 | -entry table). Assuming that the code ideally represents the probability of | |
| 185 | -the symbols, it takes on the average 1.25 lookups per symbol. That's compared | |
| 186 | -to one lookup for the single table, or 1.66 lookups per symbol for the | |
| 187 | -Huffman tree. | |
| 188 | - | |
| 189 | -There, I think that gives you a picture of what's going on. For inflate, the | |
| 190 | -meaning of a particular symbol is often more than just a letter. It can be a | |
| 191 | -byte (a "literal"), or it can be either a length or a distance which | |
| 192 | -indicates a base value and a number of bits to fetch after the code that is | |
| 193 | -added to the base value. Or it might be the special end-of-block code. The | |
| 194 | -data structures created in inftrees.c try to encode all that information | |
| 195 | -compactly in the tables. | |
| 196 | - | |
| 197 | - | |
| 198 | -Jean-loup Gailly Mark Adler | |
| 199 | -[email protected] [email protected] | |
| 200 | - | |
| 201 | - | |
| 202 | -References: | |
| 203 | - | |
| 204 | -[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data | |
| 205 | -Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, | |
| 206 | -pp. 337-343. | |
| 207 | - | |
| 208 | -``DEFLATE Compressed Data Format Specification'' available in | |
| 209 | -http://tools.ietf.org/html/rfc1951 |
| --- a/compat/zlib/doc/algorithm.txt | |
| +++ b/compat/zlib/doc/algorithm.txt | |
| @@ -1,209 +0,0 @@ | |
| 1 | 1. Compression algorithm (deflate) |
| 2 | |
| 3 | The deflation algorithm used by gzip (also zip and zlib) is a variation of |
| 4 | LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in |
| 5 | the input data. The second occurrence of a string is replaced by a |
| 6 | pointer to the previous string, in the form of a pair (distance, |
| 7 | length). Distances are limited to 32K bytes, and lengths are limited |
| 8 | to 258 bytes. When a string does not occur anywhere in the previous |
| 9 | 32K bytes, it is emitted as a sequence of literal bytes. (In this |
| 10 | description, `string' must be taken as an arbitrary sequence of bytes, |
| 11 | and is not restricted to printable characters.) |
| 12 | |
| 13 | Literals or match lengths are compressed with one Huffman tree, and |
| 14 | match distances are compressed with another tree. The trees are stored |
| 15 | in a compact form at the start of each block. The blocks can have any |
| 16 | size (except that the compressed data for one block must fit in |
| 17 | available memory). A block is terminated when deflate() determines that |
| 18 | it would be useful to start another block with fresh trees. (This is |
| 19 | somewhat similar to the behavior of LZW-based _compress_.) |
| 20 | |
| 21 | Duplicated strings are found using a hash table. All input strings of |
| 22 | length 3 are inserted in the hash table. A hash index is computed for |
| 23 | the next 3 bytes. If the hash chain for this index is not empty, all |
| 24 | strings in the chain are compared with the current input string, and |
| 25 | the longest match is selected. |
| 26 | |
| 27 | The hash chains are searched starting with the most recent strings, to |
| 28 | favor small distances and thus take advantage of the Huffman encoding. |
| 29 | The hash chains are singly linked. There are no deletions from the |
| 30 | hash chains, the algorithm simply discards matches that are too old. |
| 31 | |
| 32 | To avoid a worst-case situation, very long hash chains are arbitrarily |
| 33 | truncated at a certain length, determined by a runtime option (level |
| 34 | parameter of deflateInit). So deflate() does not always find the longest |
| 35 | possible match but generally finds a match which is long enough. |
| 36 | |
| 37 | deflate() also defers the selection of matches with a lazy evaluation |
| 38 | mechanism. After a match of length N has been found, deflate() searches for |
| 39 | a longer match at the next input byte. If a longer match is found, the |
| 40 | previous match is truncated to a length of one (thus producing a single |
| 41 | literal byte) and the process of lazy evaluation begins again. Otherwise, |
| 42 | the original match is kept, and the next match search is attempted only N |
| 43 | steps later. |
| 44 | |
| 45 | The lazy match evaluation is also subject to a runtime parameter. If |
| 46 | the current match is long enough, deflate() reduces the search for a longer |
| 47 | match, thus speeding up the whole process. If compression ratio is more |
| 48 | important than speed, deflate() attempts a complete second search even if |
| 49 | the first match is already long enough. |
| 50 | |
| 51 | The lazy match evaluation is not performed for the fastest compression |
| 52 | modes (level parameter 1 to 3). For these fast modes, new strings |
| 53 | are inserted in the hash table only when no match was found, or |
| 54 | when the match is not too long. This degrades the compression ratio |
| 55 | but saves time since there are both fewer insertions and fewer searches. |
| 56 | |
| 57 | |
| 58 | 2. Decompression algorithm (inflate) |
| 59 | |
| 60 | 2.1 Introduction |
| 61 | |
| 62 | The key question is how to represent a Huffman code (or any prefix code) so |
| 63 | that you can decode fast. The most important characteristic is that shorter |
| 64 | codes are much more common than longer codes, so pay attention to decoding the |
| 65 | short codes fast, and let the long codes take longer to decode. |
| 66 | |
| 67 | inflate() sets up a first level table that covers some number of bits of |
| 68 | input less than the length of longest code. It gets that many bits from the |
| 69 | stream, and looks it up in the table. The table will tell if the next |
| 70 | code is that many bits or less and how many, and if it is, it will tell |
| 71 | the value, else it will point to the next level table for which inflate() |
| 72 | grabs more bits and tries to decode a longer code. |
| 73 | |
| 74 | How many bits to make the first lookup is a tradeoff between the time it |
| 75 | takes to decode and the time it takes to build the table. If building the |
| 76 | table took no time (and if you had infinite memory), then there would only |
| 77 | be a first level table to cover all the way to the longest code. However, |
| 78 | building the table ends up taking a lot longer for more bits since short |
| 79 | codes are replicated many times in such a table. What inflate() does is |
| 80 | simply to make the number of bits in the first table a variable, and then |
| 81 | to set that variable for the maximum speed. |
| 82 | |
| 83 | For inflate, which has 286 possible codes for the literal/length tree, the size |
| 84 | of the first table is nine bits. Also the distance trees have 30 possible |
| 85 | values, and the size of the first table is six bits. Note that for each of |
| 86 | those cases, the table ended up one bit longer than the ``average'' code |
| 87 | length, i.e. the code length of an approximately flat code which would be a |
| 88 | little more than eight bits for 286 symbols and a little less than five bits |
| 89 | for 30 symbols. |
| 90 | |
| 91 | |
| 92 | 2.2 More details on the inflate table lookup |
| 93 | |
| 94 | Ok, you want to know what this cleverly obfuscated inflate tree actually |
| 95 | looks like. You are correct that it's not a Huffman tree. It is simply a |
| 96 | lookup table for the first, let's say, nine bits of a Huffman symbol. The |
| 97 | symbol could be as short as one bit or as long as 15 bits. If a particular |
| 98 | symbol is shorter than nine bits, then that symbol's translation is duplicated |
| 99 | in all those entries that start with that symbol's bits. For example, if the |
| 100 | symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a |
| 101 | symbol is nine bits long, it appears in the table once. |
| 102 | |
| 103 | If the symbol is longer than nine bits, then that entry in the table points |
| 104 | to another similar table for the remaining bits. Again, there are duplicated |
| 105 | entries as needed. The idea is that most of the time the symbol will be short |
| 106 | and there will only be one table look up. (That's whole idea behind data |
| 107 | compression in the first place.) For the less frequent long symbols, there |
| 108 | will be two lookups. If you had a compression method with really long |
| 109 | symbols, you could have as many levels of lookups as is efficient. For |
| 110 | inflate, two is enough. |
| 111 | |
| 112 | So a table entry either points to another table (in which case nine bits in |
| 113 | the above example are gobbled), or it contains the translation for the symbol |
| 114 | and the number of bits to gobble. Then you start again with the next |
| 115 | ungobbled bit. |
| 116 | |
| 117 | You may wonder: why not just have one lookup table for how ever many bits the |
| 118 | longest symbol is? The reason is that if you do that, you end up spending |
| 119 | more time filling in duplicate symbol entries than you do actually decoding. |
| 120 | At least for deflate's output that generates new trees every several 10's of |
| 121 | kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code |
| 122 | would take too long if you're only decoding several thousand symbols. At the |
| 123 | other extreme, you could make a new table for every bit in the code. In fact, |
| 124 | that's essentially a Huffman tree. But then you spend too much time |
| 125 | traversing the tree while decoding, even for short symbols. |
| 126 | |
| 127 | So the number of bits for the first lookup table is a trade of the time to |
| 128 | fill out the table vs. the time spent looking at the second level and above of |
| 129 | the table. |
| 130 | |
| 131 | Here is an example, scaled down: |
| 132 | |
| 133 | The code being decoded, with 10 symbols, from 1 to 6 bits long: |
| 134 | |
| 135 | A: 0 |
| 136 | B: 10 |
| 137 | C: 1100 |
| 138 | D: 11010 |
| 139 | E: 11011 |
| 140 | F: 11100 |
| 141 | G: 11101 |
| 142 | H: 11110 |
| 143 | I: 111110 |
| 144 | J: 111111 |
| 145 | |
| 146 | Let's make the first table three bits long (eight entries): |
| 147 | |
| 148 | 000: A,1 |
| 149 | 001: A,1 |
| 150 | 010: A,1 |
| 151 | 011: A,1 |
| 152 | 100: B,2 |
| 153 | 101: B,2 |
| 154 | 110: -> table X (gobble 3 bits) |
| 155 | 111: -> table Y (gobble 3 bits) |
| 156 | |
| 157 | Each entry is what the bits decode as and how many bits that is, i.e. how |
| 158 | many bits to gobble. Or the entry points to another table, with the number of |
| 159 | bits to gobble implicit in the size of the table. |
| 160 | |
| 161 | Table X is two bits long since the longest code starting with 110 is five bits |
| 162 | long: |
| 163 | |
| 164 | 00: C,1 |
| 165 | 01: C,1 |
| 166 | 10: D,2 |
| 167 | 11: E,2 |
| 168 | |
| 169 | Table Y is three bits long since the longest code starting with 111 is six |
| 170 | bits long: |
| 171 | |
| 172 | 000: F,2 |
| 173 | 001: F,2 |
| 174 | 010: G,2 |
| 175 | 011: G,2 |
| 176 | 100: H,2 |
| 177 | 101: H,2 |
| 178 | 110: I,3 |
| 179 | 111: J,3 |
| 180 | |
| 181 | So what we have here are three tables with a total of 20 entries that had to |
| 182 | be constructed. That's compared to 64 entries for a single table. Or |
| 183 | compared to 16 entries for a Huffman tree (six two entry tables and one four |
| 184 | entry table). Assuming that the code ideally represents the probability of |
| 185 | the symbols, it takes on the average 1.25 lookups per symbol. That's compared |
| 186 | to one lookup for the single table, or 1.66 lookups per symbol for the |
| 187 | Huffman tree. |
| 188 | |
| 189 | There, I think that gives you a picture of what's going on. For inflate, the |
| 190 | meaning of a particular symbol is often more than just a letter. It can be a |
| 191 | byte (a "literal"), or it can be either a length or a distance which |
| 192 | indicates a base value and a number of bits to fetch after the code that is |
| 193 | added to the base value. Or it might be the special end-of-block code. The |
| 194 | data structures created in inftrees.c try to encode all that information |
| 195 | compactly in the tables. |
| 196 | |
| 197 | |
| 198 | Jean-loup Gailly Mark Adler |
| 199 | [email protected] [email protected] |
| 200 | |
| 201 | |
| 202 | References: |
| 203 | |
| 204 | [LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data |
| 205 | Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, |
| 206 | pp. 337-343. |
| 207 | |
| 208 | ``DEFLATE Compressed Data Format Specification'' available in |
| 209 | http://tools.ietf.org/html/rfc1951 |
| --- a/compat/zlib/doc/algorithm.txt | |
| +++ b/compat/zlib/doc/algorithm.txt | |
| @@ -1,209 +0,0 @@ | |
D
compat/zlib/doc/rfc1950.txt
-630
| --- a/compat/zlib/doc/rfc1950.txt | ||
| +++ b/compat/zlib/doc/rfc1950.txt | ||
| @@ -1,630 +0,0 @@ | ||
| 1 | - | |
| 2 | - | |
| 3 | - | |
| 4 | - | |
| 5 | - | |
| 6 | - | |
| 7 | -Network Working Group P. Deutsch | |
| 8 | -Request for Comments: 1950 Aladdin Enterprises | |
| 9 | -Category: Informational J-L. Gailly | |
| 10 | - Info-ZIP | |
| 11 | - May 1996 | |
| 12 | - | |
| 13 | - | |
| 14 | - ZLIB Compressed Data Format Specification version 3.3 | |
| 15 | - | |
| 16 | -Status of This Memo | |
| 17 | - | |
| 18 | - This memo provides information for the Internet community. This memo | |
| 19 | - does not specify an Internet standard of any kind. Distribution of | |
| 20 | - this memo is unlimited. | |
| 21 | - | |
| 22 | -IESG Note: | |
| 23 | - | |
| 24 | - The IESG takes no position on the validity of any Intellectual | |
| 25 | - Property Rights statements contained in this document. | |
| 26 | - | |
| 27 | -Notices | |
| 28 | - | |
| 29 | - Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly | |
| 30 | - | |
| 31 | - Permission is granted to copy and distribute this document for any | |
| 32 | - purpose and without charge, including translations into other | |
| 33 | - languages and incorporation into compilations, provided that the | |
| 34 | - copyright notice and this notice are preserved, and that any | |
| 35 | - substantive changes or deletions from the original are clearly | |
| 36 | - marked. | |
| 37 | - | |
| 38 | - A pointer to the latest version of this and related documentation in | |
| 39 | - HTML format can be found at the URL | |
| 40 | - <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>. | |
| 41 | - | |
| 42 | -Abstract | |
| 43 | - | |
| 44 | - This specification defines a lossless compressed data format. The | |
| 45 | - data can be produced or consumed, even for an arbitrarily long | |
| 46 | - sequentially presented input data stream, using only an a priori | |
| 47 | - bounded amount of intermediate storage. The format presently uses | |
| 48 | - the DEFLATE compression method but can be easily extended to use | |
| 49 | - other compression methods. It can be implemented readily in a manner | |
| 50 | - not covered by patents. This specification also defines the ADLER-32 | |
| 51 | - checksum (an extension and improvement of the Fletcher checksum), | |
| 52 | - used for detection of data corruption, and provides an algorithm for | |
| 53 | - computing it. | |
| 54 | - | |
| 55 | - | |
| 56 | - | |
| 57 | - | |
| 58 | -Deutsch & Gailly Informational [Page 1] | |
| 59 | - | |
| 60 | - | |
| 61 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 62 | - | |
| 63 | - | |
| 64 | -Table of Contents | |
| 65 | - | |
| 66 | - 1. Introduction ................................................... 2 | |
| 67 | - 1.1. Purpose ................................................... 2 | |
| 68 | - 1.2. Intended audience ......................................... 3 | |
| 69 | - 1.3. Scope ..................................................... 3 | |
| 70 | - 1.4. Compliance ................................................ 3 | |
| 71 | - 1.5. Definitions of terms and conventions used ................ 3 | |
| 72 | - 1.6. Changes from previous versions ............................ 3 | |
| 73 | - 2. Detailed specification ......................................... 3 | |
| 74 | - 2.1. Overall conventions ....................................... 3 | |
| 75 | - 2.2. Data format ............................................... 4 | |
| 76 | - 2.3. Compliance ................................................ 7 | |
| 77 | - 3. References ..................................................... 7 | |
| 78 | - 4. Source code .................................................... 8 | |
| 79 | - 5. Security Considerations ........................................ 8 | |
| 80 | - 6. Acknowledgements ............................................... 8 | |
| 81 | - 7. Authors' Addresses ............................................. 8 | |
| 82 | - 8. Appendix: Rationale ............................................ 9 | |
| 83 | - 9. Appendix: Sample code ..........................................10 | |
| 84 | - | |
| 85 | -1. Introduction | |
| 86 | - | |
| 87 | - 1.1. Purpose | |
| 88 | - | |
| 89 | - The purpose of this specification is to define a lossless | |
| 90 | - compressed data format that: | |
| 91 | - | |
| 92 | - * Is independent of CPU type, operating system, file system, | |
| 93 | - and character set, and hence can be used for interchange; | |
| 94 | - | |
| 95 | - * Can be produced or consumed, even for an arbitrarily long | |
| 96 | - sequentially presented input data stream, using only an a | |
| 97 | - priori bounded amount of intermediate storage, and hence can | |
| 98 | - be used in data communications or similar structures such as | |
| 99 | - Unix filters; | |
| 100 | - | |
| 101 | - * Can use a number of different compression methods; | |
| 102 | - | |
| 103 | - * Can be implemented readily in a manner not covered by | |
| 104 | - patents, and hence can be practiced freely. | |
| 105 | - | |
| 106 | - The data format defined by this specification does not attempt to | |
| 107 | - allow random access to compressed data. | |
| 108 | - | |
| 109 | - | |
| 110 | - | |
| 111 | - | |
| 112 | - | |
| 113 | - | |
| 114 | - | |
| 115 | -Deutsch & Gailly Informational [Page 2] | |
| 116 | - | |
| 117 | - | |
| 118 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 119 | - | |
| 120 | - | |
| 121 | - 1.2. Intended audience | |
| 122 | - | |
| 123 | - This specification is intended for use by implementors of software | |
| 124 | - to compress data into zlib format and/or decompress data from zlib | |
| 125 | - format. | |
| 126 | - | |
| 127 | - The text of the specification assumes a basic background in | |
| 128 | - programming at the level of bits and other primitive data | |
| 129 | - representations. | |
| 130 | - | |
| 131 | - 1.3. Scope | |
| 132 | - | |
| 133 | - The specification specifies a compressed data format that can be | |
| 134 | - used for in-memory compression of a sequence of arbitrary bytes. | |
| 135 | - | |
| 136 | - 1.4. Compliance | |
| 137 | - | |
| 138 | - Unless otherwise indicated below, a compliant decompressor must be | |
| 139 | - able to accept and decompress any data set that conforms to all | |
| 140 | - the specifications presented here; a compliant compressor must | |
| 141 | - produce data sets that conform to all the specifications presented | |
| 142 | - here. | |
| 143 | - | |
| 144 | - 1.5. Definitions of terms and conventions used | |
| 145 | - | |
| 146 | - byte: 8 bits stored or transmitted as a unit (same as an octet). | |
| 147 | - (For this specification, a byte is exactly 8 bits, even on | |
| 148 | - machines which store a character on a number of bits different | |
| 149 | - from 8.) See below, for the numbering of bits within a byte. | |
| 150 | - | |
| 151 | - 1.6. Changes from previous versions | |
| 152 | - | |
| 153 | - Version 3.1 was the first public release of this specification. | |
| 154 | - In version 3.2, some terminology was changed and the Adler-32 | |
| 155 | - sample code was rewritten for clarity. In version 3.3, the | |
| 156 | - support for a preset dictionary was introduced, and the | |
| 157 | - specification was converted to RFC style. | |
| 158 | - | |
| 159 | -2. Detailed specification | |
| 160 | - | |
| 161 | - 2.1. Overall conventions | |
| 162 | - | |
| 163 | - In the diagrams below, a box like this: | |
| 164 | - | |
| 165 | - +---+ | |
| 166 | - | | <-- the vertical bars might be missing | |
| 167 | - +---+ | |
| 168 | - | |
| 169 | - | |
| 170 | - | |
| 171 | - | |
| 172 | -Deutsch & Gailly Informational [Page 3] | |
| 173 | - | |
| 174 | - | |
| 175 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 176 | - | |
| 177 | - | |
| 178 | - represents one byte; a box like this: | |
| 179 | - | |
| 180 | - +==============+ | |
| 181 | - | | | |
| 182 | - +==============+ | |
| 183 | - | |
| 184 | - represents a variable number of bytes. | |
| 185 | - | |
| 186 | - Bytes stored within a computer do not have a "bit order", since | |
| 187 | - they are always treated as a unit. However, a byte considered as | |
| 188 | - an integer between 0 and 255 does have a most- and least- | |
| 189 | - significant bit, and since we write numbers with the most- | |
| 190 | - significant digit on the left, we also write bytes with the most- | |
| 191 | - significant bit on the left. In the diagrams below, we number the | |
| 192 | - bits of a byte so that bit 0 is the least-significant bit, i.e., | |
| 193 | - the bits are numbered: | |
| 194 | - | |
| 195 | - +--------+ | |
| 196 | - |76543210| | |
| 197 | - +--------+ | |
| 198 | - | |
| 199 | - Within a computer, a number may occupy multiple bytes. All | |
| 200 | - multi-byte numbers in the format described here are stored with | |
| 201 | - the MOST-significant byte first (at the lower memory address). | |
| 202 | - For example, the decimal number 520 is stored as: | |
| 203 | - | |
| 204 | - 0 1 | |
| 205 | - +--------+--------+ | |
| 206 | - |00000010|00001000| | |
| 207 | - +--------+--------+ | |
| 208 | - ^ ^ | |
| 209 | - | | | |
| 210 | - | + less significant byte = 8 | |
| 211 | - + more significant byte = 2 x 256 | |
| 212 | - | |
| 213 | - 2.2. Data format | |
| 214 | - | |
| 215 | - A zlib stream has the following structure: | |
| 216 | - | |
| 217 | - 0 1 | |
| 218 | - +---+---+ | |
| 219 | - |CMF|FLG| (more-->) | |
| 220 | - +---+---+ | |
| 221 | - | |
| 222 | - | |
| 223 | - | |
| 224 | - | |
| 225 | - | |
| 226 | - | |
| 227 | - | |
| 228 | - | |
| 229 | -Deutsch & Gailly Informational [Page 4] | |
| 230 | - | |
| 231 | - | |
| 232 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 233 | - | |
| 234 | - | |
| 235 | - (if FLG.FDICT set) | |
| 236 | - | |
| 237 | - 0 1 2 3 | |
| 238 | - +---+---+---+---+ | |
| 239 | - | DICTID | (more-->) | |
| 240 | - +---+---+---+---+ | |
| 241 | - | |
| 242 | - +=====================+---+---+---+---+ | |
| 243 | - |...compressed data...| ADLER32 | | |
| 244 | - +=====================+---+---+---+---+ | |
| 245 | - | |
| 246 | - Any data which may appear after ADLER32 are not part of the zlib | |
| 247 | - stream. | |
| 248 | - | |
| 249 | - CMF (Compression Method and flags) | |
| 250 | - This byte is divided into a 4-bit compression method and a 4- | |
| 251 | - bit information field depending on the compression method. | |
| 252 | - | |
| 253 | - bits 0 to 3 CM Compression method | |
| 254 | - bits 4 to 7 CINFO Compression info | |
| 255 | - | |
| 256 | - CM (Compression method) | |
| 257 | - This identifies the compression method used in the file. CM = 8 | |
| 258 | - denotes the "deflate" compression method with a window size up | |
| 259 | - to 32K. This is the method used by gzip and PNG (see | |
| 260 | - references [1] and [2] in Chapter 3, below, for the reference | |
| 261 | - documents). CM = 15 is reserved. It might be used in a future | |
| 262 | - version of this specification to indicate the presence of an | |
| 263 | - extra field before the compressed data. | |
| 264 | - | |
| 265 | - CINFO (Compression info) | |
| 266 | - For CM = 8, CINFO is the base-2 logarithm of the LZ77 window | |
| 267 | - size, minus eight (CINFO=7 indicates a 32K window size). Values | |
| 268 | - of CINFO above 7 are not allowed in this version of the | |
| 269 | - specification. CINFO is not defined in this specification for | |
| 270 | - CM not equal to 8. | |
| 271 | - | |
| 272 | - FLG (FLaGs) | |
| 273 | - This flag byte is divided as follows: | |
| 274 | - | |
| 275 | - bits 0 to 4 FCHECK (check bits for CMF and FLG) | |
| 276 | - bit 5 FDICT (preset dictionary) | |
| 277 | - bits 6 to 7 FLEVEL (compression level) | |
| 278 | - | |
| 279 | - The FCHECK value must be such that CMF and FLG, when viewed as | |
| 280 | - a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), | |
| 281 | - is a multiple of 31. | |
| 282 | - | |
| 283 | - | |
| 284 | - | |
| 285 | - | |
| 286 | -Deutsch & Gailly Informational [Page 5] | |
| 287 | - | |
| 288 | - | |
| 289 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 290 | - | |
| 291 | - | |
| 292 | - FDICT (Preset dictionary) | |
| 293 | - If FDICT is set, a DICT dictionary identifier is present | |
| 294 | - immediately after the FLG byte. The dictionary is a sequence of | |
| 295 | - bytes which are initially fed to the compressor without | |
| 296 | - producing any compressed output. DICT is the Adler-32 checksum | |
| 297 | - of this sequence of bytes (see the definition of ADLER32 | |
| 298 | - below). The decompressor can use this identifier to determine | |
| 299 | - which dictionary has been used by the compressor. | |
| 300 | - | |
| 301 | - FLEVEL (Compression level) | |
| 302 | - These flags are available for use by specific compression | |
| 303 | - methods. The "deflate" method (CM = 8) sets these flags as | |
| 304 | - follows: | |
| 305 | - | |
| 306 | - 0 - compressor used fastest algorithm | |
| 307 | - 1 - compressor used fast algorithm | |
| 308 | - 2 - compressor used default algorithm | |
| 309 | - 3 - compressor used maximum compression, slowest algorithm | |
| 310 | - | |
| 311 | - The information in FLEVEL is not needed for decompression; it | |
| 312 | - is there to indicate if recompression might be worthwhile. | |
| 313 | - | |
| 314 | - compressed data | |
| 315 | - For compression method 8, the compressed data is stored in the | |
| 316 | - deflate compressed data format as described in the document | |
| 317 | - "DEFLATE Compressed Data Format Specification" by L. Peter | |
| 318 | - Deutsch. (See reference [3] in Chapter 3, below) | |
| 319 | - | |
| 320 | - Other compressed data formats are not specified in this version | |
| 321 | - of the zlib specification. | |
| 322 | - | |
| 323 | - ADLER32 (Adler-32 checksum) | |
| 324 | - This contains a checksum value of the uncompressed data | |
| 325 | - (excluding any dictionary data) computed according to Adler-32 | |
| 326 | - algorithm. This algorithm is a 32-bit extension and improvement | |
| 327 | - of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 | |
| 328 | - standard. See references [4] and [5] in Chapter 3, below) | |
| 329 | - | |
| 330 | - Adler-32 is composed of two sums accumulated per byte: s1 is | |
| 331 | - the sum of all bytes, s2 is the sum of all s1 values. Both sums | |
| 332 | - are done modulo 65521. s1 is initialized to 1, s2 to zero. The | |
| 333 | - Adler-32 checksum is stored as s2*65536 + s1 in most- | |
| 334 | - significant-byte first (network) order. | |
| 335 | - | |
| 336 | - | |
| 337 | - | |
| 338 | - | |
| 339 | - | |
| 340 | - | |
| 341 | - | |
| 342 | - | |
| 343 | -Deutsch & Gailly Informational [Page 6] | |
| 344 | - | |
| 345 | - | |
| 346 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 347 | - | |
| 348 | - | |
| 349 | - 2.3. Compliance | |
| 350 | - | |
| 351 | - A compliant compressor must produce streams with correct CMF, FLG | |
| 352 | - and ADLER32, but need not support preset dictionaries. When the | |
| 353 | - zlib data format is used as part of another standard data format, | |
| 354 | - the compressor may use only preset dictionaries that are specified | |
| 355 | - by this other data format. If this other format does not use the | |
| 356 | - preset dictionary feature, the compressor must not set the FDICT | |
| 357 | - flag. | |
| 358 | - | |
| 359 | - A compliant decompressor must check CMF, FLG, and ADLER32, and | |
| 360 | - provide an error indication if any of these have incorrect values. | |
| 361 | - A compliant decompressor must give an error indication if CM is | |
| 362 | - not one of the values defined in this specification (only the | |
| 363 | - value 8 is permitted in this version), since another value could | |
| 364 | - indicate the presence of new features that would cause subsequent | |
| 365 | - data to be interpreted incorrectly. A compliant decompressor must | |
| 366 | - give an error indication if FDICT is set and DICTID is not the | |
| 367 | - identifier of a known preset dictionary. A decompressor may | |
| 368 | - ignore FLEVEL and still be compliant. When the zlib data format | |
| 369 | - is being used as a part of another standard format, a compliant | |
| 370 | - decompressor must support all the preset dictionaries specified by | |
| 371 | - the other format. When the other format does not use the preset | |
| 372 | - dictionary feature, a compliant decompressor must reject any | |
| 373 | - stream in which the FDICT flag is set. | |
| 374 | - | |
| 375 | -3. References | |
| 376 | - | |
| 377 | - [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", | |
| 378 | - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ | |
| 379 | - | |
| 380 | - [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", | |
| 381 | - available in ftp://ftp.uu.net/graphics/png/documents/ | |
| 382 | - | |
| 383 | - [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", | |
| 384 | - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ | |
| 385 | - | |
| 386 | - [4] Fletcher, J. G., "An Arithmetic Checksum for Serial | |
| 387 | - Transmissions," IEEE Transactions on Communications, Vol. COM-30, | |
| 388 | - No. 1, January 1982, pp. 247-252. | |
| 389 | - | |
| 390 | - [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," | |
| 391 | - November, 1993, pp. 144, 145. (Available from | |
| 392 | - gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. | |
| 393 | - | |
| 394 | - | |
| 395 | - | |
| 396 | - | |
| 397 | - | |
| 398 | - | |
| 399 | - | |
| 400 | -Deutsch & Gailly Informational [Page 7] | |
| 401 | - | |
| 402 | - | |
| 403 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 404 | - | |
| 405 | - | |
| 406 | -4. Source code | |
| 407 | - | |
| 408 | - Source code for a C language implementation of a "zlib" compliant | |
| 409 | - library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. | |
| 410 | - | |
| 411 | -5. Security Considerations | |
| 412 | - | |
| 413 | - A decoder that fails to check the ADLER32 checksum value may be | |
| 414 | - subject to undetected data corruption. | |
| 415 | - | |
| 416 | -6. Acknowledgements | |
| 417 | - | |
| 418 | - Trademarks cited in this document are the property of their | |
| 419 | - respective owners. | |
| 420 | - | |
| 421 | - Jean-Loup Gailly and Mark Adler designed the zlib format and wrote | |
| 422 | - the related software described in this specification. Glenn | |
| 423 | - Randers-Pehrson converted this document to RFC and HTML format. | |
| 424 | - | |
| 425 | -7. Authors' Addresses | |
| 426 | - | |
| 427 | - L. Peter Deutsch | |
| 428 | - Aladdin Enterprises | |
| 429 | - 203 Santa Margarita Ave. | |
| 430 | - Menlo Park, CA 94025 | |
| 431 | - | |
| 432 | - Phone: (415) 322-0103 (AM only) | |
| 433 | - FAX: (415) 322-1734 | |
| 434 | - EMail: <[email protected]> | |
| 435 | - | |
| 436 | - | |
| 437 | - Jean-Loup Gailly | |
| 438 | - | |
| 439 | - EMail: <[email protected]> | |
| 440 | - | |
| 441 | - Questions about the technical content of this specification can be | |
| 442 | - sent by email to | |
| 443 | - | |
| 444 | - Jean-Loup Gailly <[email protected]> and | |
| 445 | - Mark Adler <[email protected]> | |
| 446 | - | |
| 447 | - Editorial comments on this specification can be sent by email to | |
| 448 | - | |
| 449 | - L. Peter Deutsch <[email protected]> and | |
| 450 | - Glenn Randers-Pehrson <[email protected]> | |
| 451 | - | |
| 452 | - | |
| 453 | - | |
| 454 | - | |
| 455 | - | |
| 456 | - | |
| 457 | -Deutsch & Gailly Informational [Page 8] | |
| 458 | - | |
| 459 | - | |
| 460 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 461 | - | |
| 462 | - | |
| 463 | -8. Appendix: Rationale | |
| 464 | - | |
| 465 | - 8.1. Preset dictionaries | |
| 466 | - | |
| 467 | - A preset dictionary is specially useful to compress short input | |
| 468 | - sequences. The compressor can take advantage of the dictionary | |
| 469 | - context to encode the input in a more compact manner. The | |
| 470 | - decompressor can be initialized with the appropriate context by | |
| 471 | - virtually decompressing a compressed version of the dictionary | |
| 472 | - without producing any output. However for certain compression | |
| 473 | - algorithms such as the deflate algorithm this operation can be | |
| 474 | - achieved without actually performing any decompression. | |
| 475 | - | |
| 476 | - The compressor and the decompressor must use exactly the same | |
| 477 | - dictionary. The dictionary may be fixed or may be chosen among a | |
| 478 | - certain number of predefined dictionaries, according to the kind | |
| 479 | - of input data. The decompressor can determine which dictionary has | |
| 480 | - been chosen by the compressor by checking the dictionary | |
| 481 | - identifier. This document does not specify the contents of | |
| 482 | - predefined dictionaries, since the optimal dictionaries are | |
| 483 | - application specific. Standard data formats using this feature of | |
| 484 | - the zlib specification must precisely define the allowed | |
| 485 | - dictionaries. | |
| 486 | - | |
| 487 | - 8.2. The Adler-32 algorithm | |
| 488 | - | |
| 489 | - The Adler-32 algorithm is much faster than the CRC32 algorithm yet | |
| 490 | - still provides an extremely low probability of undetected errors. | |
| 491 | - | |
| 492 | - The modulo on unsigned long accumulators can be delayed for 5552 | |
| 493 | - bytes, so the modulo operation time is negligible. If the bytes | |
| 494 | - are a, b, c, the second sum is 3a + 2b + c + 3, and so is position | |
| 495 | - and order sensitive, unlike the first sum, which is just a | |
| 496 | - checksum. That 65521 is prime is important to avoid a possible | |
| 497 | - large class of two-byte errors that leave the check unchanged. | |
| 498 | - (The Fletcher checksum uses 255, which is not prime and which also | |
| 499 | - makes the Fletcher check insensitive to single byte changes 0 <-> | |
| 500 | - 255.) | |
| 501 | - | |
| 502 | - The sum s1 is initialized to 1 instead of zero to make the length | |
| 503 | - of the sequence part of s2, so that the length does not have to be | |
| 504 | - checked separately. (Any sequence of zeroes has a Fletcher | |
| 505 | - checksum of zero.) | |
| 506 | - | |
| 507 | - | |
| 508 | - | |
| 509 | - | |
| 510 | - | |
| 511 | - | |
| 512 | - | |
| 513 | - | |
| 514 | -Deutsch & Gailly Informational [Page 9] | |
| 515 | - | |
| 516 | - | |
| 517 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 518 | - | |
| 519 | - | |
| 520 | -9. Appendix: Sample code | |
| 521 | - | |
| 522 | - The following C code computes the Adler-32 checksum of a data buffer. | |
| 523 | - It is written for clarity, not for speed. The sample code is in the | |
| 524 | - ANSI C programming language. Non C users may find it easier to read | |
| 525 | - with these hints: | |
| 526 | - | |
| 527 | - & Bitwise AND operator. | |
| 528 | - >> Bitwise right shift operator. When applied to an | |
| 529 | - unsigned quantity, as here, right shift inserts zero bit(s) | |
| 530 | - at the left. | |
| 531 | - << Bitwise left shift operator. Left shift inserts zero | |
| 532 | - bit(s) at the right. | |
| 533 | - ++ "n++" increments the variable n. | |
| 534 | - % modulo operator: a % b is the remainder of a divided by b. | |
| 535 | - | |
| 536 | - #define BASE 65521 /* largest prime smaller than 65536 */ | |
| 537 | - | |
| 538 | - /* | |
| 539 | - Update a running Adler-32 checksum with the bytes buf[0..len-1] | |
| 540 | - and return the updated checksum. The Adler-32 checksum should be | |
| 541 | - initialized to 1. | |
| 542 | - | |
| 543 | - Usage example: | |
| 544 | - | |
| 545 | - unsigned long adler = 1L; | |
| 546 | - | |
| 547 | - while (read_buffer(buffer, length) != EOF) { | |
| 548 | - adler = update_adler32(adler, buffer, length); | |
| 549 | - } | |
| 550 | - if (adler != original_adler) error(); | |
| 551 | - */ | |
| 552 | - unsigned long update_adler32(unsigned long adler, | |
| 553 | - unsigned char *buf, int len) | |
| 554 | - { | |
| 555 | - unsigned long s1 = adler & 0xffff; | |
| 556 | - unsigned long s2 = (adler >> 16) & 0xffff; | |
| 557 | - int n; | |
| 558 | - | |
| 559 | - for (n = 0; n < len; n++) { | |
| 560 | - s1 = (s1 + buf[n]) % BASE; | |
| 561 | - s2 = (s2 + s1) % BASE; | |
| 562 | - } | |
| 563 | - return (s2 << 16) + s1; | |
| 564 | - } | |
| 565 | - | |
| 566 | - /* Return the adler32 of the bytes buf[0..len-1] */ | |
| 567 | - | |
| 568 | - | |
| 569 | - | |
| 570 | - | |
| 571 | -Deutsch & Gailly Informational [Page 10] | |
| 572 | - | |
| 573 | - | |
| 574 | -RFC 1950 ZLIB Compressed Data Format Specification May 1996 | |
| 575 | - | |
| 576 | - | |
| 577 | - unsigned long adler32(unsigned char *buf, int len) | |
| 578 | - { | |
| 579 | - return update_adler32(1L, buf, len); | |
| 580 | - } | |
| 581 | - | |
| 582 | - | |
| 583 | - | |
| 584 | - | |
| 585 | - | |
| 586 | - | |
| 587 | - | |
| 588 | - | |
| 589 | - | |
| 590 | - | |
| 591 | - | |
| 592 | - | |
| 593 | - | |
| 594 | - | |
| 595 | - | |
| 596 | - | |
| 597 | - | |
| 598 | - | |
| 599 | - | |
| 600 | - | |
| 601 | - | |
| 602 | - | |
| 603 | - | |
| 604 | - | |
| 605 | - | |
| 606 | - | |
| 607 | - | |
| 608 | - | |
| 609 | - | |
| 610 | - | |
| 611 | - | |
| 612 | - | |
| 613 | - | |
| 614 | - | |
| 615 | - | |
| 616 | - | |
| 617 | - | |
| 618 | - | |
| 619 | - | |
| 620 | - | |
| 621 | - | |
| 622 | - | |
| 623 | - | |
| 624 | - | |
| 625 | - | |
| 626 | - | |
| 627 | - | |
| 628 | -Deutsch & Gailly Informational [Page 11] | |
| 629 | - | |
| 630 | - |
| --- a/compat/zlib/doc/rfc1950.txt | |
| +++ b/compat/zlib/doc/rfc1950.txt | |
| @@ -1,630 +0,0 @@ | |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | Network Working Group P. Deutsch |
| 8 | Request for Comments: 1950 Aladdin Enterprises |
| 9 | Category: Informational J-L. Gailly |
| 10 | Info-ZIP |
| 11 | May 1996 |
| 12 | |
| 13 | |
| 14 | ZLIB Compressed Data Format Specification version 3.3 |
| 15 | |
| 16 | Status of This Memo |
| 17 | |
| 18 | This memo provides information for the Internet community. This memo |
| 19 | does not specify an Internet standard of any kind. Distribution of |
| 20 | this memo is unlimited. |
| 21 | |
| 22 | IESG Note: |
| 23 | |
| 24 | The IESG takes no position on the validity of any Intellectual |
| 25 | Property Rights statements contained in this document. |
| 26 | |
| 27 | Notices |
| 28 | |
| 29 | Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly |
| 30 | |
| 31 | Permission is granted to copy and distribute this document for any |
| 32 | purpose and without charge, including translations into other |
| 33 | languages and incorporation into compilations, provided that the |
| 34 | copyright notice and this notice are preserved, and that any |
| 35 | substantive changes or deletions from the original are clearly |
| 36 | marked. |
| 37 | |
| 38 | A pointer to the latest version of this and related documentation in |
| 39 | HTML format can be found at the URL |
| 40 | <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>. |
| 41 | |
| 42 | Abstract |
| 43 | |
| 44 | This specification defines a lossless compressed data format. The |
| 45 | data can be produced or consumed, even for an arbitrarily long |
| 46 | sequentially presented input data stream, using only an a priori |
| 47 | bounded amount of intermediate storage. The format presently uses |
| 48 | the DEFLATE compression method but can be easily extended to use |
| 49 | other compression methods. It can be implemented readily in a manner |
| 50 | not covered by patents. This specification also defines the ADLER-32 |
| 51 | checksum (an extension and improvement of the Fletcher checksum), |
| 52 | used for detection of data corruption, and provides an algorithm for |
| 53 | computing it. |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | Deutsch & Gailly Informational [Page 1] |
| 59 | |
| 60 | |
| 61 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 62 | |
| 63 | |
| 64 | Table of Contents |
| 65 | |
| 66 | 1. Introduction ................................................... 2 |
| 67 | 1.1. Purpose ................................................... 2 |
| 68 | 1.2. Intended audience ......................................... 3 |
| 69 | 1.3. Scope ..................................................... 3 |
| 70 | 1.4. Compliance ................................................ 3 |
| 71 | 1.5. Definitions of terms and conventions used ................ 3 |
| 72 | 1.6. Changes from previous versions ............................ 3 |
| 73 | 2. Detailed specification ......................................... 3 |
| 74 | 2.1. Overall conventions ....................................... 3 |
| 75 | 2.2. Data format ............................................... 4 |
| 76 | 2.3. Compliance ................................................ 7 |
| 77 | 3. References ..................................................... 7 |
| 78 | 4. Source code .................................................... 8 |
| 79 | 5. Security Considerations ........................................ 8 |
| 80 | 6. Acknowledgements ............................................... 8 |
| 81 | 7. Authors' Addresses ............................................. 8 |
| 82 | 8. Appendix: Rationale ............................................ 9 |
| 83 | 9. Appendix: Sample code ..........................................10 |
| 84 | |
| 85 | 1. Introduction |
| 86 | |
| 87 | 1.1. Purpose |
| 88 | |
| 89 | The purpose of this specification is to define a lossless |
| 90 | compressed data format that: |
| 91 | |
| 92 | * Is independent of CPU type, operating system, file system, |
| 93 | and character set, and hence can be used for interchange; |
| 94 | |
| 95 | * Can be produced or consumed, even for an arbitrarily long |
| 96 | sequentially presented input data stream, using only an a |
| 97 | priori bounded amount of intermediate storage, and hence can |
| 98 | be used in data communications or similar structures such as |
| 99 | Unix filters; |
| 100 | |
| 101 | * Can use a number of different compression methods; |
| 102 | |
| 103 | * Can be implemented readily in a manner not covered by |
| 104 | patents, and hence can be practiced freely. |
| 105 | |
| 106 | The data format defined by this specification does not attempt to |
| 107 | allow random access to compressed data. |
| 108 | |
| 109 | |
| 110 | |
| 111 | |
| 112 | |
| 113 | |
| 114 | |
| 115 | Deutsch & Gailly Informational [Page 2] |
| 116 | |
| 117 | |
| 118 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 119 | |
| 120 | |
| 121 | 1.2. Intended audience |
| 122 | |
| 123 | This specification is intended for use by implementors of software |
| 124 | to compress data into zlib format and/or decompress data from zlib |
| 125 | format. |
| 126 | |
| 127 | The text of the specification assumes a basic background in |
| 128 | programming at the level of bits and other primitive data |
| 129 | representations. |
| 130 | |
| 131 | 1.3. Scope |
| 132 | |
| 133 | The specification specifies a compressed data format that can be |
| 134 | used for in-memory compression of a sequence of arbitrary bytes. |
| 135 | |
| 136 | 1.4. Compliance |
| 137 | |
| 138 | Unless otherwise indicated below, a compliant decompressor must be |
| 139 | able to accept and decompress any data set that conforms to all |
| 140 | the specifications presented here; a compliant compressor must |
| 141 | produce data sets that conform to all the specifications presented |
| 142 | here. |
| 143 | |
| 144 | 1.5. Definitions of terms and conventions used |
| 145 | |
| 146 | byte: 8 bits stored or transmitted as a unit (same as an octet). |
| 147 | (For this specification, a byte is exactly 8 bits, even on |
| 148 | machines which store a character on a number of bits different |
| 149 | from 8.) See below, for the numbering of bits within a byte. |
| 150 | |
| 151 | 1.6. Changes from previous versions |
| 152 | |
| 153 | Version 3.1 was the first public release of this specification. |
| 154 | In version 3.2, some terminology was changed and the Adler-32 |
| 155 | sample code was rewritten for clarity. In version 3.3, the |
| 156 | support for a preset dictionary was introduced, and the |
| 157 | specification was converted to RFC style. |
| 158 | |
| 159 | 2. Detailed specification |
| 160 | |
| 161 | 2.1. Overall conventions |
| 162 | |
| 163 | In the diagrams below, a box like this: |
| 164 | |
| 165 | +---+ |
| 166 | | | <-- the vertical bars might be missing |
| 167 | +---+ |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | Deutsch & Gailly Informational [Page 3] |
| 173 | |
| 174 | |
| 175 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 176 | |
| 177 | |
| 178 | represents one byte; a box like this: |
| 179 | |
| 180 | +==============+ |
| 181 | | | |
| 182 | +==============+ |
| 183 | |
| 184 | represents a variable number of bytes. |
| 185 | |
| 186 | Bytes stored within a computer do not have a "bit order", since |
| 187 | they are always treated as a unit. However, a byte considered as |
| 188 | an integer between 0 and 255 does have a most- and least- |
| 189 | significant bit, and since we write numbers with the most- |
| 190 | significant digit on the left, we also write bytes with the most- |
| 191 | significant bit on the left. In the diagrams below, we number the |
| 192 | bits of a byte so that bit 0 is the least-significant bit, i.e., |
| 193 | the bits are numbered: |
| 194 | |
| 195 | +--------+ |
| 196 | |76543210| |
| 197 | +--------+ |
| 198 | |
| 199 | Within a computer, a number may occupy multiple bytes. All |
| 200 | multi-byte numbers in the format described here are stored with |
| 201 | the MOST-significant byte first (at the lower memory address). |
| 202 | For example, the decimal number 520 is stored as: |
| 203 | |
| 204 | 0 1 |
| 205 | +--------+--------+ |
| 206 | |00000010|00001000| |
| 207 | +--------+--------+ |
| 208 | ^ ^ |
| 209 | | | |
| 210 | | + less significant byte = 8 |
| 211 | + more significant byte = 2 x 256 |
| 212 | |
| 213 | 2.2. Data format |
| 214 | |
| 215 | A zlib stream has the following structure: |
| 216 | |
| 217 | 0 1 |
| 218 | +---+---+ |
| 219 | |CMF|FLG| (more-->) |
| 220 | +---+---+ |
| 221 | |
| 222 | |
| 223 | |
| 224 | |
| 225 | |
| 226 | |
| 227 | |
| 228 | |
| 229 | Deutsch & Gailly Informational [Page 4] |
| 230 | |
| 231 | |
| 232 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 233 | |
| 234 | |
| 235 | (if FLG.FDICT set) |
| 236 | |
| 237 | 0 1 2 3 |
| 238 | +---+---+---+---+ |
| 239 | | DICTID | (more-->) |
| 240 | +---+---+---+---+ |
| 241 | |
| 242 | +=====================+---+---+---+---+ |
| 243 | |...compressed data...| ADLER32 | |
| 244 | +=====================+---+---+---+---+ |
| 245 | |
| 246 | Any data which may appear after ADLER32 are not part of the zlib |
| 247 | stream. |
| 248 | |
| 249 | CMF (Compression Method and flags) |
| 250 | This byte is divided into a 4-bit compression method and a 4- |
| 251 | bit information field depending on the compression method. |
| 252 | |
| 253 | bits 0 to 3 CM Compression method |
| 254 | bits 4 to 7 CINFO Compression info |
| 255 | |
| 256 | CM (Compression method) |
| 257 | This identifies the compression method used in the file. CM = 8 |
| 258 | denotes the "deflate" compression method with a window size up |
| 259 | to 32K. This is the method used by gzip and PNG (see |
| 260 | references [1] and [2] in Chapter 3, below, for the reference |
| 261 | documents). CM = 15 is reserved. It might be used in a future |
| 262 | version of this specification to indicate the presence of an |
| 263 | extra field before the compressed data. |
| 264 | |
| 265 | CINFO (Compression info) |
| 266 | For CM = 8, CINFO is the base-2 logarithm of the LZ77 window |
| 267 | size, minus eight (CINFO=7 indicates a 32K window size). Values |
| 268 | of CINFO above 7 are not allowed in this version of the |
| 269 | specification. CINFO is not defined in this specification for |
| 270 | CM not equal to 8. |
| 271 | |
| 272 | FLG (FLaGs) |
| 273 | This flag byte is divided as follows: |
| 274 | |
| 275 | bits 0 to 4 FCHECK (check bits for CMF and FLG) |
| 276 | bit 5 FDICT (preset dictionary) |
| 277 | bits 6 to 7 FLEVEL (compression level) |
| 278 | |
| 279 | The FCHECK value must be such that CMF and FLG, when viewed as |
| 280 | a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), |
| 281 | is a multiple of 31. |
| 282 | |
| 283 | |
| 284 | |
| 285 | |
| 286 | Deutsch & Gailly Informational [Page 5] |
| 287 | |
| 288 | |
| 289 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 290 | |
| 291 | |
| 292 | FDICT (Preset dictionary) |
| 293 | If FDICT is set, a DICT dictionary identifier is present |
| 294 | immediately after the FLG byte. The dictionary is a sequence of |
| 295 | bytes which are initially fed to the compressor without |
| 296 | producing any compressed output. DICT is the Adler-32 checksum |
| 297 | of this sequence of bytes (see the definition of ADLER32 |
| 298 | below). The decompressor can use this identifier to determine |
| 299 | which dictionary has been used by the compressor. |
| 300 | |
| 301 | FLEVEL (Compression level) |
| 302 | These flags are available for use by specific compression |
| 303 | methods. The "deflate" method (CM = 8) sets these flags as |
| 304 | follows: |
| 305 | |
| 306 | 0 - compressor used fastest algorithm |
| 307 | 1 - compressor used fast algorithm |
| 308 | 2 - compressor used default algorithm |
| 309 | 3 - compressor used maximum compression, slowest algorithm |
| 310 | |
| 311 | The information in FLEVEL is not needed for decompression; it |
| 312 | is there to indicate if recompression might be worthwhile. |
| 313 | |
| 314 | compressed data |
| 315 | For compression method 8, the compressed data is stored in the |
| 316 | deflate compressed data format as described in the document |
| 317 | "DEFLATE Compressed Data Format Specification" by L. Peter |
| 318 | Deutsch. (See reference [3] in Chapter 3, below) |
| 319 | |
| 320 | Other compressed data formats are not specified in this version |
| 321 | of the zlib specification. |
| 322 | |
| 323 | ADLER32 (Adler-32 checksum) |
| 324 | This contains a checksum value of the uncompressed data |
| 325 | (excluding any dictionary data) computed according to Adler-32 |
| 326 | algorithm. This algorithm is a 32-bit extension and improvement |
| 327 | of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 |
| 328 | standard. See references [4] and [5] in Chapter 3, below) |
| 329 | |
| 330 | Adler-32 is composed of two sums accumulated per byte: s1 is |
| 331 | the sum of all bytes, s2 is the sum of all s1 values. Both sums |
| 332 | are done modulo 65521. s1 is initialized to 1, s2 to zero. The |
| 333 | Adler-32 checksum is stored as s2*65536 + s1 in most- |
| 334 | significant-byte first (network) order. |
| 335 | |
| 336 | |
| 337 | |
| 338 | |
| 339 | |
| 340 | |
| 341 | |
| 342 | |
| 343 | Deutsch & Gailly Informational [Page 6] |
| 344 | |
| 345 | |
| 346 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 347 | |
| 348 | |
| 349 | 2.3. Compliance |
| 350 | |
| 351 | A compliant compressor must produce streams with correct CMF, FLG |
| 352 | and ADLER32, but need not support preset dictionaries. When the |
| 353 | zlib data format is used as part of another standard data format, |
| 354 | the compressor may use only preset dictionaries that are specified |
| 355 | by this other data format. If this other format does not use the |
| 356 | preset dictionary feature, the compressor must not set the FDICT |
| 357 | flag. |
| 358 | |
| 359 | A compliant decompressor must check CMF, FLG, and ADLER32, and |
| 360 | provide an error indication if any of these have incorrect values. |
| 361 | A compliant decompressor must give an error indication if CM is |
| 362 | not one of the values defined in this specification (only the |
| 363 | value 8 is permitted in this version), since another value could |
| 364 | indicate the presence of new features that would cause subsequent |
| 365 | data to be interpreted incorrectly. A compliant decompressor must |
| 366 | give an error indication if FDICT is set and DICTID is not the |
| 367 | identifier of a known preset dictionary. A decompressor may |
| 368 | ignore FLEVEL and still be compliant. When the zlib data format |
| 369 | is being used as a part of another standard format, a compliant |
| 370 | decompressor must support all the preset dictionaries specified by |
| 371 | the other format. When the other format does not use the preset |
| 372 | dictionary feature, a compliant decompressor must reject any |
| 373 | stream in which the FDICT flag is set. |
| 374 | |
| 375 | 3. References |
| 376 | |
| 377 | [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", |
| 378 | available in ftp://ftp.uu.net/pub/archiving/zip/doc/ |
| 379 | |
| 380 | [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", |
| 381 | available in ftp://ftp.uu.net/graphics/png/documents/ |
| 382 | |
| 383 | [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", |
| 384 | available in ftp://ftp.uu.net/pub/archiving/zip/doc/ |
| 385 | |
| 386 | [4] Fletcher, J. G., "An Arithmetic Checksum for Serial |
| 387 | Transmissions," IEEE Transactions on Communications, Vol. COM-30, |
| 388 | No. 1, January 1982, pp. 247-252. |
| 389 | |
| 390 | [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," |
| 391 | November, 1993, pp. 144, 145. (Available from |
| 392 | gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. |
| 393 | |
| 394 | |
| 395 | |
| 396 | |
| 397 | |
| 398 | |
| 399 | |
| 400 | Deutsch & Gailly Informational [Page 7] |
| 401 | |
| 402 | |
| 403 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 404 | |
| 405 | |
| 406 | 4. Source code |
| 407 | |
| 408 | Source code for a C language implementation of a "zlib" compliant |
| 409 | library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. |
| 410 | |
| 411 | 5. Security Considerations |
| 412 | |
| 413 | A decoder that fails to check the ADLER32 checksum value may be |
| 414 | subject to undetected data corruption. |
| 415 | |
| 416 | 6. Acknowledgements |
| 417 | |
| 418 | Trademarks cited in this document are the property of their |
| 419 | respective owners. |
| 420 | |
| 421 | Jean-Loup Gailly and Mark Adler designed the zlib format and wrote |
| 422 | the related software described in this specification. Glenn |
| 423 | Randers-Pehrson converted this document to RFC and HTML format. |
| 424 | |
| 425 | 7. Authors' Addresses |
| 426 | |
| 427 | L. Peter Deutsch |
| 428 | Aladdin Enterprises |
| 429 | 203 Santa Margarita Ave. |
| 430 | Menlo Park, CA 94025 |
| 431 | |
| 432 | Phone: (415) 322-0103 (AM only) |
| 433 | FAX: (415) 322-1734 |
| 434 | EMail: <[email protected]> |
| 435 | |
| 436 | |
| 437 | Jean-Loup Gailly |
| 438 | |
| 439 | EMail: <[email protected]> |
| 440 | |
| 441 | Questions about the technical content of this specification can be |
| 442 | sent by email to |
| 443 | |
| 444 | Jean-Loup Gailly <[email protected]> and |
| 445 | Mark Adler <[email protected]> |
| 446 | |
| 447 | Editorial comments on this specification can be sent by email to |
| 448 | |
| 449 | L. Peter Deutsch <[email protected]> and |
| 450 | Glenn Randers-Pehrson <[email protected]> |
| 451 | |
| 452 | |
| 453 | |
| 454 | |
| 455 | |
| 456 | |
| 457 | Deutsch & Gailly Informational [Page 8] |
| 458 | |
| 459 | |
| 460 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 461 | |
| 462 | |
| 463 | 8. Appendix: Rationale |
| 464 | |
| 465 | 8.1. Preset dictionaries |
| 466 | |
| 467 | A preset dictionary is specially useful to compress short input |
| 468 | sequences. The compressor can take advantage of the dictionary |
| 469 | context to encode the input in a more compact manner. The |
| 470 | decompressor can be initialized with the appropriate context by |
| 471 | virtually decompressing a compressed version of the dictionary |
| 472 | without producing any output. However for certain compression |
| 473 | algorithms such as the deflate algorithm this operation can be |
| 474 | achieved without actually performing any decompression. |
| 475 | |
| 476 | The compressor and the decompressor must use exactly the same |
| 477 | dictionary. The dictionary may be fixed or may be chosen among a |
| 478 | certain number of predefined dictionaries, according to the kind |
| 479 | of input data. The decompressor can determine which dictionary has |
| 480 | been chosen by the compressor by checking the dictionary |
| 481 | identifier. This document does not specify the contents of |
| 482 | predefined dictionaries, since the optimal dictionaries are |
| 483 | application specific. Standard data formats using this feature of |
| 484 | the zlib specification must precisely define the allowed |
| 485 | dictionaries. |
| 486 | |
| 487 | 8.2. The Adler-32 algorithm |
| 488 | |
| 489 | The Adler-32 algorithm is much faster than the CRC32 algorithm yet |
| 490 | still provides an extremely low probability of undetected errors. |
| 491 | |
| 492 | The modulo on unsigned long accumulators can be delayed for 5552 |
| 493 | bytes, so the modulo operation time is negligible. If the bytes |
| 494 | are a, b, c, the second sum is 3a + 2b + c + 3, and so is position |
| 495 | and order sensitive, unlike the first sum, which is just a |
| 496 | checksum. That 65521 is prime is important to avoid a possible |
| 497 | large class of two-byte errors that leave the check unchanged. |
| 498 | (The Fletcher checksum uses 255, which is not prime and which also |
| 499 | makes the Fletcher check insensitive to single byte changes 0 <-> |
| 500 | 255.) |
| 501 | |
| 502 | The sum s1 is initialized to 1 instead of zero to make the length |
| 503 | of the sequence part of s2, so that the length does not have to be |
| 504 | checked separately. (Any sequence of zeroes has a Fletcher |
| 505 | checksum of zero.) |
| 506 | |
| 507 | |
| 508 | |
| 509 | |
| 510 | |
| 511 | |
| 512 | |
| 513 | |
| 514 | Deutsch & Gailly Informational [Page 9] |
| 515 | |
| 516 | |
| 517 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 518 | |
| 519 | |
| 520 | 9. Appendix: Sample code |
| 521 | |
| 522 | The following C code computes the Adler-32 checksum of a data buffer. |
| 523 | It is written for clarity, not for speed. The sample code is in the |
| 524 | ANSI C programming language. Non C users may find it easier to read |
| 525 | with these hints: |
| 526 | |
| 527 | & Bitwise AND operator. |
| 528 | >> Bitwise right shift operator. When applied to an |
| 529 | unsigned quantity, as here, right shift inserts zero bit(s) |
| 530 | at the left. |
| 531 | << Bitwise left shift operator. Left shift inserts zero |
| 532 | bit(s) at the right. |
| 533 | ++ "n++" increments the variable n. |
| 534 | % modulo operator: a % b is the remainder of a divided by b. |
| 535 | |
| 536 | #define BASE 65521 /* largest prime smaller than 65536 */ |
| 537 | |
| 538 | /* |
| 539 | Update a running Adler-32 checksum with the bytes buf[0..len-1] |
| 540 | and return the updated checksum. The Adler-32 checksum should be |
| 541 | initialized to 1. |
| 542 | |
| 543 | Usage example: |
| 544 | |
| 545 | unsigned long adler = 1L; |
| 546 | |
| 547 | while (read_buffer(buffer, length) != EOF) { |
| 548 | adler = update_adler32(adler, buffer, length); |
| 549 | } |
| 550 | if (adler != original_adler) error(); |
| 551 | */ |
| 552 | unsigned long update_adler32(unsigned long adler, |
| 553 | unsigned char *buf, int len) |
| 554 | { |
| 555 | unsigned long s1 = adler & 0xffff; |
| 556 | unsigned long s2 = (adler >> 16) & 0xffff; |
| 557 | int n; |
| 558 | |
| 559 | for (n = 0; n < len; n++) { |
| 560 | s1 = (s1 + buf[n]) % BASE; |
| 561 | s2 = (s2 + s1) % BASE; |
| 562 | } |
| 563 | return (s2 << 16) + s1; |
| 564 | } |
| 565 | |
| 566 | /* Return the adler32 of the bytes buf[0..len-1] */ |
| 567 | |
| 568 | |
| 569 | |
| 570 | |
| 571 | Deutsch & Gailly Informational [Page 10] |
| 572 | |
| 573 | |
| 574 | RFC 1950 ZLIB Compressed Data Format Specification May 1996 |
| 575 | |
| 576 | |
| 577 | unsigned long adler32(unsigned char *buf, int len) |
| 578 | { |
| 579 | return update_adler32(1L, buf, len); |
| 580 | } |
| 581 | |
| 582 | |
| 583 | |
| 584 | |
| 585 | |
| 586 | |
| 587 | |
| 588 | |
| 589 | |
| 590 | |
| 591 | |
| 592 | |
| 593 | |
| 594 | |
| 595 | |
| 596 | |
| 597 | |
| 598 | |
| 599 | |
| 600 | |
| 601 | |
| 602 | |
| 603 | |
| 604 | |
| 605 | |
| 606 | |
| 607 | |
| 608 | |
| 609 | |
| 610 | |
| 611 | |
| 612 | |
| 613 | |
| 614 | |
| 615 | |
| 616 | |
| 617 | |
| 618 | |
| 619 | |
| 620 | |
| 621 | |
| 622 | |
| 623 | |
| 624 | |
| 625 | |
| 626 | |
| 627 | |
| 628 | Deutsch & Gailly Informational [Page 11] |
| 629 | |
| 630 |
| --- a/compat/zlib/doc/rfc1950.txt | |
| +++ b/compat/zlib/doc/rfc1950.txt | |
| @@ -1,630 +0,0 @@ | |
D
compat/zlib/doc/rfc1951.txt
-972
| --- a/compat/zlib/doc/rfc1951.txt | ||
| +++ b/compat/zlib/doc/rfc1951.txt | ||
| @@ -1,972 +0,0 @@ | ||
| 1 | - | |
| 2 | - | |
| 3 | - | |
| 4 | - | |
| 5 | - | |
| 6 | - | |
| 7 | -Network Working Group P. Deutsch | |
| 8 | -Request for Comments: 1951 Aladdin Enterprises | |
| 9 | -Category: Informational May 1996 | |
| 10 | - | |
| 11 | - | |
| 12 | - DEFLATE Compressed Data Format Specification version 1.3 | |
| 13 | - | |
| 14 | -Status of This Memo | |
| 15 | - | |
| 16 | - This memo provides information for the Internet community. This memo | |
| 17 | - does not specify an Internet standard of any kind. Distribution of | |
| 18 | - this memo is unlimited. | |
| 19 | - | |
| 20 | -IESG Note: | |
| 21 | - | |
| 22 | - The IESG takes no position on the validity of any Intellectual | |
| 23 | - Property Rights statements contained in this document. | |
| 24 | - | |
| 25 | -Notices | |
| 26 | - | |
| 27 | - Copyright (c) 1996 L. Peter Deutsch | |
| 28 | - | |
| 29 | - Permission is granted to copy and distribute this document for any | |
| 30 | - purpose and without charge, including translations into other | |
| 31 | - languages and incorporation into compilations, provided that the | |
| 32 | - copyright notice and this notice are preserved, and that any | |
| 33 | - substantive changes or deletions from the original are clearly | |
| 34 | - marked. | |
| 35 | - | |
| 36 | - A pointer to the latest version of this and related documentation in | |
| 37 | - HTML format can be found at the URL | |
| 38 | - <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>. | |
| 39 | - | |
| 40 | -Abstract | |
| 41 | - | |
| 42 | - This specification defines a lossless compressed data format that | |
| 43 | - compresses data using a combination of the LZ77 algorithm and Huffman | |
| 44 | - coding, with efficiency comparable to the best currently available | |
| 45 | - general-purpose compression methods. The data can be produced or | |
| 46 | - consumed, even for an arbitrarily long sequentially presented input | |
| 47 | - data stream, using only an a priori bounded amount of intermediate | |
| 48 | - storage. The format can be implemented readily in a manner not | |
| 49 | - covered by patents. | |
| 50 | - | |
| 51 | - | |
| 52 | - | |
| 53 | - | |
| 54 | - | |
| 55 | - | |
| 56 | - | |
| 57 | - | |
| 58 | -Deutsch Informational [Page 1] | |
| 59 | - | |
| 60 | - | |
| 61 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 62 | - | |
| 63 | - | |
| 64 | -Table of Contents | |
| 65 | - | |
| 66 | - 1. Introduction ................................................... 2 | |
| 67 | - 1.1. Purpose ................................................... 2 | |
| 68 | - 1.2. Intended audience ......................................... 3 | |
| 69 | - 1.3. Scope ..................................................... 3 | |
| 70 | - 1.4. Compliance ................................................ 3 | |
| 71 | - 1.5. Definitions of terms and conventions used ................ 3 | |
| 72 | - 1.6. Changes from previous versions ............................ 4 | |
| 73 | - 2. Compressed representation overview ............................. 4 | |
| 74 | - 3. Detailed specification ......................................... 5 | |
| 75 | - 3.1. Overall conventions ....................................... 5 | |
| 76 | - 3.1.1. Packing into bytes .................................. 5 | |
| 77 | - 3.2. Compressed block format ................................... 6 | |
| 78 | - 3.2.1. Synopsis of prefix and Huffman coding ............... 6 | |
| 79 | - 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 | |
| 80 | - 3.2.3. Details of block format ............................. 9 | |
| 81 | - 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 | |
| 82 | - 3.2.5. Compressed blocks (length and distance codes) ...... 11 | |
| 83 | - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 | |
| 84 | - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 | |
| 85 | - 3.3. Compliance ............................................... 14 | |
| 86 | - 4. Compression algorithm details ................................. 14 | |
| 87 | - 5. References .................................................... 16 | |
| 88 | - 6. Security Considerations ....................................... 16 | |
| 89 | - 7. Source code ................................................... 16 | |
| 90 | - 8. Acknowledgements .............................................. 16 | |
| 91 | - 9. Author's Address .............................................. 17 | |
| 92 | - | |
| 93 | -1. Introduction | |
| 94 | - | |
| 95 | - 1.1. Purpose | |
| 96 | - | |
| 97 | - The purpose of this specification is to define a lossless | |
| 98 | - compressed data format that: | |
| 99 | - * Is independent of CPU type, operating system, file system, | |
| 100 | - and character set, and hence can be used for interchange; | |
| 101 | - * Can be produced or consumed, even for an arbitrarily long | |
| 102 | - sequentially presented input data stream, using only an a | |
| 103 | - priori bounded amount of intermediate storage, and hence | |
| 104 | - can be used in data communications or similar structures | |
| 105 | - such as Unix filters; | |
| 106 | - * Compresses data with efficiency comparable to the best | |
| 107 | - currently available general-purpose compression methods, | |
| 108 | - and in particular considerably better than the "compress" | |
| 109 | - program; | |
| 110 | - * Can be implemented readily in a manner not covered by | |
| 111 | - patents, and hence can be practiced freely; | |
| 112 | - | |
| 113 | - | |
| 114 | - | |
| 115 | -Deutsch Informational [Page 2] | |
| 116 | - | |
| 117 | - | |
| 118 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 119 | - | |
| 120 | - | |
| 121 | - * Is compatible with the file format produced by the current | |
| 122 | - widely used gzip utility, in that conforming decompressors | |
| 123 | - will be able to read data produced by the existing gzip | |
| 124 | - compressor. | |
| 125 | - | |
| 126 | - The data format defined by this specification does not attempt to: | |
| 127 | - | |
| 128 | - * Allow random access to compressed data; | |
| 129 | - * Compress specialized data (e.g., raster graphics) as well | |
| 130 | - as the best currently available specialized algorithms. | |
| 131 | - | |
| 132 | - A simple counting argument shows that no lossless compression | |
| 133 | - algorithm can compress every possible input data set. For the | |
| 134 | - format defined here, the worst case expansion is 5 bytes per 32K- | |
| 135 | - byte block, i.e., a size increase of 0.015% for large data sets. | |
| 136 | - English text usually compresses by a factor of 2.5 to 3; | |
| 137 | - executable files usually compress somewhat less; graphical data | |
| 138 | - such as raster images may compress much more. | |
| 139 | - | |
| 140 | - 1.2. Intended audience | |
| 141 | - | |
| 142 | - This specification is intended for use by implementors of software | |
| 143 | - to compress data into "deflate" format and/or decompress data from | |
| 144 | - "deflate" format. | |
| 145 | - | |
| 146 | - The text of the specification assumes a basic background in | |
| 147 | - programming at the level of bits and other primitive data | |
| 148 | - representations. Familiarity with the technique of Huffman coding | |
| 149 | - is helpful but not required. | |
| 150 | - | |
| 151 | - 1.3. Scope | |
| 152 | - | |
| 153 | - The specification specifies a method for representing a sequence | |
| 154 | - of bytes as a (usually shorter) sequence of bits, and a method for | |
| 155 | - packing the latter bit sequence into bytes. | |
| 156 | - | |
| 157 | - 1.4. Compliance | |
| 158 | - | |
| 159 | - Unless otherwise indicated below, a compliant decompressor must be | |
| 160 | - able to accept and decompress any data set that conforms to all | |
| 161 | - the specifications presented here; a compliant compressor must | |
| 162 | - produce data sets that conform to all the specifications presented | |
| 163 | - here. | |
| 164 | - | |
| 165 | - 1.5. Definitions of terms and conventions used | |
| 166 | - | |
| 167 | - Byte: 8 bits stored or transmitted as a unit (same as an octet). | |
| 168 | - For this specification, a byte is exactly 8 bits, even on machines | |
| 169 | - | |
| 170 | - | |
| 171 | - | |
| 172 | -Deutsch Informational [Page 3] | |
| 173 | - | |
| 174 | - | |
| 175 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 176 | - | |
| 177 | - | |
| 178 | - which store a character on a number of bits different from eight. | |
| 179 | - See below, for the numbering of bits within a byte. | |
| 180 | - | |
| 181 | - String: a sequence of arbitrary bytes. | |
| 182 | - | |
| 183 | - 1.6. Changes from previous versions | |
| 184 | - | |
| 185 | - There have been no technical changes to the deflate format since | |
| 186 | - version 1.1 of this specification. In version 1.2, some | |
| 187 | - terminology was changed. Version 1.3 is a conversion of the | |
| 188 | - specification to RFC style. | |
| 189 | - | |
| 190 | -2. Compressed representation overview | |
| 191 | - | |
| 192 | - A compressed data set consists of a series of blocks, corresponding | |
| 193 | - to successive blocks of input data. The block sizes are arbitrary, | |
| 194 | - except that non-compressible blocks are limited to 65,535 bytes. | |
| 195 | - | |
| 196 | - Each block is compressed using a combination of the LZ77 algorithm | |
| 197 | - and Huffman coding. The Huffman trees for each block are independent | |
| 198 | - of those for previous or subsequent blocks; the LZ77 algorithm may | |
| 199 | - use a reference to a duplicated string occurring in a previous block, | |
| 200 | - up to 32K input bytes before. | |
| 201 | - | |
| 202 | - Each block consists of two parts: a pair of Huffman code trees that | |
| 203 | - describe the representation of the compressed data part, and a | |
| 204 | - compressed data part. (The Huffman trees themselves are compressed | |
| 205 | - using Huffman encoding.) The compressed data consists of a series of | |
| 206 | - elements of two types: literal bytes (of strings that have not been | |
| 207 | - detected as duplicated within the previous 32K input bytes), and | |
| 208 | - pointers to duplicated strings, where a pointer is represented as a | |
| 209 | - pair <length, backward distance>. The representation used in the | |
| 210 | - "deflate" format limits distances to 32K bytes and lengths to 258 | |
| 211 | - bytes, but does not limit the size of a block, except for | |
| 212 | - uncompressible blocks, which are limited as noted above. | |
| 213 | - | |
| 214 | - Each type of value (literals, distances, and lengths) in the | |
| 215 | - compressed data is represented using a Huffman code, using one code | |
| 216 | - tree for literals and lengths and a separate code tree for distances. | |
| 217 | - The code trees for each block appear in a compact form just before | |
| 218 | - the compressed data for that block. | |
| 219 | - | |
| 220 | - | |
| 221 | - | |
| 222 | - | |
| 223 | - | |
| 224 | - | |
| 225 | - | |
| 226 | - | |
| 227 | - | |
| 228 | - | |
| 229 | -Deutsch Informational [Page 4] | |
| 230 | - | |
| 231 | - | |
| 232 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 233 | - | |
| 234 | - | |
| 235 | -3. Detailed specification | |
| 236 | - | |
| 237 | - 3.1. Overall conventions In the diagrams below, a box like this: | |
| 238 | - | |
| 239 | - +---+ | |
| 240 | - | | <-- the vertical bars might be missing | |
| 241 | - +---+ | |
| 242 | - | |
| 243 | - represents one byte; a box like this: | |
| 244 | - | |
| 245 | - +==============+ | |
| 246 | - | | | |
| 247 | - +==============+ | |
| 248 | - | |
| 249 | - represents a variable number of bytes. | |
| 250 | - | |
| 251 | - Bytes stored within a computer do not have a "bit order", since | |
| 252 | - they are always treated as a unit. However, a byte considered as | |
| 253 | - an integer between 0 and 255 does have a most- and least- | |
| 254 | - significant bit, and since we write numbers with the most- | |
| 255 | - significant digit on the left, we also write bytes with the most- | |
| 256 | - significant bit on the left. In the diagrams below, we number the | |
| 257 | - bits of a byte so that bit 0 is the least-significant bit, i.e., | |
| 258 | - the bits are numbered: | |
| 259 | - | |
| 260 | - +--------+ | |
| 261 | - |76543210| | |
| 262 | - +--------+ | |
| 263 | - | |
| 264 | - Within a computer, a number may occupy multiple bytes. All | |
| 265 | - multi-byte numbers in the format described here are stored with | |
| 266 | - the least-significant byte first (at the lower memory address). | |
| 267 | - For example, the decimal number 520 is stored as: | |
| 268 | - | |
| 269 | - 0 1 | |
| 270 | - +--------+--------+ | |
| 271 | - |00001000|00000010| | |
| 272 | - +--------+--------+ | |
| 273 | - ^ ^ | |
| 274 | - | | | |
| 275 | - | + more significant byte = 2 x 256 | |
| 276 | - + less significant byte = 8 | |
| 277 | - | |
| 278 | - 3.1.1. Packing into bytes | |
| 279 | - | |
| 280 | - This document does not address the issue of the order in which | |
| 281 | - bits of a byte are transmitted on a bit-sequential medium, | |
| 282 | - since the final data format described here is byte- rather than | |
| 283 | - | |
| 284 | - | |
| 285 | - | |
| 286 | -Deutsch Informational [Page 5] | |
| 287 | - | |
| 288 | - | |
| 289 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 290 | - | |
| 291 | - | |
| 292 | - bit-oriented. However, we describe the compressed block format | |
| 293 | - in below, as a sequence of data elements of various bit | |
| 294 | - lengths, not a sequence of bytes. We must therefore specify | |
| 295 | - how to pack these data elements into bytes to form the final | |
| 296 | - compressed byte sequence: | |
| 297 | - | |
| 298 | - * Data elements are packed into bytes in order of | |
| 299 | - increasing bit number within the byte, i.e., starting | |
| 300 | - with the least-significant bit of the byte. | |
| 301 | - * Data elements other than Huffman codes are packed | |
| 302 | - starting with the least-significant bit of the data | |
| 303 | - element. | |
| 304 | - * Huffman codes are packed starting with the most- | |
| 305 | - significant bit of the code. | |
| 306 | - | |
| 307 | - In other words, if one were to print out the compressed data as | |
| 308 | - a sequence of bytes, starting with the first byte at the | |
| 309 | - *right* margin and proceeding to the *left*, with the most- | |
| 310 | - significant bit of each byte on the left as usual, one would be | |
| 311 | - able to parse the result from right to left, with fixed-width | |
| 312 | - elements in the correct MSB-to-LSB order and Huffman codes in | |
| 313 | - bit-reversed order (i.e., with the first bit of the code in the | |
| 314 | - relative LSB position). | |
| 315 | - | |
| 316 | - 3.2. Compressed block format | |
| 317 | - | |
| 318 | - 3.2.1. Synopsis of prefix and Huffman coding | |
| 319 | - | |
| 320 | - Prefix coding represents symbols from an a priori known | |
| 321 | - alphabet by bit sequences (codes), one code for each symbol, in | |
| 322 | - a manner such that different symbols may be represented by bit | |
| 323 | - sequences of different lengths, but a parser can always parse | |
| 324 | - an encoded string unambiguously symbol-by-symbol. | |
| 325 | - | |
| 326 | - We define a prefix code in terms of a binary tree in which the | |
| 327 | - two edges descending from each non-leaf node are labeled 0 and | |
| 328 | - 1 and in which the leaf nodes correspond one-for-one with (are | |
| 329 | - labeled with) the symbols of the alphabet; then the code for a | |
| 330 | - symbol is the sequence of 0's and 1's on the edges leading from | |
| 331 | - the root to the leaf labeled with that symbol. For example: | |
| 332 | - | |
| 333 | - | |
| 334 | - | |
| 335 | - | |
| 336 | - | |
| 337 | - | |
| 338 | - | |
| 339 | - | |
| 340 | - | |
| 341 | - | |
| 342 | - | |
| 343 | -Deutsch Informational [Page 6] | |
| 344 | - | |
| 345 | - | |
| 346 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 347 | - | |
| 348 | - | |
| 349 | - /\ Symbol Code | |
| 350 | - 0 1 ------ ---- | |
| 351 | - / \ A 00 | |
| 352 | - /\ B B 1 | |
| 353 | - 0 1 C 011 | |
| 354 | - / \ D 010 | |
| 355 | - A /\ | |
| 356 | - 0 1 | |
| 357 | - / \ | |
| 358 | - D C | |
| 359 | - | |
| 360 | - A parser can decode the next symbol from an encoded input | |
| 361 | - stream by walking down the tree from the root, at each step | |
| 362 | - choosing the edge corresponding to the next input bit. | |
| 363 | - | |
| 364 | - Given an alphabet with known symbol frequencies, the Huffman | |
| 365 | - algorithm allows the construction of an optimal prefix code | |
| 366 | - (one which represents strings with those symbol frequencies | |
| 367 | - using the fewest bits of any possible prefix codes for that | |
| 368 | - alphabet). Such a code is called a Huffman code. (See | |
| 369 | - reference [1] in Chapter 5, references for additional | |
| 370 | - information on Huffman codes.) | |
| 371 | - | |
| 372 | - Note that in the "deflate" format, the Huffman codes for the | |
| 373 | - various alphabets must not exceed certain maximum code lengths. | |
| 374 | - This constraint complicates the algorithm for computing code | |
| 375 | - lengths from symbol frequencies. Again, see Chapter 5, | |
| 376 | - references for details. | |
| 377 | - | |
| 378 | - 3.2.2. Use of Huffman coding in the "deflate" format | |
| 379 | - | |
| 380 | - The Huffman codes used for each alphabet in the "deflate" | |
| 381 | - format have two additional rules: | |
| 382 | - | |
| 383 | - * All codes of a given bit length have lexicographically | |
| 384 | - consecutive values, in the same order as the symbols | |
| 385 | - they represent; | |
| 386 | - | |
| 387 | - * Shorter codes lexicographically precede longer codes. | |
| 388 | - | |
| 389 | - | |
| 390 | - | |
| 391 | - | |
| 392 | - | |
| 393 | - | |
| 394 | - | |
| 395 | - | |
| 396 | - | |
| 397 | - | |
| 398 | - | |
| 399 | - | |
| 400 | -Deutsch Informational [Page 7] | |
| 401 | - | |
| 402 | - | |
| 403 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 404 | - | |
| 405 | - | |
| 406 | - We could recode the example above to follow this rule as | |
| 407 | - follows, assuming that the order of the alphabet is ABCD: | |
| 408 | - | |
| 409 | - Symbol Code | |
| 410 | - ------ ---- | |
| 411 | - A 10 | |
| 412 | - B 0 | |
| 413 | - C 110 | |
| 414 | - D 111 | |
| 415 | - | |
| 416 | - I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are | |
| 417 | - lexicographically consecutive. | |
| 418 | - | |
| 419 | - Given this rule, we can define the Huffman code for an alphabet | |
| 420 | - just by giving the bit lengths of the codes for each symbol of | |
| 421 | - the alphabet in order; this is sufficient to determine the | |
| 422 | - actual codes. In our example, the code is completely defined | |
| 423 | - by the sequence of bit lengths (2, 1, 3, 3). The following | |
| 424 | - algorithm generates the codes as integers, intended to be read | |
| 425 | - from most- to least-significant bit. The code lengths are | |
| 426 | - initially in tree[I].Len; the codes are produced in | |
| 427 | - tree[I].Code. | |
| 428 | - | |
| 429 | - 1) Count the number of codes for each code length. Let | |
| 430 | - bl_count[N] be the number of codes of length N, N >= 1. | |
| 431 | - | |
| 432 | - 2) Find the numerical value of the smallest code for each | |
| 433 | - code length: | |
| 434 | - | |
| 435 | - code = 0; | |
| 436 | - bl_count[0] = 0; | |
| 437 | - for (bits = 1; bits <= MAX_BITS; bits++) { | |
| 438 | - code = (code + bl_count[bits-1]) << 1; | |
| 439 | - next_code[bits] = code; | |
| 440 | - } | |
| 441 | - | |
| 442 | - 3) Assign numerical values to all codes, using consecutive | |
| 443 | - values for all codes of the same length with the base | |
| 444 | - values determined at step 2. Codes that are never used | |
| 445 | - (which have a bit length of zero) must not be assigned a | |
| 446 | - value. | |
| 447 | - | |
| 448 | - for (n = 0; n <= max_code; n++) { | |
| 449 | - len = tree[n].Len; | |
| 450 | - if (len != 0) { | |
| 451 | - tree[n].Code = next_code[len]; | |
| 452 | - next_code[len]++; | |
| 453 | - } | |
| 454 | - | |
| 455 | - | |
| 456 | - | |
| 457 | -Deutsch Informational [Page 8] | |
| 458 | - | |
| 459 | - | |
| 460 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 461 | - | |
| 462 | - | |
| 463 | - } | |
| 464 | - | |
| 465 | - Example: | |
| 466 | - | |
| 467 | - Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, | |
| 468 | - 3, 2, 4, 4). After step 1, we have: | |
| 469 | - | |
| 470 | - N bl_count[N] | |
| 471 | - - ----------- | |
| 472 | - 2 1 | |
| 473 | - 3 5 | |
| 474 | - 4 2 | |
| 475 | - | |
| 476 | - Step 2 computes the following next_code values: | |
| 477 | - | |
| 478 | - N next_code[N] | |
| 479 | - - ------------ | |
| 480 | - 1 0 | |
| 481 | - 2 0 | |
| 482 | - 3 2 | |
| 483 | - 4 14 | |
| 484 | - | |
| 485 | - Step 3 produces the following code values: | |
| 486 | - | |
| 487 | - Symbol Length Code | |
| 488 | - ------ ------ ---- | |
| 489 | - A 3 010 | |
| 490 | - B 3 011 | |
| 491 | - C 3 100 | |
| 492 | - D 3 101 | |
| 493 | - E 3 110 | |
| 494 | - F 2 00 | |
| 495 | - G 4 1110 | |
| 496 | - H 4 1111 | |
| 497 | - | |
| 498 | - 3.2.3. Details of block format | |
| 499 | - | |
| 500 | - Each block of compressed data begins with 3 header bits | |
| 501 | - containing the following data: | |
| 502 | - | |
| 503 | - first bit BFINAL | |
| 504 | - next 2 bits BTYPE | |
| 505 | - | |
| 506 | - Note that the header bits do not necessarily begin on a byte | |
| 507 | - boundary, since a block does not necessarily occupy an integral | |
| 508 | - number of bytes. | |
| 509 | - | |
| 510 | - | |
| 511 | - | |
| 512 | - | |
| 513 | - | |
| 514 | -Deutsch Informational [Page 9] | |
| 515 | - | |
| 516 | - | |
| 517 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 518 | - | |
| 519 | - | |
| 520 | - BFINAL is set if and only if this is the last block of the data | |
| 521 | - set. | |
| 522 | - | |
| 523 | - BTYPE specifies how the data are compressed, as follows: | |
| 524 | - | |
| 525 | - 00 - no compression | |
| 526 | - 01 - compressed with fixed Huffman codes | |
| 527 | - 10 - compressed with dynamic Huffman codes | |
| 528 | - 11 - reserved (error) | |
| 529 | - | |
| 530 | - The only difference between the two compressed cases is how the | |
| 531 | - Huffman codes for the literal/length and distance alphabets are | |
| 532 | - defined. | |
| 533 | - | |
| 534 | - In all cases, the decoding algorithm for the actual data is as | |
| 535 | - follows: | |
| 536 | - | |
| 537 | - do | |
| 538 | - read block header from input stream. | |
| 539 | - if stored with no compression | |
| 540 | - skip any remaining bits in current partially | |
| 541 | - processed byte | |
| 542 | - read LEN and NLEN (see next section) | |
| 543 | - copy LEN bytes of data to output | |
| 544 | - otherwise | |
| 545 | - if compressed with dynamic Huffman codes | |
| 546 | - read representation of code trees (see | |
| 547 | - subsection below) | |
| 548 | - loop (until end of block code recognized) | |
| 549 | - decode literal/length value from input stream | |
| 550 | - if value < 256 | |
| 551 | - copy value (literal byte) to output stream | |
| 552 | - otherwise | |
| 553 | - if value = end of block (256) | |
| 554 | - break from loop | |
| 555 | - otherwise (value = 257..285) | |
| 556 | - decode distance from input stream | |
| 557 | - | |
| 558 | - move backwards distance bytes in the output | |
| 559 | - stream, and copy length bytes from this | |
| 560 | - position to the output stream. | |
| 561 | - end loop | |
| 562 | - while not last block | |
| 563 | - | |
| 564 | - Note that a duplicated string reference may refer to a string | |
| 565 | - in a previous block; i.e., the backward distance may cross one | |
| 566 | - or more block boundaries. However a distance cannot refer past | |
| 567 | - the beginning of the output stream. (An application using a | |
| 568 | - | |
| 569 | - | |
| 570 | - | |
| 571 | -Deutsch Informational [Page 10] | |
| 572 | - | |
| 573 | - | |
| 574 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 575 | - | |
| 576 | - | |
| 577 | - preset dictionary might discard part of the output stream; a | |
| 578 | - distance can refer to that part of the output stream anyway) | |
| 579 | - Note also that the referenced string may overlap the current | |
| 580 | - position; for example, if the last 2 bytes decoded have values | |
| 581 | - X and Y, a string reference with <length = 5, distance = 2> | |
| 582 | - adds X,Y,X,Y,X to the output stream. | |
| 583 | - | |
| 584 | - We now specify each compression method in turn. | |
| 585 | - | |
| 586 | - 3.2.4. Non-compressed blocks (BTYPE=00) | |
| 587 | - | |
| 588 | - Any bits of input up to the next byte boundary are ignored. | |
| 589 | - The rest of the block consists of the following information: | |
| 590 | - | |
| 591 | - 0 1 2 3 4... | |
| 592 | - +---+---+---+---+================================+ | |
| 593 | - | LEN | NLEN |... LEN bytes of literal data...| | |
| 594 | - +---+---+---+---+================================+ | |
| 595 | - | |
| 596 | - LEN is the number of data bytes in the block. NLEN is the | |
| 597 | - one's complement of LEN. | |
| 598 | - | |
| 599 | - 3.2.5. Compressed blocks (length and distance codes) | |
| 600 | - | |
| 601 | - As noted above, encoded data blocks in the "deflate" format | |
| 602 | - consist of sequences of symbols drawn from three conceptually | |
| 603 | - distinct alphabets: either literal bytes, from the alphabet of | |
| 604 | - byte values (0..255), or <length, backward distance> pairs, | |
| 605 | - where the length is drawn from (3..258) and the distance is | |
| 606 | - drawn from (1..32,768). In fact, the literal and length | |
| 607 | - alphabets are merged into a single alphabet (0..285), where | |
| 608 | - values 0..255 represent literal bytes, the value 256 indicates | |
| 609 | - end-of-block, and values 257..285 represent length codes | |
| 610 | - (possibly in conjunction with extra bits following the symbol | |
| 611 | - code) as follows: | |
| 612 | - | |
| 613 | - | |
| 614 | - | |
| 615 | - | |
| 616 | - | |
| 617 | - | |
| 618 | - | |
| 619 | - | |
| 620 | - | |
| 621 | - | |
| 622 | - | |
| 623 | - | |
| 624 | - | |
| 625 | - | |
| 626 | - | |
| 627 | - | |
| 628 | -Deutsch Informational [Page 11] | |
| 629 | - | |
| 630 | - | |
| 631 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 632 | - | |
| 633 | - | |
| 634 | - Extra Extra Extra | |
| 635 | - Code Bits Length(s) Code Bits Lengths Code Bits Length(s) | |
| 636 | - ---- ---- ------ ---- ---- ------- ---- ---- ------- | |
| 637 | - 257 0 3 267 1 15,16 277 4 67-82 | |
| 638 | - 258 0 4 268 1 17,18 278 4 83-98 | |
| 639 | - 259 0 5 269 2 19-22 279 4 99-114 | |
| 640 | - 260 0 6 270 2 23-26 280 4 115-130 | |
| 641 | - 261 0 7 271 2 27-30 281 5 131-162 | |
| 642 | - 262 0 8 272 2 31-34 282 5 163-194 | |
| 643 | - 263 0 9 273 3 35-42 283 5 195-226 | |
| 644 | - 264 0 10 274 3 43-50 284 5 227-257 | |
| 645 | - 265 1 11,12 275 3 51-58 285 0 258 | |
| 646 | - 266 1 13,14 276 3 59-66 | |
| 647 | - | |
| 648 | - The extra bits should be interpreted as a machine integer | |
| 649 | - stored with the most-significant bit first, e.g., bits 1110 | |
| 650 | - represent the value 14. | |
| 651 | - | |
| 652 | - Extra Extra Extra | |
| 653 | - Code Bits Dist Code Bits Dist Code Bits Distance | |
| 654 | - ---- ---- ---- ---- ---- ------ ---- ---- -------- | |
| 655 | - 0 0 1 10 4 33-48 20 9 1025-1536 | |
| 656 | - 1 0 2 11 4 49-64 21 9 1537-2048 | |
| 657 | - 2 0 3 12 5 65-96 22 10 2049-3072 | |
| 658 | - 3 0 4 13 5 97-128 23 10 3073-4096 | |
| 659 | - 4 1 5,6 14 6 129-192 24 11 4097-6144 | |
| 660 | - 5 1 7,8 15 6 193-256 25 11 6145-8192 | |
| 661 | - 6 2 9-12 16 7 257-384 26 12 8193-12288 | |
| 662 | - 7 2 13-16 17 7 385-512 27 12 12289-16384 | |
| 663 | - 8 3 17-24 18 8 513-768 28 13 16385-24576 | |
| 664 | - 9 3 25-32 19 8 769-1024 29 13 24577-32768 | |
| 665 | - | |
| 666 | - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) | |
| 667 | - | |
| 668 | - The Huffman codes for the two alphabets are fixed, and are not | |
| 669 | - represented explicitly in the data. The Huffman code lengths | |
| 670 | - for the literal/length alphabet are: | |
| 671 | - | |
| 672 | - Lit Value Bits Codes | |
| 673 | - --------- ---- ----- | |
| 674 | - 0 - 143 8 00110000 through | |
| 675 | - 10111111 | |
| 676 | - 144 - 255 9 110010000 through | |
| 677 | - 111111111 | |
| 678 | - 256 - 279 7 0000000 through | |
| 679 | - 0010111 | |
| 680 | - 280 - 287 8 11000000 through | |
| 681 | - 11000111 | |
| 682 | - | |
| 683 | - | |
| 684 | - | |
| 685 | -Deutsch Informational [Page 12] | |
| 686 | - | |
| 687 | - | |
| 688 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 689 | - | |
| 690 | - | |
| 691 | - The code lengths are sufficient to generate the actual codes, | |
| 692 | - as described above; we show the codes in the table for added | |
| 693 | - clarity. Literal/length values 286-287 will never actually | |
| 694 | - occur in the compressed data, but participate in the code | |
| 695 | - construction. | |
| 696 | - | |
| 697 | - Distance codes 0-31 are represented by (fixed-length) 5-bit | |
| 698 | - codes, with possible additional bits as shown in the table | |
| 699 | - shown in Paragraph 3.2.5, above. Note that distance codes 30- | |
| 700 | - 31 will never actually occur in the compressed data. | |
| 701 | - | |
| 702 | - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) | |
| 703 | - | |
| 704 | - The Huffman codes for the two alphabets appear in the block | |
| 705 | - immediately after the header bits and before the actual | |
| 706 | - compressed data, first the literal/length code and then the | |
| 707 | - distance code. Each code is defined by a sequence of code | |
| 708 | - lengths, as discussed in Paragraph 3.2.2, above. For even | |
| 709 | - greater compactness, the code length sequences themselves are | |
| 710 | - compressed using a Huffman code. The alphabet for code lengths | |
| 711 | - is as follows: | |
| 712 | - | |
| 713 | - 0 - 15: Represent code lengths of 0 - 15 | |
| 714 | - 16: Copy the previous code length 3 - 6 times. | |
| 715 | - The next 2 bits indicate repeat length | |
| 716 | - (0 = 3, ... , 3 = 6) | |
| 717 | - Example: Codes 8, 16 (+2 bits 11), | |
| 718 | - 16 (+2 bits 10) will expand to | |
| 719 | - 12 code lengths of 8 (1 + 6 + 5) | |
| 720 | - 17: Repeat a code length of 0 for 3 - 10 times. | |
| 721 | - (3 bits of length) | |
| 722 | - 18: Repeat a code length of 0 for 11 - 138 times | |
| 723 | - (7 bits of length) | |
| 724 | - | |
| 725 | - A code length of 0 indicates that the corresponding symbol in | |
| 726 | - the literal/length or distance alphabet will not occur in the | |
| 727 | - block, and should not participate in the Huffman code | |
| 728 | - construction algorithm given earlier. If only one distance | |
| 729 | - code is used, it is encoded using one bit, not zero bits; in | |
| 730 | - this case there is a single code length of one, with one unused | |
| 731 | - code. One distance code of zero bits means that there are no | |
| 732 | - distance codes used at all (the data is all literals). | |
| 733 | - | |
| 734 | - We can now define the format of the block: | |
| 735 | - | |
| 736 | - 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) | |
| 737 | - 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) | |
| 738 | - 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) | |
| 739 | - | |
| 740 | - | |
| 741 | - | |
| 742 | -Deutsch Informational [Page 13] | |
| 743 | - | |
| 744 | - | |
| 745 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 746 | - | |
| 747 | - | |
| 748 | - (HCLEN + 4) x 3 bits: code lengths for the code length | |
| 749 | - alphabet given just above, in the order: 16, 17, 18, | |
| 750 | - 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 | |
| 751 | - | |
| 752 | - These code lengths are interpreted as 3-bit integers | |
| 753 | - (0-7); as above, a code length of 0 means the | |
| 754 | - corresponding symbol (literal/length or distance code | |
| 755 | - length) is not used. | |
| 756 | - | |
| 757 | - HLIT + 257 code lengths for the literal/length alphabet, | |
| 758 | - encoded using the code length Huffman code | |
| 759 | - | |
| 760 | - HDIST + 1 code lengths for the distance alphabet, | |
| 761 | - encoded using the code length Huffman code | |
| 762 | - | |
| 763 | - The actual compressed data of the block, | |
| 764 | - encoded using the literal/length and distance Huffman | |
| 765 | - codes | |
| 766 | - | |
| 767 | - The literal/length symbol 256 (end of data), | |
| 768 | - encoded using the literal/length Huffman code | |
| 769 | - | |
| 770 | - The code length repeat codes can cross from HLIT + 257 to the | |
| 771 | - HDIST + 1 code lengths. In other words, all code lengths form | |
| 772 | - a single sequence of HLIT + HDIST + 258 values. | |
| 773 | - | |
| 774 | - 3.3. Compliance | |
| 775 | - | |
| 776 | - A compressor may limit further the ranges of values specified in | |
| 777 | - the previous section and still be compliant; for example, it may | |
| 778 | - limit the range of backward pointers to some value smaller than | |
| 779 | - 32K. Similarly, a compressor may limit the size of blocks so that | |
| 780 | - a compressible block fits in memory. | |
| 781 | - | |
| 782 | - A compliant decompressor must accept the full range of possible | |
| 783 | - values defined in the previous section, and must accept blocks of | |
| 784 | - arbitrary size. | |
| 785 | - | |
| 786 | -4. Compression algorithm details | |
| 787 | - | |
| 788 | - While it is the intent of this document to define the "deflate" | |
| 789 | - compressed data format without reference to any particular | |
| 790 | - compression algorithm, the format is related to the compressed | |
| 791 | - formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); | |
| 792 | - since many variations of LZ77 are patented, it is strongly | |
| 793 | - recommended that the implementor of a compressor follow the general | |
| 794 | - algorithm presented here, which is known not to be patented per se. | |
| 795 | - The material in this section is not part of the definition of the | |
| 796 | - | |
| 797 | - | |
| 798 | - | |
| 799 | -Deutsch Informational [Page 14] | |
| 800 | - | |
| 801 | - | |
| 802 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 803 | - | |
| 804 | - | |
| 805 | - specification per se, and a compressor need not follow it in order to | |
| 806 | - be compliant. | |
| 807 | - | |
| 808 | - The compressor terminates a block when it determines that starting a | |
| 809 | - new block with fresh trees would be useful, or when the block size | |
| 810 | - fills up the compressor's block buffer. | |
| 811 | - | |
| 812 | - The compressor uses a chained hash table to find duplicated strings, | |
| 813 | - using a hash function that operates on 3-byte sequences. At any | |
| 814 | - given point during compression, let XYZ be the next 3 input bytes to | |
| 815 | - be examined (not necessarily all different, of course). First, the | |
| 816 | - compressor examines the hash chain for XYZ. If the chain is empty, | |
| 817 | - the compressor simply writes out X as a literal byte and advances one | |
| 818 | - byte in the input. If the hash chain is not empty, indicating that | |
| 819 | - the sequence XYZ (or, if we are unlucky, some other 3 bytes with the | |
| 820 | - same hash function value) has occurred recently, the compressor | |
| 821 | - compares all strings on the XYZ hash chain with the actual input data | |
| 822 | - sequence starting at the current point, and selects the longest | |
| 823 | - match. | |
| 824 | - | |
| 825 | - The compressor searches the hash chains starting with the most recent | |
| 826 | - strings, to favor small distances and thus take advantage of the | |
| 827 | - Huffman encoding. The hash chains are singly linked. There are no | |
| 828 | - deletions from the hash chains; the algorithm simply discards matches | |
| 829 | - that are too old. To avoid a worst-case situation, very long hash | |
| 830 | - chains are arbitrarily truncated at a certain length, determined by a | |
| 831 | - run-time parameter. | |
| 832 | - | |
| 833 | - To improve overall compression, the compressor optionally defers the | |
| 834 | - selection of matches ("lazy matching"): after a match of length N has | |
| 835 | - been found, the compressor searches for a longer match starting at | |
| 836 | - the next input byte. If it finds a longer match, it truncates the | |
| 837 | - previous match to a length of one (thus producing a single literal | |
| 838 | - byte) and then emits the longer match. Otherwise, it emits the | |
| 839 | - original match, and, as described above, advances N bytes before | |
| 840 | - continuing. | |
| 841 | - | |
| 842 | - Run-time parameters also control this "lazy match" procedure. If | |
| 843 | - compression ratio is most important, the compressor attempts a | |
| 844 | - complete second search regardless of the length of the first match. | |
| 845 | - In the normal case, if the current match is "long enough", the | |
| 846 | - compressor reduces the search for a longer match, thus speeding up | |
| 847 | - the process. If speed is most important, the compressor inserts new | |
| 848 | - strings in the hash table only when no match was found, or when the | |
| 849 | - match is not "too long". This degrades the compression ratio but | |
| 850 | - saves time since there are both fewer insertions and fewer searches. | |
| 851 | - | |
| 852 | - | |
| 853 | - | |
| 854 | - | |
| 855 | - | |
| 856 | -Deutsch Informational [Page 15] | |
| 857 | - | |
| 858 | - | |
| 859 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 860 | - | |
| 861 | - | |
| 862 | -5. References | |
| 863 | - | |
| 864 | - [1] Huffman, D. A., "A Method for the Construction of Minimum | |
| 865 | - Redundancy Codes", Proceedings of the Institute of Radio | |
| 866 | - Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. | |
| 867 | - | |
| 868 | - [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data | |
| 869 | - Compression", IEEE Transactions on Information Theory, Vol. 23, | |
| 870 | - No. 3, pp. 337-343. | |
| 871 | - | |
| 872 | - [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, | |
| 873 | - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ | |
| 874 | - | |
| 875 | - [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, | |
| 876 | - available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ | |
| 877 | - | |
| 878 | - [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix | |
| 879 | - encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. | |
| 880 | - | |
| 881 | - [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," | |
| 882 | - Comm. ACM, 33,4, April 1990, pp. 449-459. | |
| 883 | - | |
| 884 | -6. Security Considerations | |
| 885 | - | |
| 886 | - Any data compression method involves the reduction of redundancy in | |
| 887 | - the data. Consequently, any corruption of the data is likely to have | |
| 888 | - severe effects and be difficult to correct. Uncompressed text, on | |
| 889 | - the other hand, will probably still be readable despite the presence | |
| 890 | - of some corrupted bytes. | |
| 891 | - | |
| 892 | - It is recommended that systems using this data format provide some | |
| 893 | - means of validating the integrity of the compressed data. See | |
| 894 | - reference [3], for example. | |
| 895 | - | |
| 896 | -7. Source code | |
| 897 | - | |
| 898 | - Source code for a C language implementation of a "deflate" compliant | |
| 899 | - compressor and decompressor is available within the zlib package at | |
| 900 | - ftp://ftp.uu.net/pub/archiving/zip/zlib/. | |
| 901 | - | |
| 902 | -8. Acknowledgements | |
| 903 | - | |
| 904 | - Trademarks cited in this document are the property of their | |
| 905 | - respective owners. | |
| 906 | - | |
| 907 | - Phil Katz designed the deflate format. Jean-Loup Gailly and Mark | |
| 908 | - Adler wrote the related software described in this specification. | |
| 909 | - Glenn Randers-Pehrson converted this document to RFC and HTML format. | |
| 910 | - | |
| 911 | - | |
| 912 | - | |
| 913 | -Deutsch Informational [Page 16] | |
| 914 | - | |
| 915 | - | |
| 916 | -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 | |
| 917 | - | |
| 918 | - | |
| 919 | -9. Author's Address | |
| 920 | - | |
| 921 | - L. Peter Deutsch | |
| 922 | - Aladdin Enterprises | |
| 923 | - 203 Santa Margarita Ave. | |
| 924 | - Menlo Park, CA 94025 | |
| 925 | - | |
| 926 | - Phone: (415) 322-0103 (AM only) | |
| 927 | - FAX: (415) 322-1734 | |
| 928 | - EMail: <[email protected]> | |
| 929 | - | |
| 930 | - Questions about the technical content of this specification can be | |
| 931 | - sent by email to: | |
| 932 | - | |
| 933 | - Jean-Loup Gailly <[email protected]> and | |
| 934 | - Mark Adler <[email protected]> | |
| 935 | - | |
| 936 | - Editorial comments on this specification can be sent by email to: | |
| 937 | - | |
| 938 | - L. Peter Deutsch <[email protected]> and | |
| 939 | - Glenn Randers-Pehrson <[email protected]> | |
| 940 | - | |
| 941 | - | |
| 942 | - | |
| 943 | - | |
| 944 | - | |
| 945 | - | |
| 946 | - | |
| 947 | - | |
| 948 | - | |
| 949 | - | |
| 950 | - | |
| 951 | - | |
| 952 | - | |
| 953 | - | |
| 954 | - | |
| 955 | - | |
| 956 | - | |
| 957 | - | |
| 958 | - | |
| 959 | - | |
| 960 | - | |
| 961 | - | |
| 962 | - | |
| 963 | - | |
| 964 | - | |
| 965 | - | |
| 966 | - | |
| 967 | - | |
| 968 | - | |
| 969 | - | |
| 970 | -Deutsch Informational [Page 17] | |
| 971 | - | |
| 972 | - |
| --- a/compat/zlib/doc/rfc1951.txt | |
| +++ b/compat/zlib/doc/rfc1951.txt | |
| @@ -1,972 +0,0 @@ | |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | Network Working Group P. Deutsch |
| 8 | Request for Comments: 1951 Aladdin Enterprises |
| 9 | Category: Informational May 1996 |
| 10 | |
| 11 | |
| 12 | DEFLATE Compressed Data Format Specification version 1.3 |
| 13 | |
| 14 | Status of This Memo |
| 15 | |
| 16 | This memo provides information for the Internet community. This memo |
| 17 | does not specify an Internet standard of any kind. Distribution of |
| 18 | this memo is unlimited. |
| 19 | |
| 20 | IESG Note: |
| 21 | |
| 22 | The IESG takes no position on the validity of any Intellectual |
| 23 | Property Rights statements contained in this document. |
| 24 | |
| 25 | Notices |
| 26 | |
| 27 | Copyright (c) 1996 L. Peter Deutsch |
| 28 | |
| 29 | Permission is granted to copy and distribute this document for any |
| 30 | purpose and without charge, including translations into other |
| 31 | languages and incorporation into compilations, provided that the |
| 32 | copyright notice and this notice are preserved, and that any |
| 33 | substantive changes or deletions from the original are clearly |
| 34 | marked. |
| 35 | |
| 36 | A pointer to the latest version of this and related documentation in |
| 37 | HTML format can be found at the URL |
| 38 | <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>. |
| 39 | |
| 40 | Abstract |
| 41 | |
| 42 | This specification defines a lossless compressed data format that |
| 43 | compresses data using a combination of the LZ77 algorithm and Huffman |
| 44 | coding, with efficiency comparable to the best currently available |
| 45 | general-purpose compression methods. The data can be produced or |
| 46 | consumed, even for an arbitrarily long sequentially presented input |
| 47 | data stream, using only an a priori bounded amount of intermediate |
| 48 | storage. The format can be implemented readily in a manner not |
| 49 | covered by patents. |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | Deutsch Informational [Page 1] |
| 59 | |
| 60 | |
| 61 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 62 | |
| 63 | |
| 64 | Table of Contents |
| 65 | |
| 66 | 1. Introduction ................................................... 2 |
| 67 | 1.1. Purpose ................................................... 2 |
| 68 | 1.2. Intended audience ......................................... 3 |
| 69 | 1.3. Scope ..................................................... 3 |
| 70 | 1.4. Compliance ................................................ 3 |
| 71 | 1.5. Definitions of terms and conventions used ................ 3 |
| 72 | 1.6. Changes from previous versions ............................ 4 |
| 73 | 2. Compressed representation overview ............................. 4 |
| 74 | 3. Detailed specification ......................................... 5 |
| 75 | 3.1. Overall conventions ....................................... 5 |
| 76 | 3.1.1. Packing into bytes .................................. 5 |
| 77 | 3.2. Compressed block format ................................... 6 |
| 78 | 3.2.1. Synopsis of prefix and Huffman coding ............... 6 |
| 79 | 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 |
| 80 | 3.2.3. Details of block format ............................. 9 |
| 81 | 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 |
| 82 | 3.2.5. Compressed blocks (length and distance codes) ...... 11 |
| 83 | 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 |
| 84 | 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 |
| 85 | 3.3. Compliance ............................................... 14 |
| 86 | 4. Compression algorithm details ................................. 14 |
| 87 | 5. References .................................................... 16 |
| 88 | 6. Security Considerations ....................................... 16 |
| 89 | 7. Source code ................................................... 16 |
| 90 | 8. Acknowledgements .............................................. 16 |
| 91 | 9. Author's Address .............................................. 17 |
| 92 | |
| 93 | 1. Introduction |
| 94 | |
| 95 | 1.1. Purpose |
| 96 | |
| 97 | The purpose of this specification is to define a lossless |
| 98 | compressed data format that: |
| 99 | * Is independent of CPU type, operating system, file system, |
| 100 | and character set, and hence can be used for interchange; |
| 101 | * Can be produced or consumed, even for an arbitrarily long |
| 102 | sequentially presented input data stream, using only an a |
| 103 | priori bounded amount of intermediate storage, and hence |
| 104 | can be used in data communications or similar structures |
| 105 | such as Unix filters; |
| 106 | * Compresses data with efficiency comparable to the best |
| 107 | currently available general-purpose compression methods, |
| 108 | and in particular considerably better than the "compress" |
| 109 | program; |
| 110 | * Can be implemented readily in a manner not covered by |
| 111 | patents, and hence can be practiced freely; |
| 112 | |
| 113 | |
| 114 | |
| 115 | Deutsch Informational [Page 2] |
| 116 | |
| 117 | |
| 118 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 119 | |
| 120 | |
| 121 | * Is compatible with the file format produced by the current |
| 122 | widely used gzip utility, in that conforming decompressors |
| 123 | will be able to read data produced by the existing gzip |
| 124 | compressor. |
| 125 | |
| 126 | The data format defined by this specification does not attempt to: |
| 127 | |
| 128 | * Allow random access to compressed data; |
| 129 | * Compress specialized data (e.g., raster graphics) as well |
| 130 | as the best currently available specialized algorithms. |
| 131 | |
| 132 | A simple counting argument shows that no lossless compression |
| 133 | algorithm can compress every possible input data set. For the |
| 134 | format defined here, the worst case expansion is 5 bytes per 32K- |
| 135 | byte block, i.e., a size increase of 0.015% for large data sets. |
| 136 | English text usually compresses by a factor of 2.5 to 3; |
| 137 | executable files usually compress somewhat less; graphical data |
| 138 | such as raster images may compress much more. |
| 139 | |
| 140 | 1.2. Intended audience |
| 141 | |
| 142 | This specification is intended for use by implementors of software |
| 143 | to compress data into "deflate" format and/or decompress data from |
| 144 | "deflate" format. |
| 145 | |
| 146 | The text of the specification assumes a basic background in |
| 147 | programming at the level of bits and other primitive data |
| 148 | representations. Familiarity with the technique of Huffman coding |
| 149 | is helpful but not required. |
| 150 | |
| 151 | 1.3. Scope |
| 152 | |
| 153 | The specification specifies a method for representing a sequence |
| 154 | of bytes as a (usually shorter) sequence of bits, and a method for |
| 155 | packing the latter bit sequence into bytes. |
| 156 | |
| 157 | 1.4. Compliance |
| 158 | |
| 159 | Unless otherwise indicated below, a compliant decompressor must be |
| 160 | able to accept and decompress any data set that conforms to all |
| 161 | the specifications presented here; a compliant compressor must |
| 162 | produce data sets that conform to all the specifications presented |
| 163 | here. |
| 164 | |
| 165 | 1.5. Definitions of terms and conventions used |
| 166 | |
| 167 | Byte: 8 bits stored or transmitted as a unit (same as an octet). |
| 168 | For this specification, a byte is exactly 8 bits, even on machines |
| 169 | |
| 170 | |
| 171 | |
| 172 | Deutsch Informational [Page 3] |
| 173 | |
| 174 | |
| 175 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 176 | |
| 177 | |
| 178 | which store a character on a number of bits different from eight. |
| 179 | See below, for the numbering of bits within a byte. |
| 180 | |
| 181 | String: a sequence of arbitrary bytes. |
| 182 | |
| 183 | 1.6. Changes from previous versions |
| 184 | |
| 185 | There have been no technical changes to the deflate format since |
| 186 | version 1.1 of this specification. In version 1.2, some |
| 187 | terminology was changed. Version 1.3 is a conversion of the |
| 188 | specification to RFC style. |
| 189 | |
| 190 | 2. Compressed representation overview |
| 191 | |
| 192 | A compressed data set consists of a series of blocks, corresponding |
| 193 | to successive blocks of input data. The block sizes are arbitrary, |
| 194 | except that non-compressible blocks are limited to 65,535 bytes. |
| 195 | |
| 196 | Each block is compressed using a combination of the LZ77 algorithm |
| 197 | and Huffman coding. The Huffman trees for each block are independent |
| 198 | of those for previous or subsequent blocks; the LZ77 algorithm may |
| 199 | use a reference to a duplicated string occurring in a previous block, |
| 200 | up to 32K input bytes before. |
| 201 | |
| 202 | Each block consists of two parts: a pair of Huffman code trees that |
| 203 | describe the representation of the compressed data part, and a |
| 204 | compressed data part. (The Huffman trees themselves are compressed |
| 205 | using Huffman encoding.) The compressed data consists of a series of |
| 206 | elements of two types: literal bytes (of strings that have not been |
| 207 | detected as duplicated within the previous 32K input bytes), and |
| 208 | pointers to duplicated strings, where a pointer is represented as a |
| 209 | pair <length, backward distance>. The representation used in the |
| 210 | "deflate" format limits distances to 32K bytes and lengths to 258 |
| 211 | bytes, but does not limit the size of a block, except for |
| 212 | uncompressible blocks, which are limited as noted above. |
| 213 | |
| 214 | Each type of value (literals, distances, and lengths) in the |
| 215 | compressed data is represented using a Huffman code, using one code |
| 216 | tree for literals and lengths and a separate code tree for distances. |
| 217 | The code trees for each block appear in a compact form just before |
| 218 | the compressed data for that block. |
| 219 | |
| 220 | |
| 221 | |
| 222 | |
| 223 | |
| 224 | |
| 225 | |
| 226 | |
| 227 | |
| 228 | |
| 229 | Deutsch Informational [Page 4] |
| 230 | |
| 231 | |
| 232 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 233 | |
| 234 | |
| 235 | 3. Detailed specification |
| 236 | |
| 237 | 3.1. Overall conventions In the diagrams below, a box like this: |
| 238 | |
| 239 | +---+ |
| 240 | | | <-- the vertical bars might be missing |
| 241 | +---+ |
| 242 | |
| 243 | represents one byte; a box like this: |
| 244 | |
| 245 | +==============+ |
| 246 | | | |
| 247 | +==============+ |
| 248 | |
| 249 | represents a variable number of bytes. |
| 250 | |
| 251 | Bytes stored within a computer do not have a "bit order", since |
| 252 | they are always treated as a unit. However, a byte considered as |
| 253 | an integer between 0 and 255 does have a most- and least- |
| 254 | significant bit, and since we write numbers with the most- |
| 255 | significant digit on the left, we also write bytes with the most- |
| 256 | significant bit on the left. In the diagrams below, we number the |
| 257 | bits of a byte so that bit 0 is the least-significant bit, i.e., |
| 258 | the bits are numbered: |
| 259 | |
| 260 | +--------+ |
| 261 | |76543210| |
| 262 | +--------+ |
| 263 | |
| 264 | Within a computer, a number may occupy multiple bytes. All |
| 265 | multi-byte numbers in the format described here are stored with |
| 266 | the least-significant byte first (at the lower memory address). |
| 267 | For example, the decimal number 520 is stored as: |
| 268 | |
| 269 | 0 1 |
| 270 | +--------+--------+ |
| 271 | |00001000|00000010| |
| 272 | +--------+--------+ |
| 273 | ^ ^ |
| 274 | | | |
| 275 | | + more significant byte = 2 x 256 |
| 276 | + less significant byte = 8 |
| 277 | |
| 278 | 3.1.1. Packing into bytes |
| 279 | |
| 280 | This document does not address the issue of the order in which |
| 281 | bits of a byte are transmitted on a bit-sequential medium, |
| 282 | since the final data format described here is byte- rather than |
| 283 | |
| 284 | |
| 285 | |
| 286 | Deutsch Informational [Page 5] |
| 287 | |
| 288 | |
| 289 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 290 | |
| 291 | |
| 292 | bit-oriented. However, we describe the compressed block format |
| 293 | in below, as a sequence of data elements of various bit |
| 294 | lengths, not a sequence of bytes. We must therefore specify |
| 295 | how to pack these data elements into bytes to form the final |
| 296 | compressed byte sequence: |
| 297 | |
| 298 | * Data elements are packed into bytes in order of |
| 299 | increasing bit number within the byte, i.e., starting |
| 300 | with the least-significant bit of the byte. |
| 301 | * Data elements other than Huffman codes are packed |
| 302 | starting with the least-significant bit of the data |
| 303 | element. |
| 304 | * Huffman codes are packed starting with the most- |
| 305 | significant bit of the code. |
| 306 | |
| 307 | In other words, if one were to print out the compressed data as |
| 308 | a sequence of bytes, starting with the first byte at the |
| 309 | *right* margin and proceeding to the *left*, with the most- |
| 310 | significant bit of each byte on the left as usual, one would be |
| 311 | able to parse the result from right to left, with fixed-width |
| 312 | elements in the correct MSB-to-LSB order and Huffman codes in |
| 313 | bit-reversed order (i.e., with the first bit of the code in the |
| 314 | relative LSB position). |
| 315 | |
| 316 | 3.2. Compressed block format |
| 317 | |
| 318 | 3.2.1. Synopsis of prefix and Huffman coding |
| 319 | |
| 320 | Prefix coding represents symbols from an a priori known |
| 321 | alphabet by bit sequences (codes), one code for each symbol, in |
| 322 | a manner such that different symbols may be represented by bit |
| 323 | sequences of different lengths, but a parser can always parse |
| 324 | an encoded string unambiguously symbol-by-symbol. |
| 325 | |
| 326 | We define a prefix code in terms of a binary tree in which the |
| 327 | two edges descending from each non-leaf node are labeled 0 and |
| 328 | 1 and in which the leaf nodes correspond one-for-one with (are |
| 329 | labeled with) the symbols of the alphabet; then the code for a |
| 330 | symbol is the sequence of 0's and 1's on the edges leading from |
| 331 | the root to the leaf labeled with that symbol. For example: |
| 332 | |
| 333 | |
| 334 | |
| 335 | |
| 336 | |
| 337 | |
| 338 | |
| 339 | |
| 340 | |
| 341 | |
| 342 | |
| 343 | Deutsch Informational [Page 6] |
| 344 | |
| 345 | |
| 346 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 347 | |
| 348 | |
| 349 | /\ Symbol Code |
| 350 | 0 1 ------ ---- |
| 351 | / \ A 00 |
| 352 | /\ B B 1 |
| 353 | 0 1 C 011 |
| 354 | / \ D 010 |
| 355 | A /\ |
| 356 | 0 1 |
| 357 | / \ |
| 358 | D C |
| 359 | |
| 360 | A parser can decode the next symbol from an encoded input |
| 361 | stream by walking down the tree from the root, at each step |
| 362 | choosing the edge corresponding to the next input bit. |
| 363 | |
| 364 | Given an alphabet with known symbol frequencies, the Huffman |
| 365 | algorithm allows the construction of an optimal prefix code |
| 366 | (one which represents strings with those symbol frequencies |
| 367 | using the fewest bits of any possible prefix codes for that |
| 368 | alphabet). Such a code is called a Huffman code. (See |
| 369 | reference [1] in Chapter 5, references for additional |
| 370 | information on Huffman codes.) |
| 371 | |
| 372 | Note that in the "deflate" format, the Huffman codes for the |
| 373 | various alphabets must not exceed certain maximum code lengths. |
| 374 | This constraint complicates the algorithm for computing code |
| 375 | lengths from symbol frequencies. Again, see Chapter 5, |
| 376 | references for details. |
| 377 | |
| 378 | 3.2.2. Use of Huffman coding in the "deflate" format |
| 379 | |
| 380 | The Huffman codes used for each alphabet in the "deflate" |
| 381 | format have two additional rules: |
| 382 | |
| 383 | * All codes of a given bit length have lexicographically |
| 384 | consecutive values, in the same order as the symbols |
| 385 | they represent; |
| 386 | |
| 387 | * Shorter codes lexicographically precede longer codes. |
| 388 | |
| 389 | |
| 390 | |
| 391 | |
| 392 | |
| 393 | |
| 394 | |
| 395 | |
| 396 | |
| 397 | |
| 398 | |
| 399 | |
| 400 | Deutsch Informational [Page 7] |
| 401 | |
| 402 | |
| 403 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 404 | |
| 405 | |
| 406 | We could recode the example above to follow this rule as |
| 407 | follows, assuming that the order of the alphabet is ABCD: |
| 408 | |
| 409 | Symbol Code |
| 410 | ------ ---- |
| 411 | A 10 |
| 412 | B 0 |
| 413 | C 110 |
| 414 | D 111 |
| 415 | |
| 416 | I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are |
| 417 | lexicographically consecutive. |
| 418 | |
| 419 | Given this rule, we can define the Huffman code for an alphabet |
| 420 | just by giving the bit lengths of the codes for each symbol of |
| 421 | the alphabet in order; this is sufficient to determine the |
| 422 | actual codes. In our example, the code is completely defined |
| 423 | by the sequence of bit lengths (2, 1, 3, 3). The following |
| 424 | algorithm generates the codes as integers, intended to be read |
| 425 | from most- to least-significant bit. The code lengths are |
| 426 | initially in tree[I].Len; the codes are produced in |
| 427 | tree[I].Code. |
| 428 | |
| 429 | 1) Count the number of codes for each code length. Let |
| 430 | bl_count[N] be the number of codes of length N, N >= 1. |
| 431 | |
| 432 | 2) Find the numerical value of the smallest code for each |
| 433 | code length: |
| 434 | |
| 435 | code = 0; |
| 436 | bl_count[0] = 0; |
| 437 | for (bits = 1; bits <= MAX_BITS; bits++) { |
| 438 | code = (code + bl_count[bits-1]) << 1; |
| 439 | next_code[bits] = code; |
| 440 | } |
| 441 | |
| 442 | 3) Assign numerical values to all codes, using consecutive |
| 443 | values for all codes of the same length with the base |
| 444 | values determined at step 2. Codes that are never used |
| 445 | (which have a bit length of zero) must not be assigned a |
| 446 | value. |
| 447 | |
| 448 | for (n = 0; n <= max_code; n++) { |
| 449 | len = tree[n].Len; |
| 450 | if (len != 0) { |
| 451 | tree[n].Code = next_code[len]; |
| 452 | next_code[len]++; |
| 453 | } |
| 454 | |
| 455 | |
| 456 | |
| 457 | Deutsch Informational [Page 8] |
| 458 | |
| 459 | |
| 460 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 461 | |
| 462 | |
| 463 | } |
| 464 | |
| 465 | Example: |
| 466 | |
| 467 | Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, |
| 468 | 3, 2, 4, 4). After step 1, we have: |
| 469 | |
| 470 | N bl_count[N] |
| 471 | - ----------- |
| 472 | 2 1 |
| 473 | 3 5 |
| 474 | 4 2 |
| 475 | |
| 476 | Step 2 computes the following next_code values: |
| 477 | |
| 478 | N next_code[N] |
| 479 | - ------------ |
| 480 | 1 0 |
| 481 | 2 0 |
| 482 | 3 2 |
| 483 | 4 14 |
| 484 | |
| 485 | Step 3 produces the following code values: |
| 486 | |
| 487 | Symbol Length Code |
| 488 | ------ ------ ---- |
| 489 | A 3 010 |
| 490 | B 3 011 |
| 491 | C 3 100 |
| 492 | D 3 101 |
| 493 | E 3 110 |
| 494 | F 2 00 |
| 495 | G 4 1110 |
| 496 | H 4 1111 |
| 497 | |
| 498 | 3.2.3. Details of block format |
| 499 | |
| 500 | Each block of compressed data begins with 3 header bits |
| 501 | containing the following data: |
| 502 | |
| 503 | first bit BFINAL |
| 504 | next 2 bits BTYPE |
| 505 | |
| 506 | Note that the header bits do not necessarily begin on a byte |
| 507 | boundary, since a block does not necessarily occupy an integral |
| 508 | number of bytes. |
| 509 | |
| 510 | |
| 511 | |
| 512 | |
| 513 | |
| 514 | Deutsch Informational [Page 9] |
| 515 | |
| 516 | |
| 517 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 518 | |
| 519 | |
| 520 | BFINAL is set if and only if this is the last block of the data |
| 521 | set. |
| 522 | |
| 523 | BTYPE specifies how the data are compressed, as follows: |
| 524 | |
| 525 | 00 - no compression |
| 526 | 01 - compressed with fixed Huffman codes |
| 527 | 10 - compressed with dynamic Huffman codes |
| 528 | 11 - reserved (error) |
| 529 | |
| 530 | The only difference between the two compressed cases is how the |
| 531 | Huffman codes for the literal/length and distance alphabets are |
| 532 | defined. |
| 533 | |
| 534 | In all cases, the decoding algorithm for the actual data is as |
| 535 | follows: |
| 536 | |
| 537 | do |
| 538 | read block header from input stream. |
| 539 | if stored with no compression |
| 540 | skip any remaining bits in current partially |
| 541 | processed byte |
| 542 | read LEN and NLEN (see next section) |
| 543 | copy LEN bytes of data to output |
| 544 | otherwise |
| 545 | if compressed with dynamic Huffman codes |
| 546 | read representation of code trees (see |
| 547 | subsection below) |
| 548 | loop (until end of block code recognized) |
| 549 | decode literal/length value from input stream |
| 550 | if value < 256 |
| 551 | copy value (literal byte) to output stream |
| 552 | otherwise |
| 553 | if value = end of block (256) |
| 554 | break from loop |
| 555 | otherwise (value = 257..285) |
| 556 | decode distance from input stream |
| 557 | |
| 558 | move backwards distance bytes in the output |
| 559 | stream, and copy length bytes from this |
| 560 | position to the output stream. |
| 561 | end loop |
| 562 | while not last block |
| 563 | |
| 564 | Note that a duplicated string reference may refer to a string |
| 565 | in a previous block; i.e., the backward distance may cross one |
| 566 | or more block boundaries. However a distance cannot refer past |
| 567 | the beginning of the output stream. (An application using a |
| 568 | |
| 569 | |
| 570 | |
| 571 | Deutsch Informational [Page 10] |
| 572 | |
| 573 | |
| 574 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 575 | |
| 576 | |
| 577 | preset dictionary might discard part of the output stream; a |
| 578 | distance can refer to that part of the output stream anyway) |
| 579 | Note also that the referenced string may overlap the current |
| 580 | position; for example, if the last 2 bytes decoded have values |
| 581 | X and Y, a string reference with <length = 5, distance = 2> |
| 582 | adds X,Y,X,Y,X to the output stream. |
| 583 | |
| 584 | We now specify each compression method in turn. |
| 585 | |
| 586 | 3.2.4. Non-compressed blocks (BTYPE=00) |
| 587 | |
| 588 | Any bits of input up to the next byte boundary are ignored. |
| 589 | The rest of the block consists of the following information: |
| 590 | |
| 591 | 0 1 2 3 4... |
| 592 | +---+---+---+---+================================+ |
| 593 | | LEN | NLEN |... LEN bytes of literal data...| |
| 594 | +---+---+---+---+================================+ |
| 595 | |
| 596 | LEN is the number of data bytes in the block. NLEN is the |
| 597 | one's complement of LEN. |
| 598 | |
| 599 | 3.2.5. Compressed blocks (length and distance codes) |
| 600 | |
| 601 | As noted above, encoded data blocks in the "deflate" format |
| 602 | consist of sequences of symbols drawn from three conceptually |
| 603 | distinct alphabets: either literal bytes, from the alphabet of |
| 604 | byte values (0..255), or <length, backward distance> pairs, |
| 605 | where the length is drawn from (3..258) and the distance is |
| 606 | drawn from (1..32,768). In fact, the literal and length |
| 607 | alphabets are merged into a single alphabet (0..285), where |
| 608 | values 0..255 represent literal bytes, the value 256 indicates |
| 609 | end-of-block, and values 257..285 represent length codes |
| 610 | (possibly in conjunction with extra bits following the symbol |
| 611 | code) as follows: |
| 612 | |
| 613 | |
| 614 | |
| 615 | |
| 616 | |
| 617 | |
| 618 | |
| 619 | |
| 620 | |
| 621 | |
| 622 | |
| 623 | |
| 624 | |
| 625 | |
| 626 | |
| 627 | |
| 628 | Deutsch Informational [Page 11] |
| 629 | |
| 630 | |
| 631 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 632 | |
| 633 | |
| 634 | Extra Extra Extra |
| 635 | Code Bits Length(s) Code Bits Lengths Code Bits Length(s) |
| 636 | ---- ---- ------ ---- ---- ------- ---- ---- ------- |
| 637 | 257 0 3 267 1 15,16 277 4 67-82 |
| 638 | 258 0 4 268 1 17,18 278 4 83-98 |
| 639 | 259 0 5 269 2 19-22 279 4 99-114 |
| 640 | 260 0 6 270 2 23-26 280 4 115-130 |
| 641 | 261 0 7 271 2 27-30 281 5 131-162 |
| 642 | 262 0 8 272 2 31-34 282 5 163-194 |
| 643 | 263 0 9 273 3 35-42 283 5 195-226 |
| 644 | 264 0 10 274 3 43-50 284 5 227-257 |
| 645 | 265 1 11,12 275 3 51-58 285 0 258 |
| 646 | 266 1 13,14 276 3 59-66 |
| 647 | |
| 648 | The extra bits should be interpreted as a machine integer |
| 649 | stored with the most-significant bit first, e.g., bits 1110 |
| 650 | represent the value 14. |
| 651 | |
| 652 | Extra Extra Extra |
| 653 | Code Bits Dist Code Bits Dist Code Bits Distance |
| 654 | ---- ---- ---- ---- ---- ------ ---- ---- -------- |
| 655 | 0 0 1 10 4 33-48 20 9 1025-1536 |
| 656 | 1 0 2 11 4 49-64 21 9 1537-2048 |
| 657 | 2 0 3 12 5 65-96 22 10 2049-3072 |
| 658 | 3 0 4 13 5 97-128 23 10 3073-4096 |
| 659 | 4 1 5,6 14 6 129-192 24 11 4097-6144 |
| 660 | 5 1 7,8 15 6 193-256 25 11 6145-8192 |
| 661 | 6 2 9-12 16 7 257-384 26 12 8193-12288 |
| 662 | 7 2 13-16 17 7 385-512 27 12 12289-16384 |
| 663 | 8 3 17-24 18 8 513-768 28 13 16385-24576 |
| 664 | 9 3 25-32 19 8 769-1024 29 13 24577-32768 |
| 665 | |
| 666 | 3.2.6. Compression with fixed Huffman codes (BTYPE=01) |
| 667 | |
| 668 | The Huffman codes for the two alphabets are fixed, and are not |
| 669 | represented explicitly in the data. The Huffman code lengths |
| 670 | for the literal/length alphabet are: |
| 671 | |
| 672 | Lit Value Bits Codes |
| 673 | --------- ---- ----- |
| 674 | 0 - 143 8 00110000 through |
| 675 | 10111111 |
| 676 | 144 - 255 9 110010000 through |
| 677 | 111111111 |
| 678 | 256 - 279 7 0000000 through |
| 679 | 0010111 |
| 680 | 280 - 287 8 11000000 through |
| 681 | 11000111 |
| 682 | |
| 683 | |
| 684 | |
| 685 | Deutsch Informational [Page 12] |
| 686 | |
| 687 | |
| 688 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 689 | |
| 690 | |
| 691 | The code lengths are sufficient to generate the actual codes, |
| 692 | as described above; we show the codes in the table for added |
| 693 | clarity. Literal/length values 286-287 will never actually |
| 694 | occur in the compressed data, but participate in the code |
| 695 | construction. |
| 696 | |
| 697 | Distance codes 0-31 are represented by (fixed-length) 5-bit |
| 698 | codes, with possible additional bits as shown in the table |
| 699 | shown in Paragraph 3.2.5, above. Note that distance codes 30- |
| 700 | 31 will never actually occur in the compressed data. |
| 701 | |
| 702 | 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) |
| 703 | |
| 704 | The Huffman codes for the two alphabets appear in the block |
| 705 | immediately after the header bits and before the actual |
| 706 | compressed data, first the literal/length code and then the |
| 707 | distance code. Each code is defined by a sequence of code |
| 708 | lengths, as discussed in Paragraph 3.2.2, above. For even |
| 709 | greater compactness, the code length sequences themselves are |
| 710 | compressed using a Huffman code. The alphabet for code lengths |
| 711 | is as follows: |
| 712 | |
| 713 | 0 - 15: Represent code lengths of 0 - 15 |
| 714 | 16: Copy the previous code length 3 - 6 times. |
| 715 | The next 2 bits indicate repeat length |
| 716 | (0 = 3, ... , 3 = 6) |
| 717 | Example: Codes 8, 16 (+2 bits 11), |
| 718 | 16 (+2 bits 10) will expand to |
| 719 | 12 code lengths of 8 (1 + 6 + 5) |
| 720 | 17: Repeat a code length of 0 for 3 - 10 times. |
| 721 | (3 bits of length) |
| 722 | 18: Repeat a code length of 0 for 11 - 138 times |
| 723 | (7 bits of length) |
| 724 | |
| 725 | A code length of 0 indicates that the corresponding symbol in |
| 726 | the literal/length or distance alphabet will not occur in the |
| 727 | block, and should not participate in the Huffman code |
| 728 | construction algorithm given earlier. If only one distance |
| 729 | code is used, it is encoded using one bit, not zero bits; in |
| 730 | this case there is a single code length of one, with one unused |
| 731 | code. One distance code of zero bits means that there are no |
| 732 | distance codes used at all (the data is all literals). |
| 733 | |
| 734 | We can now define the format of the block: |
| 735 | |
| 736 | 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) |
| 737 | 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) |
| 738 | 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) |
| 739 | |
| 740 | |
| 741 | |
| 742 | Deutsch Informational [Page 13] |
| 743 | |
| 744 | |
| 745 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 746 | |
| 747 | |
| 748 | (HCLEN + 4) x 3 bits: code lengths for the code length |
| 749 | alphabet given just above, in the order: 16, 17, 18, |
| 750 | 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 |
| 751 | |
| 752 | These code lengths are interpreted as 3-bit integers |
| 753 | (0-7); as above, a code length of 0 means the |
| 754 | corresponding symbol (literal/length or distance code |
| 755 | length) is not used. |
| 756 | |
| 757 | HLIT + 257 code lengths for the literal/length alphabet, |
| 758 | encoded using the code length Huffman code |
| 759 | |
| 760 | HDIST + 1 code lengths for the distance alphabet, |
| 761 | encoded using the code length Huffman code |
| 762 | |
| 763 | The actual compressed data of the block, |
| 764 | encoded using the literal/length and distance Huffman |
| 765 | codes |
| 766 | |
| 767 | The literal/length symbol 256 (end of data), |
| 768 | encoded using the literal/length Huffman code |
| 769 | |
| 770 | The code length repeat codes can cross from HLIT + 257 to the |
| 771 | HDIST + 1 code lengths. In other words, all code lengths form |
| 772 | a single sequence of HLIT + HDIST + 258 values. |
| 773 | |
| 774 | 3.3. Compliance |
| 775 | |
| 776 | A compressor may limit further the ranges of values specified in |
| 777 | the previous section and still be compliant; for example, it may |
| 778 | limit the range of backward pointers to some value smaller than |
| 779 | 32K. Similarly, a compressor may limit the size of blocks so that |
| 780 | a compressible block fits in memory. |
| 781 | |
| 782 | A compliant decompressor must accept the full range of possible |
| 783 | values defined in the previous section, and must accept blocks of |
| 784 | arbitrary size. |
| 785 | |
| 786 | 4. Compression algorithm details |
| 787 | |
| 788 | While it is the intent of this document to define the "deflate" |
| 789 | compressed data format without reference to any particular |
| 790 | compression algorithm, the format is related to the compressed |
| 791 | formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); |
| 792 | since many variations of LZ77 are patented, it is strongly |
| 793 | recommended that the implementor of a compressor follow the general |
| 794 | algorithm presented here, which is known not to be patented per se. |
| 795 | The material in this section is not part of the definition of the |
| 796 | |
| 797 | |
| 798 | |
| 799 | Deutsch Informational [Page 14] |
| 800 | |
| 801 | |
| 802 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 803 | |
| 804 | |
| 805 | specification per se, and a compressor need not follow it in order to |
| 806 | be compliant. |
| 807 | |
| 808 | The compressor terminates a block when it determines that starting a |
| 809 | new block with fresh trees would be useful, or when the block size |
| 810 | fills up the compressor's block buffer. |
| 811 | |
| 812 | The compressor uses a chained hash table to find duplicated strings, |
| 813 | using a hash function that operates on 3-byte sequences. At any |
| 814 | given point during compression, let XYZ be the next 3 input bytes to |
| 815 | be examined (not necessarily all different, of course). First, the |
| 816 | compressor examines the hash chain for XYZ. If the chain is empty, |
| 817 | the compressor simply writes out X as a literal byte and advances one |
| 818 | byte in the input. If the hash chain is not empty, indicating that |
| 819 | the sequence XYZ (or, if we are unlucky, some other 3 bytes with the |
| 820 | same hash function value) has occurred recently, the compressor |
| 821 | compares all strings on the XYZ hash chain with the actual input data |
| 822 | sequence starting at the current point, and selects the longest |
| 823 | match. |
| 824 | |
| 825 | The compressor searches the hash chains starting with the most recent |
| 826 | strings, to favor small distances and thus take advantage of the |
| 827 | Huffman encoding. The hash chains are singly linked. There are no |
| 828 | deletions from the hash chains; the algorithm simply discards matches |
| 829 | that are too old. To avoid a worst-case situation, very long hash |
| 830 | chains are arbitrarily truncated at a certain length, determined by a |
| 831 | run-time parameter. |
| 832 | |
| 833 | To improve overall compression, the compressor optionally defers the |
| 834 | selection of matches ("lazy matching"): after a match of length N has |
| 835 | been found, the compressor searches for a longer match starting at |
| 836 | the next input byte. If it finds a longer match, it truncates the |
| 837 | previous match to a length of one (thus producing a single literal |
| 838 | byte) and then emits the longer match. Otherwise, it emits the |
| 839 | original match, and, as described above, advances N bytes before |
| 840 | continuing. |
| 841 | |
| 842 | Run-time parameters also control this "lazy match" procedure. If |
| 843 | compression ratio is most important, the compressor attempts a |
| 844 | complete second search regardless of the length of the first match. |
| 845 | In the normal case, if the current match is "long enough", the |
| 846 | compressor reduces the search for a longer match, thus speeding up |
| 847 | the process. If speed is most important, the compressor inserts new |
| 848 | strings in the hash table only when no match was found, or when the |
| 849 | match is not "too long". This degrades the compression ratio but |
| 850 | saves time since there are both fewer insertions and fewer searches. |
| 851 | |
| 852 | |
| 853 | |
| 854 | |
| 855 | |
| 856 | Deutsch Informational [Page 15] |
| 857 | |
| 858 | |
| 859 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 860 | |
| 861 | |
| 862 | 5. References |
| 863 | |
| 864 | [1] Huffman, D. A., "A Method for the Construction of Minimum |
| 865 | Redundancy Codes", Proceedings of the Institute of Radio |
| 866 | Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. |
| 867 | |
| 868 | [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data |
| 869 | Compression", IEEE Transactions on Information Theory, Vol. 23, |
| 870 | No. 3, pp. 337-343. |
| 871 | |
| 872 | [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, |
| 873 | available in ftp://ftp.uu.net/pub/archiving/zip/doc/ |
| 874 | |
| 875 | [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, |
| 876 | available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ |
| 877 | |
| 878 | [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix |
| 879 | encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. |
| 880 | |
| 881 | [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," |
| 882 | Comm. ACM, 33,4, April 1990, pp. 449-459. |
| 883 | |
| 884 | 6. Security Considerations |
| 885 | |
| 886 | Any data compression method involves the reduction of redundancy in |
| 887 | the data. Consequently, any corruption of the data is likely to have |
| 888 | severe effects and be difficult to correct. Uncompressed text, on |
| 889 | the other hand, will probably still be readable despite the presence |
| 890 | of some corrupted bytes. |
| 891 | |
| 892 | It is recommended that systems using this data format provide some |
| 893 | means of validating the integrity of the compressed data. See |
| 894 | reference [3], for example. |
| 895 | |
| 896 | 7. Source code |
| 897 | |
| 898 | Source code for a C language implementation of a "deflate" compliant |
| 899 | compressor and decompressor is available within the zlib package at |
| 900 | ftp://ftp.uu.net/pub/archiving/zip/zlib/. |
| 901 | |
| 902 | 8. Acknowledgements |
| 903 | |
| 904 | Trademarks cited in this document are the property of their |
| 905 | respective owners. |
| 906 | |
| 907 | Phil Katz designed the deflate format. Jean-Loup Gailly and Mark |
| 908 | Adler wrote the related software described in this specification. |
| 909 | Glenn Randers-Pehrson converted this document to RFC and HTML format. |
| 910 | |
| 911 | |
| 912 | |
| 913 | Deutsch Informational [Page 16] |
| 914 | |
| 915 | |
| 916 | RFC 1951 DEFLATE Compressed Data Format Specification May 1996 |
| 917 | |
| 918 | |
| 919 | 9. Author's Address |
| 920 | |
| 921 | L. Peter Deutsch |
| 922 | Aladdin Enterprises |
| 923 | 203 Santa Margarita Ave. |
| 924 | Menlo Park, CA 94025 |
| 925 | |
| 926 | Phone: (415) 322-0103 (AM only) |
| 927 | FAX: (415) 322-1734 |
| 928 | EMail: <[email protected]> |
| 929 | |
| 930 | Questions about the technical content of this specification can be |
| 931 | sent by email to: |
| 932 | |
| 933 | Jean-Loup Gailly <[email protected]> and |
| 934 | Mark Adler <[email protected]> |
| 935 | |
| 936 | Editorial comments on this specification can be sent by email to: |
| 937 | |
| 938 | L. Peter Deutsch <[email protected]> and |
| 939 | Glenn Randers-Pehrson <[email protected]> |
| 940 | |
| 941 | |
| 942 | |
| 943 | |
| 944 | |
| 945 | |
| 946 | |
| 947 | |
| 948 | |
| 949 | |
| 950 | |
| 951 | |
| 952 | |
| 953 | |
| 954 | |
| 955 | |
| 956 | |
| 957 | |
| 958 | |
| 959 | |
| 960 | |
| 961 | |
| 962 | |
| 963 | |
| 964 | |
| 965 | |
| 966 | |
| 967 | |
| 968 | |
| 969 | |
| 970 | Deutsch Informational [Page 17] |
| 971 | |
| 972 |
| --- a/compat/zlib/doc/rfc1951.txt | |
| +++ b/compat/zlib/doc/rfc1951.txt | |
| @@ -1,972 +0,0 @@ | |
D
compat/zlib/doc/rfc1952.txt
-687
| --- a/compat/zlib/doc/rfc1952.txt | ||
| +++ b/compat/zlib/doc/rfc1952.txt | ||
| @@ -1,687 +0,0 @@ | ||
| 1 | - | |
| 2 | - | |
| 3 | - | |
| 4 | - | |
| 5 | - | |
| 6 | - | |
| 7 | -Network Working Group P. Deutsch | |
| 8 | -Request for Comments: 1952 Aladdin Enterprises | |
| 9 | -Category: Informational May 1996 | |
| 10 | - | |
| 11 | - | |
| 12 | - GZIP file format specification version 4.3 | |
| 13 | - | |
| 14 | -Status of This Memo | |
| 15 | - | |
| 16 | - This memo provides information for the Internet community. This memo | |
| 17 | - does not specify an Internet standard of any kind. Distribution of | |
| 18 | - this memo is unlimited. | |
| 19 | - | |
| 20 | -IESG Note: | |
| 21 | - | |
| 22 | - The IESG takes no position on the validity of any Intellectual | |
| 23 | - Property Rights statements contained in this document. | |
| 24 | - | |
| 25 | -Notices | |
| 26 | - | |
| 27 | - Copyright (c) 1996 L. Peter Deutsch | |
| 28 | - | |
| 29 | - Permission is granted to copy and distribute this document for any | |
| 30 | - purpose and without charge, including translations into other | |
| 31 | - languages and incorporation into compilations, provided that the | |
| 32 | - copyright notice and this notice are preserved, and that any | |
| 33 | - substantive changes or deletions from the original are clearly | |
| 34 | - marked. | |
| 35 | - | |
| 36 | - A pointer to the latest version of this and related documentation in | |
| 37 | - HTML format can be found at the URL | |
| 38 | - <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>. | |
| 39 | - | |
| 40 | -Abstract | |
| 41 | - | |
| 42 | - This specification defines a lossless compressed data format that is | |
| 43 | - compatible with the widely used GZIP utility. The format includes a | |
| 44 | - cyclic redundancy check value for detecting data corruption. The | |
| 45 | - format presently uses the DEFLATE method of compression but can be | |
| 46 | - easily extended to use other compression methods. The format can be | |
| 47 | - implemented readily in a manner not covered by patents. | |
| 48 | - | |
| 49 | - | |
| 50 | - | |
| 51 | - | |
| 52 | - | |
| 53 | - | |
| 54 | - | |
| 55 | - | |
| 56 | - | |
| 57 | - | |
| 58 | -Deutsch Informational [Page 1] | |
| 59 | - | |
| 60 | - | |
| 61 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 62 | - | |
| 63 | - | |
| 64 | -Table of Contents | |
| 65 | - | |
| 66 | - 1. Introduction ................................................... 2 | |
| 67 | - 1.1. Purpose ................................................... 2 | |
| 68 | - 1.2. Intended audience ......................................... 3 | |
| 69 | - 1.3. Scope ..................................................... 3 | |
| 70 | - 1.4. Compliance ................................................ 3 | |
| 71 | - 1.5. Definitions of terms and conventions used ................. 3 | |
| 72 | - 1.6. Changes from previous versions ............................ 3 | |
| 73 | - 2. Detailed specification ......................................... 4 | |
| 74 | - 2.1. Overall conventions ....................................... 4 | |
| 75 | - 2.2. File format ............................................... 5 | |
| 76 | - 2.3. Member format ............................................. 5 | |
| 77 | - 2.3.1. Member header and trailer ........................... 6 | |
| 78 | - 2.3.1.1. Extra field ................................... 8 | |
| 79 | - 2.3.1.2. Compliance .................................... 9 | |
| 80 | - 3. References .................................................. 9 | |
| 81 | - 4. Security Considerations .................................... 10 | |
| 82 | - 5. Acknowledgements ........................................... 10 | |
| 83 | - 6. Author's Address ........................................... 10 | |
| 84 | - 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 | |
| 85 | - 8. Appendix: Sample CRC Code .................................. 11 | |
| 86 | - | |
| 87 | -1. Introduction | |
| 88 | - | |
| 89 | - 1.1. Purpose | |
| 90 | - | |
| 91 | - The purpose of this specification is to define a lossless | |
| 92 | - compressed data format that: | |
| 93 | - | |
| 94 | - * Is independent of CPU type, operating system, file system, | |
| 95 | - and character set, and hence can be used for interchange; | |
| 96 | - * Can compress or decompress a data stream (as opposed to a | |
| 97 | - randomly accessible file) to produce another data stream, | |
| 98 | - using only an a priori bounded amount of intermediate | |
| 99 | - storage, and hence can be used in data communications or | |
| 100 | - similar structures such as Unix filters; | |
| 101 | - * Compresses data with efficiency comparable to the best | |
| 102 | - currently available general-purpose compression methods, | |
| 103 | - and in particular considerably better than the "compress" | |
| 104 | - program; | |
| 105 | - * Can be implemented readily in a manner not covered by | |
| 106 | - patents, and hence can be practiced freely; | |
| 107 | - * Is compatible with the file format produced by the current | |
| 108 | - widely used gzip utility, in that conforming decompressors | |
| 109 | - will be able to read data produced by the existing gzip | |
| 110 | - compressor. | |
| 111 | - | |
| 112 | - | |
| 113 | - | |
| 114 | - | |
| 115 | -Deutsch Informational [Page 2] | |
| 116 | - | |
| 117 | - | |
| 118 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 119 | - | |
| 120 | - | |
| 121 | - The data format defined by this specification does not attempt to: | |
| 122 | - | |
| 123 | - * Provide random access to compressed data; | |
| 124 | - * Compress specialized data (e.g., raster graphics) as well as | |
| 125 | - the best currently available specialized algorithms. | |
| 126 | - | |
| 127 | - 1.2. Intended audience | |
| 128 | - | |
| 129 | - This specification is intended for use by implementors of software | |
| 130 | - to compress data into gzip format and/or decompress data from gzip | |
| 131 | - format. | |
| 132 | - | |
| 133 | - The text of the specification assumes a basic background in | |
| 134 | - programming at the level of bits and other primitive data | |
| 135 | - representations. | |
| 136 | - | |
| 137 | - 1.3. Scope | |
| 138 | - | |
| 139 | - The specification specifies a compression method and a file format | |
| 140 | - (the latter assuming only that a file can store a sequence of | |
| 141 | - arbitrary bytes). It does not specify any particular interface to | |
| 142 | - a file system or anything about character sets or encodings | |
| 143 | - (except for file names and comments, which are optional). | |
| 144 | - | |
| 145 | - 1.4. Compliance | |
| 146 | - | |
| 147 | - Unless otherwise indicated below, a compliant decompressor must be | |
| 148 | - able to accept and decompress any file that conforms to all the | |
| 149 | - specifications presented here; a compliant compressor must produce | |
| 150 | - files that conform to all the specifications presented here. The | |
| 151 | - material in the appendices is not part of the specification per se | |
| 152 | - and is not relevant to compliance. | |
| 153 | - | |
| 154 | - 1.5. Definitions of terms and conventions used | |
| 155 | - | |
| 156 | - byte: 8 bits stored or transmitted as a unit (same as an octet). | |
| 157 | - (For this specification, a byte is exactly 8 bits, even on | |
| 158 | - machines which store a character on a number of bits different | |
| 159 | - from 8.) See below for the numbering of bits within a byte. | |
| 160 | - | |
| 161 | - 1.6. Changes from previous versions | |
| 162 | - | |
| 163 | - There have been no technical changes to the gzip format since | |
| 164 | - version 4.1 of this specification. In version 4.2, some | |
| 165 | - terminology was changed, and the sample CRC code was rewritten for | |
| 166 | - clarity and to eliminate the requirement for the caller to do pre- | |
| 167 | - and post-conditioning. Version 4.3 is a conversion of the | |
| 168 | - specification to RFC style. | |
| 169 | - | |
| 170 | - | |
| 171 | - | |
| 172 | -Deutsch Informational [Page 3] | |
| 173 | - | |
| 174 | - | |
| 175 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 176 | - | |
| 177 | - | |
| 178 | -2. Detailed specification | |
| 179 | - | |
| 180 | - 2.1. Overall conventions | |
| 181 | - | |
| 182 | - In the diagrams below, a box like this: | |
| 183 | - | |
| 184 | - +---+ | |
| 185 | - | | <-- the vertical bars might be missing | |
| 186 | - +---+ | |
| 187 | - | |
| 188 | - represents one byte; a box like this: | |
| 189 | - | |
| 190 | - +==============+ | |
| 191 | - | | | |
| 192 | - +==============+ | |
| 193 | - | |
| 194 | - represents a variable number of bytes. | |
| 195 | - | |
| 196 | - Bytes stored within a computer do not have a "bit order", since | |
| 197 | - they are always treated as a unit. However, a byte considered as | |
| 198 | - an integer between 0 and 255 does have a most- and least- | |
| 199 | - significant bit, and since we write numbers with the most- | |
| 200 | - significant digit on the left, we also write bytes with the most- | |
| 201 | - significant bit on the left. In the diagrams below, we number the | |
| 202 | - bits of a byte so that bit 0 is the least-significant bit, i.e., | |
| 203 | - the bits are numbered: | |
| 204 | - | |
| 205 | - +--------+ | |
| 206 | - |76543210| | |
| 207 | - +--------+ | |
| 208 | - | |
| 209 | - This document does not address the issue of the order in which | |
| 210 | - bits of a byte are transmitted on a bit-sequential medium, since | |
| 211 | - the data format described here is byte- rather than bit-oriented. | |
| 212 | - | |
| 213 | - Within a computer, a number may occupy multiple bytes. All | |
| 214 | - multi-byte numbers in the format described here are stored with | |
| 215 | - the least-significant byte first (at the lower memory address). | |
| 216 | - For example, the decimal number 520 is stored as: | |
| 217 | - | |
| 218 | - 0 1 | |
| 219 | - +--------+--------+ | |
| 220 | - |00001000|00000010| | |
| 221 | - +--------+--------+ | |
| 222 | - ^ ^ | |
| 223 | - | | | |
| 224 | - | + more significant byte = 2 x 256 | |
| 225 | - + less significant byte = 8 | |
| 226 | - | |
| 227 | - | |
| 228 | - | |
| 229 | -Deutsch Informational [Page 4] | |
| 230 | - | |
| 231 | - | |
| 232 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 233 | - | |
| 234 | - | |
| 235 | - 2.2. File format | |
| 236 | - | |
| 237 | - A gzip file consists of a series of "members" (compressed data | |
| 238 | - sets). The format of each member is specified in the following | |
| 239 | - section. The members simply appear one after another in the file, | |
| 240 | - with no additional information before, between, or after them. | |
| 241 | - | |
| 242 | - 2.3. Member format | |
| 243 | - | |
| 244 | - Each member has the following structure: | |
| 245 | - | |
| 246 | - +---+---+---+---+---+---+---+---+---+---+ | |
| 247 | - |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) | |
| 248 | - +---+---+---+---+---+---+---+---+---+---+ | |
| 249 | - | |
| 250 | - (if FLG.FEXTRA set) | |
| 251 | - | |
| 252 | - +---+---+=================================+ | |
| 253 | - | XLEN |...XLEN bytes of "extra field"...| (more-->) | |
| 254 | - +---+---+=================================+ | |
| 255 | - | |
| 256 | - (if FLG.FNAME set) | |
| 257 | - | |
| 258 | - +=========================================+ | |
| 259 | - |...original file name, zero-terminated...| (more-->) | |
| 260 | - +=========================================+ | |
| 261 | - | |
| 262 | - (if FLG.FCOMMENT set) | |
| 263 | - | |
| 264 | - +===================================+ | |
| 265 | - |...file comment, zero-terminated...| (more-->) | |
| 266 | - +===================================+ | |
| 267 | - | |
| 268 | - (if FLG.FHCRC set) | |
| 269 | - | |
| 270 | - +---+---+ | |
| 271 | - | CRC16 | | |
| 272 | - +---+---+ | |
| 273 | - | |
| 274 | - +=======================+ | |
| 275 | - |...compressed blocks...| (more-->) | |
| 276 | - +=======================+ | |
| 277 | - | |
| 278 | - 0 1 2 3 4 5 6 7 | |
| 279 | - +---+---+---+---+---+---+---+---+ | |
| 280 | - | CRC32 | ISIZE | | |
| 281 | - +---+---+---+---+---+---+---+---+ | |
| 282 | - | |
| 283 | - | |
| 284 | - | |
| 285 | - | |
| 286 | -Deutsch Informational [Page 5] | |
| 287 | - | |
| 288 | - | |
| 289 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 290 | - | |
| 291 | - | |
| 292 | - 2.3.1. Member header and trailer | |
| 293 | - | |
| 294 | - ID1 (IDentification 1) | |
| 295 | - ID2 (IDentification 2) | |
| 296 | - These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 | |
| 297 | - (0x8b, \213), to identify the file as being in gzip format. | |
| 298 | - | |
| 299 | - CM (Compression Method) | |
| 300 | - This identifies the compression method used in the file. CM | |
| 301 | - = 0-7 are reserved. CM = 8 denotes the "deflate" | |
| 302 | - compression method, which is the one customarily used by | |
| 303 | - gzip and which is documented elsewhere. | |
| 304 | - | |
| 305 | - FLG (FLaGs) | |
| 306 | - This flag byte is divided into individual bits as follows: | |
| 307 | - | |
| 308 | - bit 0 FTEXT | |
| 309 | - bit 1 FHCRC | |
| 310 | - bit 2 FEXTRA | |
| 311 | - bit 3 FNAME | |
| 312 | - bit 4 FCOMMENT | |
| 313 | - bit 5 reserved | |
| 314 | - bit 6 reserved | |
| 315 | - bit 7 reserved | |
| 316 | - | |
| 317 | - If FTEXT is set, the file is probably ASCII text. This is | |
| 318 | - an optional indication, which the compressor may set by | |
| 319 | - checking a small amount of the input data to see whether any | |
| 320 | - non-ASCII characters are present. In case of doubt, FTEXT | |
| 321 | - is cleared, indicating binary data. For systems which have | |
| 322 | - different file formats for ascii text and binary data, the | |
| 323 | - decompressor can use FTEXT to choose the appropriate format. | |
| 324 | - We deliberately do not specify the algorithm used to set | |
| 325 | - this bit, since a compressor always has the option of | |
| 326 | - leaving it cleared and a decompressor always has the option | |
| 327 | - of ignoring it and letting some other program handle issues | |
| 328 | - of data conversion. | |
| 329 | - | |
| 330 | - If FHCRC is set, a CRC16 for the gzip header is present, | |
| 331 | - immediately before the compressed data. The CRC16 consists | |
| 332 | - of the two least significant bytes of the CRC32 for all | |
| 333 | - bytes of the gzip header up to and not including the CRC16. | |
| 334 | - [The FHCRC bit was never set by versions of gzip up to | |
| 335 | - 1.2.4, even though it was documented with a different | |
| 336 | - meaning in gzip 1.2.4.] | |
| 337 | - | |
| 338 | - If FEXTRA is set, optional extra fields are present, as | |
| 339 | - described in a following section. | |
| 340 | - | |
| 341 | - | |
| 342 | - | |
| 343 | -Deutsch Informational [Page 6] | |
| 344 | - | |
| 345 | - | |
| 346 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 347 | - | |
| 348 | - | |
| 349 | - If FNAME is set, an original file name is present, | |
| 350 | - terminated by a zero byte. The name must consist of ISO | |
| 351 | - 8859-1 (LATIN-1) characters; on operating systems using | |
| 352 | - EBCDIC or any other character set for file names, the name | |
| 353 | - must be translated to the ISO LATIN-1 character set. This | |
| 354 | - is the original name of the file being compressed, with any | |
| 355 | - directory components removed, and, if the file being | |
| 356 | - compressed is on a file system with case insensitive names, | |
| 357 | - forced to lower case. There is no original file name if the | |
| 358 | - data was compressed from a source other than a named file; | |
| 359 | - for example, if the source was stdin on a Unix system, there | |
| 360 | - is no file name. | |
| 361 | - | |
| 362 | - If FCOMMENT is set, a zero-terminated file comment is | |
| 363 | - present. This comment is not interpreted; it is only | |
| 364 | - intended for human consumption. The comment must consist of | |
| 365 | - ISO 8859-1 (LATIN-1) characters. Line breaks should be | |
| 366 | - denoted by a single line feed character (10 decimal). | |
| 367 | - | |
| 368 | - Reserved FLG bits must be zero. | |
| 369 | - | |
| 370 | - MTIME (Modification TIME) | |
| 371 | - This gives the most recent modification time of the original | |
| 372 | - file being compressed. The time is in Unix format, i.e., | |
| 373 | - seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this | |
| 374 | - may cause problems for MS-DOS and other systems that use | |
| 375 | - local rather than Universal time.) If the compressed data | |
| 376 | - did not come from a file, MTIME is set to the time at which | |
| 377 | - compression started. MTIME = 0 means no time stamp is | |
| 378 | - available. | |
| 379 | - | |
| 380 | - XFL (eXtra FLags) | |
| 381 | - These flags are available for use by specific compression | |
| 382 | - methods. The "deflate" method (CM = 8) sets these flags as | |
| 383 | - follows: | |
| 384 | - | |
| 385 | - XFL = 2 - compressor used maximum compression, | |
| 386 | - slowest algorithm | |
| 387 | - XFL = 4 - compressor used fastest algorithm | |
| 388 | - | |
| 389 | - OS (Operating System) | |
| 390 | - This identifies the type of file system on which compression | |
| 391 | - took place. This may be useful in determining end-of-line | |
| 392 | - convention for text files. The currently defined values are | |
| 393 | - as follows: | |
| 394 | - | |
| 395 | - | |
| 396 | - | |
| 397 | - | |
| 398 | - | |
| 399 | - | |
| 400 | -Deutsch Informational [Page 7] | |
| 401 | - | |
| 402 | - | |
| 403 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 404 | - | |
| 405 | - | |
| 406 | - 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) | |
| 407 | - 1 - Amiga | |
| 408 | - 2 - VMS (or OpenVMS) | |
| 409 | - 3 - Unix | |
| 410 | - 4 - VM/CMS | |
| 411 | - 5 - Atari TOS | |
| 412 | - 6 - HPFS filesystem (OS/2, NT) | |
| 413 | - 7 - Macintosh | |
| 414 | - 8 - Z-System | |
| 415 | - 9 - CP/M | |
| 416 | - 10 - TOPS-20 | |
| 417 | - 11 - NTFS filesystem (NT) | |
| 418 | - 12 - QDOS | |
| 419 | - 13 - Acorn RISCOS | |
| 420 | - 255 - unknown | |
| 421 | - | |
| 422 | - XLEN (eXtra LENgth) | |
| 423 | - If FLG.FEXTRA is set, this gives the length of the optional | |
| 424 | - extra field. See below for details. | |
| 425 | - | |
| 426 | - CRC32 (CRC-32) | |
| 427 | - This contains a Cyclic Redundancy Check value of the | |
| 428 | - uncompressed data computed according to CRC-32 algorithm | |
| 429 | - used in the ISO 3309 standard and in section 8.1.1.6.2 of | |
| 430 | - ITU-T recommendation V.42. (See http://www.iso.ch for | |
| 431 | - ordering ISO documents. See gopher://info.itu.ch for an | |
| 432 | - online version of ITU-T V.42.) | |
| 433 | - | |
| 434 | - ISIZE (Input SIZE) | |
| 435 | - This contains the size of the original (uncompressed) input | |
| 436 | - data modulo 2^32. | |
| 437 | - | |
| 438 | - 2.3.1.1. Extra field | |
| 439 | - | |
| 440 | - If the FLG.FEXTRA bit is set, an "extra field" is present in | |
| 441 | - the header, with total length XLEN bytes. It consists of a | |
| 442 | - series of subfields, each of the form: | |
| 443 | - | |
| 444 | - +---+---+---+---+==================================+ | |
| 445 | - |SI1|SI2| LEN |... LEN bytes of subfield data ...| | |
| 446 | - +---+---+---+---+==================================+ | |
| 447 | - | |
| 448 | - SI1 and SI2 provide a subfield ID, typically two ASCII letters | |
| 449 | - with some mnemonic value. Jean-Loup Gailly | |
| 450 | - <[email protected]> is maintaining a registry of subfield | |
| 451 | - IDs; please send him any subfield ID you wish to use. Subfield | |
| 452 | - IDs with SI2 = 0 are reserved for future use. The following | |
| 453 | - IDs are currently defined: | |
| 454 | - | |
| 455 | - | |
| 456 | - | |
| 457 | -Deutsch Informational [Page 8] | |
| 458 | - | |
| 459 | - | |
| 460 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 461 | - | |
| 462 | - | |
| 463 | - SI1 SI2 Data | |
| 464 | - ---------- ---------- ---- | |
| 465 | - 0x41 ('A') 0x70 ('P') Apollo file type information | |
| 466 | - | |
| 467 | - LEN gives the length of the subfield data, excluding the 4 | |
| 468 | - initial bytes. | |
| 469 | - | |
| 470 | - 2.3.1.2. Compliance | |
| 471 | - | |
| 472 | - A compliant compressor must produce files with correct ID1, | |
| 473 | - ID2, CM, CRC32, and ISIZE, but may set all the other fields in | |
| 474 | - the fixed-length part of the header to default values (255 for | |
| 475 | - OS, 0 for all others). The compressor must set all reserved | |
| 476 | - bits to zero. | |
| 477 | - | |
| 478 | - A compliant decompressor must check ID1, ID2, and CM, and | |
| 479 | - provide an error indication if any of these have incorrect | |
| 480 | - values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC | |
| 481 | - at least so it can skip over the optional fields if they are | |
| 482 | - present. It need not examine any other part of the header or | |
| 483 | - trailer; in particular, a decompressor may ignore FTEXT and OS | |
| 484 | - and always produce binary output, and still be compliant. A | |
| 485 | - compliant decompressor must give an error indication if any | |
| 486 | - reserved bit is non-zero, since such a bit could indicate the | |
| 487 | - presence of a new field that would cause subsequent data to be | |
| 488 | - interpreted incorrectly. | |
| 489 | - | |
| 490 | -3. References | |
| 491 | - | |
| 492 | - [1] "Information Processing - 8-bit single-byte coded graphic | |
| 493 | - character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). | |
| 494 | - The ISO 8859-1 (Latin-1) character set is a superset of 7-bit | |
| 495 | - ASCII. Files defining this character set are available as | |
| 496 | - iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ | |
| 497 | - | |
| 498 | - [2] ISO 3309 | |
| 499 | - | |
| 500 | - [3] ITU-T recommendation V.42 | |
| 501 | - | |
| 502 | - [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", | |
| 503 | - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ | |
| 504 | - | |
| 505 | - [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in | |
| 506 | - ftp://prep.ai.mit.edu/pub/gnu/ | |
| 507 | - | |
| 508 | - [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table | |
| 509 | - Look-Up", Communications of the ACM, 31(8), pp.1008-1013. | |
| 510 | - | |
| 511 | - | |
| 512 | - | |
| 513 | - | |
| 514 | -Deutsch Informational [Page 9] | |
| 515 | - | |
| 516 | - | |
| 517 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 518 | - | |
| 519 | - | |
| 520 | - [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, | |
| 521 | - pp.118-133. | |
| 522 | - | |
| 523 | - [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, | |
| 524 | - describing the CRC concept. | |
| 525 | - | |
| 526 | -4. Security Considerations | |
| 527 | - | |
| 528 | - Any data compression method involves the reduction of redundancy in | |
| 529 | - the data. Consequently, any corruption of the data is likely to have | |
| 530 | - severe effects and be difficult to correct. Uncompressed text, on | |
| 531 | - the other hand, will probably still be readable despite the presence | |
| 532 | - of some corrupted bytes. | |
| 533 | - | |
| 534 | - It is recommended that systems using this data format provide some | |
| 535 | - means of validating the integrity of the compressed data, such as by | |
| 536 | - setting and checking the CRC-32 check value. | |
| 537 | - | |
| 538 | -5. Acknowledgements | |
| 539 | - | |
| 540 | - Trademarks cited in this document are the property of their | |
| 541 | - respective owners. | |
| 542 | - | |
| 543 | - Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, | |
| 544 | - the related software described in this specification. Glenn | |
| 545 | - Randers-Pehrson converted this document to RFC and HTML format. | |
| 546 | - | |
| 547 | -6. Author's Address | |
| 548 | - | |
| 549 | - L. Peter Deutsch | |
| 550 | - Aladdin Enterprises | |
| 551 | - 203 Santa Margarita Ave. | |
| 552 | - Menlo Park, CA 94025 | |
| 553 | - | |
| 554 | - Phone: (415) 322-0103 (AM only) | |
| 555 | - FAX: (415) 322-1734 | |
| 556 | - EMail: <[email protected]> | |
| 557 | - | |
| 558 | - Questions about the technical content of this specification can be | |
| 559 | - sent by email to: | |
| 560 | - | |
| 561 | - Jean-Loup Gailly <[email protected]> and | |
| 562 | - Mark Adler <[email protected]> | |
| 563 | - | |
| 564 | - Editorial comments on this specification can be sent by email to: | |
| 565 | - | |
| 566 | - L. Peter Deutsch <[email protected]> and | |
| 567 | - Glenn Randers-Pehrson <[email protected]> | |
| 568 | - | |
| 569 | - | |
| 570 | - | |
| 571 | -Deutsch Informational [Page 10] | |
| 572 | - | |
| 573 | - | |
| 574 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 575 | - | |
| 576 | - | |
| 577 | -7. Appendix: Jean-Loup Gailly's gzip utility | |
| 578 | - | |
| 579 | - The most widely used implementation of gzip compression, and the | |
| 580 | - original documentation on which this specification is based, were | |
| 581 | - created by Jean-Loup Gailly <[email protected]>. Since this | |
| 582 | - implementation is a de facto standard, we mention some more of its | |
| 583 | - features here. Again, the material in this section is not part of | |
| 584 | - the specification per se, and implementations need not follow it to | |
| 585 | - be compliant. | |
| 586 | - | |
| 587 | - When compressing or decompressing a file, gzip preserves the | |
| 588 | - protection, ownership, and modification time attributes on the local | |
| 589 | - file system, since there is no provision for representing protection | |
| 590 | - attributes in the gzip file format itself. Since the file format | |
| 591 | - includes a modification time, the gzip decompressor provides a | |
| 592 | - command line switch that assigns the modification time from the file, | |
| 593 | - rather than the local modification time of the compressed input, to | |
| 594 | - the decompressed output. | |
| 595 | - | |
| 596 | -8. Appendix: Sample CRC Code | |
| 597 | - | |
| 598 | - The following sample code represents a practical implementation of | |
| 599 | - the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 | |
| 600 | - for a formal specification.) | |
| 601 | - | |
| 602 | - The sample code is in the ANSI C programming language. Non C users | |
| 603 | - may find it easier to read with these hints: | |
| 604 | - | |
| 605 | - & Bitwise AND operator. | |
| 606 | - ^ Bitwise exclusive-OR operator. | |
| 607 | - >> Bitwise right shift operator. When applied to an | |
| 608 | - unsigned quantity, as here, right shift inserts zero | |
| 609 | - bit(s) at the left. | |
| 610 | - ! Logical NOT operator. | |
| 611 | - ++ "n++" increments the variable n. | |
| 612 | - 0xNNN 0x introduces a hexadecimal (base 16) constant. | |
| 613 | - Suffix L indicates a long value (at least 32 bits). | |
| 614 | - | |
| 615 | - /* Table of CRCs of all 8-bit messages. */ | |
| 616 | - unsigned long crc_table[256]; | |
| 617 | - | |
| 618 | - /* Flag: has the table been computed? Initially false. */ | |
| 619 | - int crc_table_computed = 0; | |
| 620 | - | |
| 621 | - /* Make the table for a fast CRC. */ | |
| 622 | - void make_crc_table(void) | |
| 623 | - { | |
| 624 | - unsigned long c; | |
| 625 | - | |
| 626 | - | |
| 627 | - | |
| 628 | -Deutsch Informational [Page 11] | |
| 629 | - | |
| 630 | - | |
| 631 | -RFC 1952 GZIP File Format Specification May 1996 | |
| 632 | - | |
| 633 | - | |
| 634 | - int n, k; | |
| 635 | - for (n = 0; n < 256; n++) { | |
| 636 | - c = (unsigned long) n; | |
| 637 | - for (k = 0; k < 8; k++) { | |
| 638 | - if (c & 1) { | |
| 639 | - c = 0xedb88320L ^ (c >> 1); | |
| 640 | - } else { | |
| 641 | - c = c >> 1; | |
| 642 | - } | |
| 643 | - } | |
| 644 | - crc_table[n] = c; | |
| 645 | - } | |
| 646 | - crc_table_computed = 1; | |
| 647 | - } | |
| 648 | - | |
| 649 | - /* | |
| 650 | - Update a running crc with the bytes buf[0..len-1] and return | |
| 651 | - the updated crc. The crc should be initialized to zero. Pre- and | |
| 652 | - post-conditioning (one's complement) is performed within this | |
| 653 | - function so it shouldn't be done by the caller. Usage example: | |
| 654 | - | |
| 655 | - unsigned long crc = 0L; | |
| 656 | - | |
| 657 | - while (read_buffer(buffer, length) != EOF) { | |
| 658 | - crc = update_crc(crc, buffer, length); | |
| 659 | - } | |
| 660 | - if (crc != original_crc) error(); | |
| 661 | - */ | |
| 662 | - unsigned long update_crc(unsigned long crc, | |
| 663 | - unsigned char *buf, int len) | |
| 664 | - { | |
| 665 | - unsigned long c = crc ^ 0xffffffffL; | |
| 666 | - int n; | |
| 667 | - | |
| 668 | - if (!crc_table_computed) | |
| 669 | - make_crc_table(); | |
| 670 | - for (n = 0; n < len; n++) { | |
| 671 | - c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); | |
| 672 | - } | |
| 673 | - return c ^ 0xffffffffL; | |
| 674 | - } | |
| 675 | - | |
| 676 | - /* Return the CRC of the bytes buf[0..len-1]. */ | |
| 677 | - unsigned long crc(unsigned char *buf, int len) | |
| 678 | - { | |
| 679 | - return update_crc(0L, buf, len); | |
| 680 | - } | |
| 681 | - | |
| 682 | - | |
| 683 | - | |
| 684 | - | |
| 685 | -Deutsch Informational [Page 12] | |
| 686 | - | |
| 687 | - |
| --- a/compat/zlib/doc/rfc1952.txt | |
| +++ b/compat/zlib/doc/rfc1952.txt | |
| @@ -1,687 +0,0 @@ | |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | Network Working Group P. Deutsch |
| 8 | Request for Comments: 1952 Aladdin Enterprises |
| 9 | Category: Informational May 1996 |
| 10 | |
| 11 | |
| 12 | GZIP file format specification version 4.3 |
| 13 | |
| 14 | Status of This Memo |
| 15 | |
| 16 | This memo provides information for the Internet community. This memo |
| 17 | does not specify an Internet standard of any kind. Distribution of |
| 18 | this memo is unlimited. |
| 19 | |
| 20 | IESG Note: |
| 21 | |
| 22 | The IESG takes no position on the validity of any Intellectual |
| 23 | Property Rights statements contained in this document. |
| 24 | |
| 25 | Notices |
| 26 | |
| 27 | Copyright (c) 1996 L. Peter Deutsch |
| 28 | |
| 29 | Permission is granted to copy and distribute this document for any |
| 30 | purpose and without charge, including translations into other |
| 31 | languages and incorporation into compilations, provided that the |
| 32 | copyright notice and this notice are preserved, and that any |
| 33 | substantive changes or deletions from the original are clearly |
| 34 | marked. |
| 35 | |
| 36 | A pointer to the latest version of this and related documentation in |
| 37 | HTML format can be found at the URL |
| 38 | <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>. |
| 39 | |
| 40 | Abstract |
| 41 | |
| 42 | This specification defines a lossless compressed data format that is |
| 43 | compatible with the widely used GZIP utility. The format includes a |
| 44 | cyclic redundancy check value for detecting data corruption. The |
| 45 | format presently uses the DEFLATE method of compression but can be |
| 46 | easily extended to use other compression methods. The format can be |
| 47 | implemented readily in a manner not covered by patents. |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | Deutsch Informational [Page 1] |
| 59 | |
| 60 | |
| 61 | RFC 1952 GZIP File Format Specification May 1996 |
| 62 | |
| 63 | |
| 64 | Table of Contents |
| 65 | |
| 66 | 1. Introduction ................................................... 2 |
| 67 | 1.1. Purpose ................................................... 2 |
| 68 | 1.2. Intended audience ......................................... 3 |
| 69 | 1.3. Scope ..................................................... 3 |
| 70 | 1.4. Compliance ................................................ 3 |
| 71 | 1.5. Definitions of terms and conventions used ................. 3 |
| 72 | 1.6. Changes from previous versions ............................ 3 |
| 73 | 2. Detailed specification ......................................... 4 |
| 74 | 2.1. Overall conventions ....................................... 4 |
| 75 | 2.2. File format ............................................... 5 |
| 76 | 2.3. Member format ............................................. 5 |
| 77 | 2.3.1. Member header and trailer ........................... 6 |
| 78 | 2.3.1.1. Extra field ................................... 8 |
| 79 | 2.3.1.2. Compliance .................................... 9 |
| 80 | 3. References .................................................. 9 |
| 81 | 4. Security Considerations .................................... 10 |
| 82 | 5. Acknowledgements ........................................... 10 |
| 83 | 6. Author's Address ........................................... 10 |
| 84 | 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 |
| 85 | 8. Appendix: Sample CRC Code .................................. 11 |
| 86 | |
| 87 | 1. Introduction |
| 88 | |
| 89 | 1.1. Purpose |
| 90 | |
| 91 | The purpose of this specification is to define a lossless |
| 92 | compressed data format that: |
| 93 | |
| 94 | * Is independent of CPU type, operating system, file system, |
| 95 | and character set, and hence can be used for interchange; |
| 96 | * Can compress or decompress a data stream (as opposed to a |
| 97 | randomly accessible file) to produce another data stream, |
| 98 | using only an a priori bounded amount of intermediate |
| 99 | storage, and hence can be used in data communications or |
| 100 | similar structures such as Unix filters; |
| 101 | * Compresses data with efficiency comparable to the best |
| 102 | currently available general-purpose compression methods, |
| 103 | and in particular considerably better than the "compress" |
| 104 | program; |
| 105 | * Can be implemented readily in a manner not covered by |
| 106 | patents, and hence can be practiced freely; |
| 107 | * Is compatible with the file format produced by the current |
| 108 | widely used gzip utility, in that conforming decompressors |
| 109 | will be able to read data produced by the existing gzip |
| 110 | compressor. |
| 111 | |
| 112 | |
| 113 | |
| 114 | |
| 115 | Deutsch Informational [Page 2] |
| 116 | |
| 117 | |
| 118 | RFC 1952 GZIP File Format Specification May 1996 |
| 119 | |
| 120 | |
| 121 | The data format defined by this specification does not attempt to: |
| 122 | |
| 123 | * Provide random access to compressed data; |
| 124 | * Compress specialized data (e.g., raster graphics) as well as |
| 125 | the best currently available specialized algorithms. |
| 126 | |
| 127 | 1.2. Intended audience |
| 128 | |
| 129 | This specification is intended for use by implementors of software |
| 130 | to compress data into gzip format and/or decompress data from gzip |
| 131 | format. |
| 132 | |
| 133 | The text of the specification assumes a basic background in |
| 134 | programming at the level of bits and other primitive data |
| 135 | representations. |
| 136 | |
| 137 | 1.3. Scope |
| 138 | |
| 139 | The specification specifies a compression method and a file format |
| 140 | (the latter assuming only that a file can store a sequence of |
| 141 | arbitrary bytes). It does not specify any particular interface to |
| 142 | a file system or anything about character sets or encodings |
| 143 | (except for file names and comments, which are optional). |
| 144 | |
| 145 | 1.4. Compliance |
| 146 | |
| 147 | Unless otherwise indicated below, a compliant decompressor must be |
| 148 | able to accept and decompress any file that conforms to all the |
| 149 | specifications presented here; a compliant compressor must produce |
| 150 | files that conform to all the specifications presented here. The |
| 151 | material in the appendices is not part of the specification per se |
| 152 | and is not relevant to compliance. |
| 153 | |
| 154 | 1.5. Definitions of terms and conventions used |
| 155 | |
| 156 | byte: 8 bits stored or transmitted as a unit (same as an octet). |
| 157 | (For this specification, a byte is exactly 8 bits, even on |
| 158 | machines which store a character on a number of bits different |
| 159 | from 8.) See below for the numbering of bits within a byte. |
| 160 | |
| 161 | 1.6. Changes from previous versions |
| 162 | |
| 163 | There have been no technical changes to the gzip format since |
| 164 | version 4.1 of this specification. In version 4.2, some |
| 165 | terminology was changed, and the sample CRC code was rewritten for |
| 166 | clarity and to eliminate the requirement for the caller to do pre- |
| 167 | and post-conditioning. Version 4.3 is a conversion of the |
| 168 | specification to RFC style. |
| 169 | |
| 170 | |
| 171 | |
| 172 | Deutsch Informational [Page 3] |
| 173 | |
| 174 | |
| 175 | RFC 1952 GZIP File Format Specification May 1996 |
| 176 | |
| 177 | |
| 178 | 2. Detailed specification |
| 179 | |
| 180 | 2.1. Overall conventions |
| 181 | |
| 182 | In the diagrams below, a box like this: |
| 183 | |
| 184 | +---+ |
| 185 | | | <-- the vertical bars might be missing |
| 186 | +---+ |
| 187 | |
| 188 | represents one byte; a box like this: |
| 189 | |
| 190 | +==============+ |
| 191 | | | |
| 192 | +==============+ |
| 193 | |
| 194 | represents a variable number of bytes. |
| 195 | |
| 196 | Bytes stored within a computer do not have a "bit order", since |
| 197 | they are always treated as a unit. However, a byte considered as |
| 198 | an integer between 0 and 255 does have a most- and least- |
| 199 | significant bit, and since we write numbers with the most- |
| 200 | significant digit on the left, we also write bytes with the most- |
| 201 | significant bit on the left. In the diagrams below, we number the |
| 202 | bits of a byte so that bit 0 is the least-significant bit, i.e., |
| 203 | the bits are numbered: |
| 204 | |
| 205 | +--------+ |
| 206 | |76543210| |
| 207 | +--------+ |
| 208 | |
| 209 | This document does not address the issue of the order in which |
| 210 | bits of a byte are transmitted on a bit-sequential medium, since |
| 211 | the data format described here is byte- rather than bit-oriented. |
| 212 | |
| 213 | Within a computer, a number may occupy multiple bytes. All |
| 214 | multi-byte numbers in the format described here are stored with |
| 215 | the least-significant byte first (at the lower memory address). |
| 216 | For example, the decimal number 520 is stored as: |
| 217 | |
| 218 | 0 1 |
| 219 | +--------+--------+ |
| 220 | |00001000|00000010| |
| 221 | +--------+--------+ |
| 222 | ^ ^ |
| 223 | | | |
| 224 | | + more significant byte = 2 x 256 |
| 225 | + less significant byte = 8 |
| 226 | |
| 227 | |
| 228 | |
| 229 | Deutsch Informational [Page 4] |
| 230 | |
| 231 | |
| 232 | RFC 1952 GZIP File Format Specification May 1996 |
| 233 | |
| 234 | |
| 235 | 2.2. File format |
| 236 | |
| 237 | A gzip file consists of a series of "members" (compressed data |
| 238 | sets). The format of each member is specified in the following |
| 239 | section. The members simply appear one after another in the file, |
| 240 | with no additional information before, between, or after them. |
| 241 | |
| 242 | 2.3. Member format |
| 243 | |
| 244 | Each member has the following structure: |
| 245 | |
| 246 | +---+---+---+---+---+---+---+---+---+---+ |
| 247 | |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) |
| 248 | +---+---+---+---+---+---+---+---+---+---+ |
| 249 | |
| 250 | (if FLG.FEXTRA set) |
| 251 | |
| 252 | +---+---+=================================+ |
| 253 | | XLEN |...XLEN bytes of "extra field"...| (more-->) |
| 254 | +---+---+=================================+ |
| 255 | |
| 256 | (if FLG.FNAME set) |
| 257 | |
| 258 | +=========================================+ |
| 259 | |...original file name, zero-terminated...| (more-->) |
| 260 | +=========================================+ |
| 261 | |
| 262 | (if FLG.FCOMMENT set) |
| 263 | |
| 264 | +===================================+ |
| 265 | |...file comment, zero-terminated...| (more-->) |
| 266 | +===================================+ |
| 267 | |
| 268 | (if FLG.FHCRC set) |
| 269 | |
| 270 | +---+---+ |
| 271 | | CRC16 | |
| 272 | +---+---+ |
| 273 | |
| 274 | +=======================+ |
| 275 | |...compressed blocks...| (more-->) |
| 276 | +=======================+ |
| 277 | |
| 278 | 0 1 2 3 4 5 6 7 |
| 279 | +---+---+---+---+---+---+---+---+ |
| 280 | | CRC32 | ISIZE | |
| 281 | +---+---+---+---+---+---+---+---+ |
| 282 | |
| 283 | |
| 284 | |
| 285 | |
| 286 | Deutsch Informational [Page 5] |
| 287 | |
| 288 | |
| 289 | RFC 1952 GZIP File Format Specification May 1996 |
| 290 | |
| 291 | |
| 292 | 2.3.1. Member header and trailer |
| 293 | |
| 294 | ID1 (IDentification 1) |
| 295 | ID2 (IDentification 2) |
| 296 | These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 |
| 297 | (0x8b, \213), to identify the file as being in gzip format. |
| 298 | |
| 299 | CM (Compression Method) |
| 300 | This identifies the compression method used in the file. CM |
| 301 | = 0-7 are reserved. CM = 8 denotes the "deflate" |
| 302 | compression method, which is the one customarily used by |
| 303 | gzip and which is documented elsewhere. |
| 304 | |
| 305 | FLG (FLaGs) |
| 306 | This flag byte is divided into individual bits as follows: |
| 307 | |
| 308 | bit 0 FTEXT |
| 309 | bit 1 FHCRC |
| 310 | bit 2 FEXTRA |
| 311 | bit 3 FNAME |
| 312 | bit 4 FCOMMENT |
| 313 | bit 5 reserved |
| 314 | bit 6 reserved |
| 315 | bit 7 reserved |
| 316 | |
| 317 | If FTEXT is set, the file is probably ASCII text. This is |
| 318 | an optional indication, which the compressor may set by |
| 319 | checking a small amount of the input data to see whether any |
| 320 | non-ASCII characters are present. In case of doubt, FTEXT |
| 321 | is cleared, indicating binary data. For systems which have |
| 322 | different file formats for ascii text and binary data, the |
| 323 | decompressor can use FTEXT to choose the appropriate format. |
| 324 | We deliberately do not specify the algorithm used to set |
| 325 | this bit, since a compressor always has the option of |
| 326 | leaving it cleared and a decompressor always has the option |
| 327 | of ignoring it and letting some other program handle issues |
| 328 | of data conversion. |
| 329 | |
| 330 | If FHCRC is set, a CRC16 for the gzip header is present, |
| 331 | immediately before the compressed data. The CRC16 consists |
| 332 | of the two least significant bytes of the CRC32 for all |
| 333 | bytes of the gzip header up to and not including the CRC16. |
| 334 | [The FHCRC bit was never set by versions of gzip up to |
| 335 | 1.2.4, even though it was documented with a different |
| 336 | meaning in gzip 1.2.4.] |
| 337 | |
| 338 | If FEXTRA is set, optional extra fields are present, as |
| 339 | described in a following section. |
| 340 | |
| 341 | |
| 342 | |
| 343 | Deutsch Informational [Page 6] |
| 344 | |
| 345 | |
| 346 | RFC 1952 GZIP File Format Specification May 1996 |
| 347 | |
| 348 | |
| 349 | If FNAME is set, an original file name is present, |
| 350 | terminated by a zero byte. The name must consist of ISO |
| 351 | 8859-1 (LATIN-1) characters; on operating systems using |
| 352 | EBCDIC or any other character set for file names, the name |
| 353 | must be translated to the ISO LATIN-1 character set. This |
| 354 | is the original name of the file being compressed, with any |
| 355 | directory components removed, and, if the file being |
| 356 | compressed is on a file system with case insensitive names, |
| 357 | forced to lower case. There is no original file name if the |
| 358 | data was compressed from a source other than a named file; |
| 359 | for example, if the source was stdin on a Unix system, there |
| 360 | is no file name. |
| 361 | |
| 362 | If FCOMMENT is set, a zero-terminated file comment is |
| 363 | present. This comment is not interpreted; it is only |
| 364 | intended for human consumption. The comment must consist of |
| 365 | ISO 8859-1 (LATIN-1) characters. Line breaks should be |
| 366 | denoted by a single line feed character (10 decimal). |
| 367 | |
| 368 | Reserved FLG bits must be zero. |
| 369 | |
| 370 | MTIME (Modification TIME) |
| 371 | This gives the most recent modification time of the original |
| 372 | file being compressed. The time is in Unix format, i.e., |
| 373 | seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this |
| 374 | may cause problems for MS-DOS and other systems that use |
| 375 | local rather than Universal time.) If the compressed data |
| 376 | did not come from a file, MTIME is set to the time at which |
| 377 | compression started. MTIME = 0 means no time stamp is |
| 378 | available. |
| 379 | |
| 380 | XFL (eXtra FLags) |
| 381 | These flags are available for use by specific compression |
| 382 | methods. The "deflate" method (CM = 8) sets these flags as |
| 383 | follows: |
| 384 | |
| 385 | XFL = 2 - compressor used maximum compression, |
| 386 | slowest algorithm |
| 387 | XFL = 4 - compressor used fastest algorithm |
| 388 | |
| 389 | OS (Operating System) |
| 390 | This identifies the type of file system on which compression |
| 391 | took place. This may be useful in determining end-of-line |
| 392 | convention for text files. The currently defined values are |
| 393 | as follows: |
| 394 | |
| 395 | |
| 396 | |
| 397 | |
| 398 | |
| 399 | |
| 400 | Deutsch Informational [Page 7] |
| 401 | |
| 402 | |
| 403 | RFC 1952 GZIP File Format Specification May 1996 |
| 404 | |
| 405 | |
| 406 | 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) |
| 407 | 1 - Amiga |
| 408 | 2 - VMS (or OpenVMS) |
| 409 | 3 - Unix |
| 410 | 4 - VM/CMS |
| 411 | 5 - Atari TOS |
| 412 | 6 - HPFS filesystem (OS/2, NT) |
| 413 | 7 - Macintosh |
| 414 | 8 - Z-System |
| 415 | 9 - CP/M |
| 416 | 10 - TOPS-20 |
| 417 | 11 - NTFS filesystem (NT) |
| 418 | 12 - QDOS |
| 419 | 13 - Acorn RISCOS |
| 420 | 255 - unknown |
| 421 | |
| 422 | XLEN (eXtra LENgth) |
| 423 | If FLG.FEXTRA is set, this gives the length of the optional |
| 424 | extra field. See below for details. |
| 425 | |
| 426 | CRC32 (CRC-32) |
| 427 | This contains a Cyclic Redundancy Check value of the |
| 428 | uncompressed data computed according to CRC-32 algorithm |
| 429 | used in the ISO 3309 standard and in section 8.1.1.6.2 of |
| 430 | ITU-T recommendation V.42. (See http://www.iso.ch for |
| 431 | ordering ISO documents. See gopher://info.itu.ch for an |
| 432 | online version of ITU-T V.42.) |
| 433 | |
| 434 | ISIZE (Input SIZE) |
| 435 | This contains the size of the original (uncompressed) input |
| 436 | data modulo 2^32. |
| 437 | |
| 438 | 2.3.1.1. Extra field |
| 439 | |
| 440 | If the FLG.FEXTRA bit is set, an "extra field" is present in |
| 441 | the header, with total length XLEN bytes. It consists of a |
| 442 | series of subfields, each of the form: |
| 443 | |
| 444 | +---+---+---+---+==================================+ |
| 445 | |SI1|SI2| LEN |... LEN bytes of subfield data ...| |
| 446 | +---+---+---+---+==================================+ |
| 447 | |
| 448 | SI1 and SI2 provide a subfield ID, typically two ASCII letters |
| 449 | with some mnemonic value. Jean-Loup Gailly |
| 450 | <[email protected]> is maintaining a registry of subfield |
| 451 | IDs; please send him any subfield ID you wish to use. Subfield |
| 452 | IDs with SI2 = 0 are reserved for future use. The following |
| 453 | IDs are currently defined: |
| 454 | |
| 455 | |
| 456 | |
| 457 | Deutsch Informational [Page 8] |
| 458 | |
| 459 | |
| 460 | RFC 1952 GZIP File Format Specification May 1996 |
| 461 | |
| 462 | |
| 463 | SI1 SI2 Data |
| 464 | ---------- ---------- ---- |
| 465 | 0x41 ('A') 0x70 ('P') Apollo file type information |
| 466 | |
| 467 | LEN gives the length of the subfield data, excluding the 4 |
| 468 | initial bytes. |
| 469 | |
| 470 | 2.3.1.2. Compliance |
| 471 | |
| 472 | A compliant compressor must produce files with correct ID1, |
| 473 | ID2, CM, CRC32, and ISIZE, but may set all the other fields in |
| 474 | the fixed-length part of the header to default values (255 for |
| 475 | OS, 0 for all others). The compressor must set all reserved |
| 476 | bits to zero. |
| 477 | |
| 478 | A compliant decompressor must check ID1, ID2, and CM, and |
| 479 | provide an error indication if any of these have incorrect |
| 480 | values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC |
| 481 | at least so it can skip over the optional fields if they are |
| 482 | present. It need not examine any other part of the header or |
| 483 | trailer; in particular, a decompressor may ignore FTEXT and OS |
| 484 | and always produce binary output, and still be compliant. A |
| 485 | compliant decompressor must give an error indication if any |
| 486 | reserved bit is non-zero, since such a bit could indicate the |
| 487 | presence of a new field that would cause subsequent data to be |
| 488 | interpreted incorrectly. |
| 489 | |
| 490 | 3. References |
| 491 | |
| 492 | [1] "Information Processing - 8-bit single-byte coded graphic |
| 493 | character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). |
| 494 | The ISO 8859-1 (Latin-1) character set is a superset of 7-bit |
| 495 | ASCII. Files defining this character set are available as |
| 496 | iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ |
| 497 | |
| 498 | [2] ISO 3309 |
| 499 | |
| 500 | [3] ITU-T recommendation V.42 |
| 501 | |
| 502 | [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", |
| 503 | available in ftp://ftp.uu.net/pub/archiving/zip/doc/ |
| 504 | |
| 505 | [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in |
| 506 | ftp://prep.ai.mit.edu/pub/gnu/ |
| 507 | |
| 508 | [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table |
| 509 | Look-Up", Communications of the ACM, 31(8), pp.1008-1013. |
| 510 | |
| 511 | |
| 512 | |
| 513 | |
| 514 | Deutsch Informational [Page 9] |
| 515 | |
| 516 | |
| 517 | RFC 1952 GZIP File Format Specification May 1996 |
| 518 | |
| 519 | |
| 520 | [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, |
| 521 | pp.118-133. |
| 522 | |
| 523 | [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, |
| 524 | describing the CRC concept. |
| 525 | |
| 526 | 4. Security Considerations |
| 527 | |
| 528 | Any data compression method involves the reduction of redundancy in |
| 529 | the data. Consequently, any corruption of the data is likely to have |
| 530 | severe effects and be difficult to correct. Uncompressed text, on |
| 531 | the other hand, will probably still be readable despite the presence |
| 532 | of some corrupted bytes. |
| 533 | |
| 534 | It is recommended that systems using this data format provide some |
| 535 | means of validating the integrity of the compressed data, such as by |
| 536 | setting and checking the CRC-32 check value. |
| 537 | |
| 538 | 5. Acknowledgements |
| 539 | |
| 540 | Trademarks cited in this document are the property of their |
| 541 | respective owners. |
| 542 | |
| 543 | Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, |
| 544 | the related software described in this specification. Glenn |
| 545 | Randers-Pehrson converted this document to RFC and HTML format. |
| 546 | |
| 547 | 6. Author's Address |
| 548 | |
| 549 | L. Peter Deutsch |
| 550 | Aladdin Enterprises |
| 551 | 203 Santa Margarita Ave. |
| 552 | Menlo Park, CA 94025 |
| 553 | |
| 554 | Phone: (415) 322-0103 (AM only) |
| 555 | FAX: (415) 322-1734 |
| 556 | EMail: <[email protected]> |
| 557 | |
| 558 | Questions about the technical content of this specification can be |
| 559 | sent by email to: |
| 560 | |
| 561 | Jean-Loup Gailly <[email protected]> and |
| 562 | Mark Adler <[email protected]> |
| 563 | |
| 564 | Editorial comments on this specification can be sent by email to: |
| 565 | |
| 566 | L. Peter Deutsch <[email protected]> and |
| 567 | Glenn Randers-Pehrson <[email protected]> |
| 568 | |
| 569 | |
| 570 | |
| 571 | Deutsch Informational [Page 10] |
| 572 | |
| 573 | |
| 574 | RFC 1952 GZIP File Format Specification May 1996 |
| 575 | |
| 576 | |
| 577 | 7. Appendix: Jean-Loup Gailly's gzip utility |
| 578 | |
| 579 | The most widely used implementation of gzip compression, and the |
| 580 | original documentation on which this specification is based, were |
| 581 | created by Jean-Loup Gailly <[email protected]>. Since this |
| 582 | implementation is a de facto standard, we mention some more of its |
| 583 | features here. Again, the material in this section is not part of |
| 584 | the specification per se, and implementations need not follow it to |
| 585 | be compliant. |
| 586 | |
| 587 | When compressing or decompressing a file, gzip preserves the |
| 588 | protection, ownership, and modification time attributes on the local |
| 589 | file system, since there is no provision for representing protection |
| 590 | attributes in the gzip file format itself. Since the file format |
| 591 | includes a modification time, the gzip decompressor provides a |
| 592 | command line switch that assigns the modification time from the file, |
| 593 | rather than the local modification time of the compressed input, to |
| 594 | the decompressed output. |
| 595 | |
| 596 | 8. Appendix: Sample CRC Code |
| 597 | |
| 598 | The following sample code represents a practical implementation of |
| 599 | the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 |
| 600 | for a formal specification.) |
| 601 | |
| 602 | The sample code is in the ANSI C programming language. Non C users |
| 603 | may find it easier to read with these hints: |
| 604 | |
| 605 | & Bitwise AND operator. |
| 606 | ^ Bitwise exclusive-OR operator. |
| 607 | >> Bitwise right shift operator. When applied to an |
| 608 | unsigned quantity, as here, right shift inserts zero |
| 609 | bit(s) at the left. |
| 610 | ! Logical NOT operator. |
| 611 | ++ "n++" increments the variable n. |
| 612 | 0xNNN 0x introduces a hexadecimal (base 16) constant. |
| 613 | Suffix L indicates a long value (at least 32 bits). |
| 614 | |
| 615 | /* Table of CRCs of all 8-bit messages. */ |
| 616 | unsigned long crc_table[256]; |
| 617 | |
| 618 | /* Flag: has the table been computed? Initially false. */ |
| 619 | int crc_table_computed = 0; |
| 620 | |
| 621 | /* Make the table for a fast CRC. */ |
| 622 | void make_crc_table(void) |
| 623 | { |
| 624 | unsigned long c; |
| 625 | |
| 626 | |
| 627 | |
| 628 | Deutsch Informational [Page 11] |
| 629 | |
| 630 | |
| 631 | RFC 1952 GZIP File Format Specification May 1996 |
| 632 | |
| 633 | |
| 634 | int n, k; |
| 635 | for (n = 0; n < 256; n++) { |
| 636 | c = (unsigned long) n; |
| 637 | for (k = 0; k < 8; k++) { |
| 638 | if (c & 1) { |
| 639 | c = 0xedb88320L ^ (c >> 1); |
| 640 | } else { |
| 641 | c = c >> 1; |
| 642 | } |
| 643 | } |
| 644 | crc_table[n] = c; |
| 645 | } |
| 646 | crc_table_computed = 1; |
| 647 | } |
| 648 | |
| 649 | /* |
| 650 | Update a running crc with the bytes buf[0..len-1] and return |
| 651 | the updated crc. The crc should be initialized to zero. Pre- and |
| 652 | post-conditioning (one's complement) is performed within this |
| 653 | function so it shouldn't be done by the caller. Usage example: |
| 654 | |
| 655 | unsigned long crc = 0L; |
| 656 | |
| 657 | while (read_buffer(buffer, length) != EOF) { |
| 658 | crc = update_crc(crc, buffer, length); |
| 659 | } |
| 660 | if (crc != original_crc) error(); |
| 661 | */ |
| 662 | unsigned long update_crc(unsigned long crc, |
| 663 | unsigned char *buf, int len) |
| 664 | { |
| 665 | unsigned long c = crc ^ 0xffffffffL; |
| 666 | int n; |
| 667 | |
| 668 | if (!crc_table_computed) |
| 669 | make_crc_table(); |
| 670 | for (n = 0; n < len; n++) { |
| 671 | c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); |
| 672 | } |
| 673 | return c ^ 0xffffffffL; |
| 674 | } |
| 675 | |
| 676 | /* Return the CRC of the bytes buf[0..len-1]. */ |
| 677 | unsigned long crc(unsigned char *buf, int len) |
| 678 | { |
| 679 | return update_crc(0L, buf, len); |
| 680 | } |
| 681 | |
| 682 | |
| 683 | |
| 684 | |
| 685 | Deutsch Informational [Page 12] |
| 686 | |
| 687 |
| --- a/compat/zlib/doc/rfc1952.txt | |
| +++ b/compat/zlib/doc/rfc1952.txt | |
| @@ -1,687 +0,0 @@ | |
D
compat/zlib/doc/txtvsbin.txt
-103
| --- a/compat/zlib/doc/txtvsbin.txt | ||
| +++ b/compat/zlib/doc/txtvsbin.txt | ||
| @@ -1,107 +0,0 @@ | ||
| 1 | -A Fast Method for Identifying Plain Text Files | |
| 2 | -============================================== | |
| 3 | - | |
| 4 | - | |
| 5 | -Introduction | |
| ------------- | ||
| 6 | - | |
| 7 | -Given a file coming from an unknown source, it is sometimes desirable | |
| 8 | -to find out whether the format of that file is plain text. Although | |
| 9 | -this may appear like a simple task, a fully accurate detection of the | |
| 10 | -file type requires heavy-duty semantic analysis on the file contents. | |
| 11 | -It is, however, possible to obtain satisfactory results by employing | |
| 12 | -various heuristics. | |
| 13 | - | |
| 14 | -Previous versions of PKZip and other zip-compatible compression tools | |
| 15 | -were using a crude detection scheme: if more than 80% (4/5) of the bytes | |
| 16 | -found in a certain buffer are within the range [7..127], the file is | |
| 17 | -labeled as plain text, otherwise it is labeled as binary. A prominent | |
| 18 | -limitation of this scheme is the restriction to Latin-based alphabets. | |
| 19 | -Other alphabets, like Greek, Cyrillic or Asian, make extensive use of | |
| 20 | -the bytes within the range [128..255], and texts using these alphabets | |
| 21 | -are most often misidentified by this scheme; in other words, the rate | |
| 22 | -of false negatives is sometimes too high, which means that the recall | |
| 23 | -is low. Another weakness of this scheme is a reduced precision, due to | |
| 24 | -the false positives that may occur when binary files containing large | |
| 25 | -amounts of textual characters are misidentified as plain text. | |
| 26 | - | |
| 27 | -In this article we propose a new, simple detection scheme that features | |
| 28 | -a much increased precision and a near-100% recall. This scheme is | |
| 29 | -designed to work on ASCII, Unicode and other ASCII-derived alphabets, | |
| 30 | -and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) | |
| 31 | -and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings | |
| 32 | -(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. | |
| 33 | - | |
| 34 | - | |
| 35 | -The Algorithm | |
| -------------- | ||
| 36 | - | |
| 37 | -The algorithm works by dividing the set of bytecodes [0..255] into three | |
| 38 | -categories: | |
| 39 | -- The white list of textual bytecodes: | |
| 40 | - 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. | |
| 41 | -- The gray list of tolerated bytecodes: | |
| 42 | - 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). | |
| 43 | -- The black list of undesired, non-textual bytecodes: | |
| 44 | - 0 (NUL) to 6, 14 to 31. | |
| 45 | - | |
| 46 | -If a file contains at least one byte that belongs to the white list and | |
| 47 | -no byte that belongs to the black list, then the file is categorized as | |
| 48 | -plain text; otherwise, it is categorized as binary. (The boundary case, | |
| 49 | -when the file is empty, automatically falls into the latter category.) | |
| 50 | - | |
| 51 | - | |
| 52 | -Rationale | |
| ---------- | ||
| 53 | - | |
| 54 | -The idea behind this algorithm relies on two observations. | |
| 55 | - | |
| 56 | -The first observation is that, although the full range of 7-bit codes | |
| 57 | -[0..127] is properly specified by the ASCII standard, most control | |
| 58 | -characters in the range [0..31] are not used in practice. The only | |
| 59 | -widely-used, almost universally-portable control codes are 9 (TAB), | |
| 60 | -10 (LF) and 13 (CR). There are a few more control codes that are | |
| 61 | -recognized on a reduced range of platforms and text viewers/editors: | |
| 62 | -7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these | |
| 63 | -codes are rarely (if ever) used alone, without being accompanied by | |
| 64 | -some printable text. Even the newer, portable text formats such as | |
| 65 | -XML avoid using control characters outside the list mentioned here. | |
| 66 | - | |
| 67 | -The second observation is that most of the binary files tend to contain | |
| 68 | -control characters, especially 0 (NUL). Even though the older text | |
| 69 | -detection schemes observe the presence of non-ASCII codes from the range | |
| 70 | -[128..255], the precision rarely has to suffer if this upper range is | |
| 71 | -labeled as textual, because the files that are genuinely binary tend to | |
| 72 | -contain both control characters and codes from the upper range. On the | |
| 73 | -other hand, the upper range needs to be labeled as textual, because it | |
| 74 | -is used by virtually all ASCII extensions. In particular, this range is | |
| 75 | -used for encoding non-Latin scripts. | |
| 76 | - | |
| 77 | -Since there is no counting involved, other than simply observing the | |
| 78 | -presence or the absence of some byte values, the algorithm produces | |
| 79 | -consistent results, regardless what alphabet encoding is being used. | |
| 80 | -(If counting were involved, it could be possible to obtain different | |
| 81 | -results on a text encoded, say, using ISO-8859-16 versus UTF-8.) | |
| 82 | - | |
| 83 | -There is an extra category of plain text files that are "polluted" with | |
| 84 | -one or more black-listed codes, either by mistake or by peculiar design | |
| 85 | -considerations. In such cases, a scheme that tolerates a small fraction | |
| 86 | -of black-listed codes would provide an increased recall (i.e. more true | |
| 87 | -positives). This, however, incurs a reduced precision overall, since | |
| 88 | -false positives are more likely to appear in binary files that contain | |
| 89 | -large chunks of textual data. Furthermore, "polluted" plain text should | |
| 90 | -be regarded as binary by general-purpose text detection schemes, because | |
| 91 | -general-purpose text processing algorithms might not be applicable. | |
| 92 | -Under this premise, it is safe to say that our detection method provides | |
| 93 | -a near-100% recall. | |
| 94 | - | |
| 95 | -Experiments have been run on many files coming from various platforms | |
| 96 | -and applications. We tried plain text files, system logs, source code, | |
| 97 | -formatted office documents, compiled object code, etc. The results | |
| 98 | -confirm the optimistic assumptions about the capabilities of this | |
| 99 | -algorithm. | |
| 100 | - | |
| 101 | - | |
| --- | ||
| 102 | -Cosmin Truta | |
| 103 | -Last updated: 2006-May-28 |
| --- a/compat/zlib/doc/txtvsbin.txt | |
| +++ b/compat/zlib/doc/txtvsbin.txt | |
| @@ -1,107 +0,0 @@ | |
| 1 | A Fast Method for Identifying Plain Text Files |
| 2 | ============================================== |
| 3 | |
| 4 | |
| 5 | Introduction |
| ------------- | |
| 6 | |
| 7 | Given a file coming from an unknown source, it is sometimes desirable |
| 8 | to find out whether the format of that file is plain text. Although |
| 9 | this may appear like a simple task, a fully accurate detection of the |
| 10 | file type requires heavy-duty semantic analysis on the file contents. |
| 11 | It is, however, possible to obtain satisfactory results by employing |
| 12 | various heuristics. |
| 13 | |
| 14 | Previous versions of PKZip and other zip-compatible compression tools |
| 15 | were using a crude detection scheme: if more than 80% (4/5) of the bytes |
| 16 | found in a certain buffer are within the range [7..127], the file is |
| 17 | labeled as plain text, otherwise it is labeled as binary. A prominent |
| 18 | limitation of this scheme is the restriction to Latin-based alphabets. |
| 19 | Other alphabets, like Greek, Cyrillic or Asian, make extensive use of |
| 20 | the bytes within the range [128..255], and texts using these alphabets |
| 21 | are most often misidentified by this scheme; in other words, the rate |
| 22 | of false negatives is sometimes too high, which means that the recall |
| 23 | is low. Another weakness of this scheme is a reduced precision, due to |
| 24 | the false positives that may occur when binary files containing large |
| 25 | amounts of textual characters are misidentified as plain text. |
| 26 | |
| 27 | In this article we propose a new, simple detection scheme that features |
| 28 | a much increased precision and a near-100% recall. This scheme is |
| 29 | designed to work on ASCII, Unicode and other ASCII-derived alphabets, |
| 30 | and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) |
| 31 | and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings |
| 32 | (UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. |
| 33 | |
| 34 | |
| 35 | The Algorithm |
| -------------- | |
| 36 | |
| 37 | The algorithm works by dividing the set of bytecodes [0..255] into three |
| 38 | categories: |
| 39 | - The white list of textual bytecodes: |
| 40 | 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. |
| 41 | - The gray list of tolerated bytecodes: |
| 42 | 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). |
| 43 | - The black list of undesired, non-textual bytecodes: |
| 44 | 0 (NUL) to 6, 14 to 31. |
| 45 | |
| 46 | If a file contains at least one byte that belongs to the white list and |
| 47 | no byte that belongs to the black list, then the file is categorized as |
| 48 | plain text; otherwise, it is categorized as binary. (The boundary case, |
| 49 | when the file is empty, automatically falls into the latter category.) |
| 50 | |
| 51 | |
| 52 | Rationale |
| ---------- | |
| 53 | |
| 54 | The idea behind this algorithm relies on two observations. |
| 55 | |
| 56 | The first observation is that, although the full range of 7-bit codes |
| 57 | [0..127] is properly specified by the ASCII standard, most control |
| 58 | characters in the range [0..31] are not used in practice. The only |
| 59 | widely-used, almost universally-portable control codes are 9 (TAB), |
| 60 | 10 (LF) and 13 (CR). There are a few more control codes that are |
| 61 | recognized on a reduced range of platforms and text viewers/editors: |
| 62 | 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these |
| 63 | codes are rarely (if ever) used alone, without being accompanied by |
| 64 | some printable text. Even the newer, portable text formats such as |
| 65 | XML avoid using control characters outside the list mentioned here. |
| 66 | |
| 67 | The second observation is that most of the binary files tend to contain |
| 68 | control characters, especially 0 (NUL). Even though the older text |
| 69 | detection schemes observe the presence of non-ASCII codes from the range |
| 70 | [128..255], the precision rarely has to suffer if this upper range is |
| 71 | labeled as textual, because the files that are genuinely binary tend to |
| 72 | contain both control characters and codes from the upper range. On the |
| 73 | other hand, the upper range needs to be labeled as textual, because it |
| 74 | is used by virtually all ASCII extensions. In particular, this range is |
| 75 | used for encoding non-Latin scripts. |
| 76 | |
| 77 | Since there is no counting involved, other than simply observing the |
| 78 | presence or the absence of some byte values, the algorithm produces |
| 79 | consistent results, regardless what alphabet encoding is being used. |
| 80 | (If counting were involved, it could be possible to obtain different |
| 81 | results on a text encoded, say, using ISO-8859-16 versus UTF-8.) |
| 82 | |
| 83 | There is an extra category of plain text files that are "polluted" with |
| 84 | one or more black-listed codes, either by mistake or by peculiar design |
| 85 | considerations. In such cases, a scheme that tolerates a small fraction |
| 86 | of black-listed codes would provide an increased recall (i.e. more true |
| 87 | positives). This, however, incurs a reduced precision overall, since |
| 88 | false positives are more likely to appear in binary files that contain |
| 89 | large chunks of textual data. Furthermore, "polluted" plain text should |
| 90 | be regarded as binary by general-purpose text detection schemes, because |
| 91 | general-purpose text processing algorithms might not be applicable. |
| 92 | Under this premise, it is safe to say that our detection method provides |
| 93 | a near-100% recall. |
| 94 | |
| 95 | Experiments have been run on many files coming from various platforms |
| 96 | and applications. We tried plain text files, system logs, source code, |
| 97 | formatted office documents, compiled object code, etc. The results |
| 98 | confirm the optimistic assumptions about the capabilities of this |
| 99 | algorithm. |
| 100 | |
| 101 | |
| --- | |
| 102 | Cosmin Truta |
| 103 | Last updated: 2006-May-28 |
| --- a/compat/zlib/doc/txtvsbin.txt | |
| +++ b/compat/zlib/doc/txtvsbin.txt | |
| @@ -1,107 +0,0 @@ | |
| ------------- | |
| -------------- | |
| ---------- | |
| --- | |
+1
-1
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | ** Copyright (c) 2010 D. Richard Hipp |
| 3 | 3 | ** |
| 4 | 4 | ** This program is free software; you can redistribute it and/or |
| 5 | 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | - | |
| 7 | +** | |
| 8 | 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | 9 | ** but without any warranty; without even the implied warranty of |
| 10 | 10 | ** merchantability or fitness for a particular purpose. |
| 11 | 11 | ** |
| 12 | 12 | ** Author contact information: |
| 13 | 13 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2010 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| 13 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2010 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | ** |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| 13 |
+9
-5
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | 3 | ** |
| 4 | 4 | ** This program is free software; you can redistribute it and/or |
| 5 | 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | - | |
| 7 | +** | |
| 8 | 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | 9 | ** but without any warranty; without even the implied warranty of |
| 10 | 10 | ** merchantability or fitness for a particular purpose. |
| 11 | 11 | ** |
| 12 | 12 | ** Author contact information: |
| @@ -647,15 +647,19 @@ | ||
| 647 | 647 | } |
| 648 | 648 | pFrom->iCursor = i; |
| 649 | 649 | } |
| 650 | 650 | |
| 651 | 651 | /* |
| 652 | -** Return true if the blob contains a valid UUID_SIZE-digit base16 identifier. | |
| 652 | +** Return true if the blob contains a valid base16 identifier artifact hash. | |
| 653 | +** | |
| 654 | +** The value returned is actually one of HNAME_SHA1 OR HNAME_K256 if the | |
| 655 | +** hash is valid. Both of these are non-zero and therefore "true". | |
| 656 | +** If the hash is not valid, then HNAME_ERROR is returned, which is zero or | |
| 657 | +** false. | |
| 653 | 658 | */ |
| 654 | -int blob_is_uuid(Blob *pBlob){ | |
| 655 | - return blob_size(pBlob)==UUID_SIZE | |
| 656 | - && validate16(blob_buffer(pBlob), UUID_SIZE); | |
| 659 | +int blob_is_hname(Blob *pBlob){ | |
| 660 | + return hname_validate(blob_buffer(pBlob), blob_size(pBlob)); | |
| 657 | 661 | } |
| 658 | 662 | |
| 659 | 663 | /* |
| 660 | 664 | ** Return true if the blob contains a valid filename |
| 661 | 665 | */ |
| 662 | 666 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| @@ -647,15 +647,19 @@ | |
| 647 | } |
| 648 | pFrom->iCursor = i; |
| 649 | } |
| 650 | |
| 651 | /* |
| 652 | ** Return true if the blob contains a valid UUID_SIZE-digit base16 identifier. |
| 653 | */ |
| 654 | int blob_is_uuid(Blob *pBlob){ |
| 655 | return blob_size(pBlob)==UUID_SIZE |
| 656 | && validate16(blob_buffer(pBlob), UUID_SIZE); |
| 657 | } |
| 658 | |
| 659 | /* |
| 660 | ** Return true if the blob contains a valid filename |
| 661 | */ |
| 662 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | ** |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| @@ -647,15 +647,19 @@ | |
| 647 | } |
| 648 | pFrom->iCursor = i; |
| 649 | } |
| 650 | |
| 651 | /* |
| 652 | ** Return true if the blob contains a valid base16 identifier artifact hash. |
| 653 | ** |
| 654 | ** The value returned is actually one of HNAME_SHA1 OR HNAME_K256 if the |
| 655 | ** hash is valid. Both of these are non-zero and therefore "true". |
| 656 | ** If the hash is not valid, then HNAME_ERROR is returned, which is zero or |
| 657 | ** false. |
| 658 | */ |
| 659 | int blob_is_hname(Blob *pBlob){ |
| 660 | return hname_validate(blob_buffer(pBlob), blob_size(pBlob)); |
| 661 | } |
| 662 | |
| 663 | /* |
| 664 | ** Return true if the blob contains a valid filename |
| 665 | */ |
| 666 |
+4
-4
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -315,11 +315,11 @@ | ||
| 315 | 315 | FileTreeNode *pSibling; /* Next element in the same subdirectory */ |
| 316 | 316 | FileTreeNode *pChild; /* List of child nodes */ |
| 317 | 317 | FileTreeNode *pLastChild; /* Last child on the pChild list */ |
| 318 | 318 | char *zName; /* Name of this entry. The "tail" */ |
| 319 | 319 | char *zFullName; /* Full pathname of this entry */ |
| 320 | - char *zUuid; /* SHA1 hash of this file. May be NULL. */ | |
| 320 | + char *zUuid; /* Artifact hash of this file. May be NULL. */ | |
| 321 | 321 | double mtime; /* Modification time for this entry */ |
| 322 | 322 | unsigned nFullName; /* Length of zFullName */ |
| 323 | 323 | unsigned iLevel; /* Levels of parent directories */ |
| 324 | 324 | }; |
| 325 | 325 | |
| @@ -345,11 +345,11 @@ | ||
| 345 | 345 | ** the tree to be constructed properly. |
| 346 | 346 | */ |
| 347 | 347 | static void tree_add_node( |
| 348 | 348 | FileTree *pTree, /* Tree into which nodes are added */ |
| 349 | 349 | const char *zPath, /* The full pathname of file to add */ |
| 350 | - const char *zUuid, /* UUID of the file. Might be NULL. */ | |
| 350 | + const char *zUuid, /* Hash of the file. Might be NULL. */ | |
| 351 | 351 | double mtime /* Modification time for this entry */ |
| 352 | 352 | ){ |
| 353 | 353 | int i; |
| 354 | 354 | FileTreeNode *pParent; /* Parent (directory) of the next node to insert */ |
| 355 | 355 | |
| @@ -368,20 +368,20 @@ | ||
| 368 | 368 | FileTreeNode *pNew; |
| 369 | 369 | int iStart = i; |
| 370 | 370 | int nByte; |
| 371 | 371 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 372 | 372 | nByte = sizeof(*pNew) + i + 1; |
| 373 | - if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; | |
| 373 | + if( zUuid!=0 && zPath[i]==0 ) nByte += HNAME_MAX+1; | |
| 374 | 374 | pNew = fossil_malloc( nByte ); |
| 375 | 375 | memset(pNew, 0, sizeof(*pNew)); |
| 376 | 376 | pNew->zFullName = (char*)&pNew[1]; |
| 377 | 377 | memcpy(pNew->zFullName, zPath, i); |
| 378 | 378 | pNew->zFullName[i] = 0; |
| 379 | 379 | pNew->nFullName = i; |
| 380 | 380 | if( zUuid!=0 && zPath[i]==0 ){ |
| 381 | 381 | pNew->zUuid = pNew->zFullName + i + 1; |
| 382 | - memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); | |
| 382 | + memcpy(pNew->zUuid, zUuid, strlen(zUuid)+1); | |
| 383 | 383 | } |
| 384 | 384 | pNew->zName = pNew->zFullName + iStart; |
| 385 | 385 | if( pTree->pLast ){ |
| 386 | 386 | pTree->pLast->pNext = pNew; |
| 387 | 387 | }else{ |
| 388 | 388 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -315,11 +315,11 @@ | |
| 315 | FileTreeNode *pSibling; /* Next element in the same subdirectory */ |
| 316 | FileTreeNode *pChild; /* List of child nodes */ |
| 317 | FileTreeNode *pLastChild; /* Last child on the pChild list */ |
| 318 | char *zName; /* Name of this entry. The "tail" */ |
| 319 | char *zFullName; /* Full pathname of this entry */ |
| 320 | char *zUuid; /* SHA1 hash of this file. May be NULL. */ |
| 321 | double mtime; /* Modification time for this entry */ |
| 322 | unsigned nFullName; /* Length of zFullName */ |
| 323 | unsigned iLevel; /* Levels of parent directories */ |
| 324 | }; |
| 325 | |
| @@ -345,11 +345,11 @@ | |
| 345 | ** the tree to be constructed properly. |
| 346 | */ |
| 347 | static void tree_add_node( |
| 348 | FileTree *pTree, /* Tree into which nodes are added */ |
| 349 | const char *zPath, /* The full pathname of file to add */ |
| 350 | const char *zUuid, /* UUID of the file. Might be NULL. */ |
| 351 | double mtime /* Modification time for this entry */ |
| 352 | ){ |
| 353 | int i; |
| 354 | FileTreeNode *pParent; /* Parent (directory) of the next node to insert */ |
| 355 | |
| @@ -368,20 +368,20 @@ | |
| 368 | FileTreeNode *pNew; |
| 369 | int iStart = i; |
| 370 | int nByte; |
| 371 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 372 | nByte = sizeof(*pNew) + i + 1; |
| 373 | if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; |
| 374 | pNew = fossil_malloc( nByte ); |
| 375 | memset(pNew, 0, sizeof(*pNew)); |
| 376 | pNew->zFullName = (char*)&pNew[1]; |
| 377 | memcpy(pNew->zFullName, zPath, i); |
| 378 | pNew->zFullName[i] = 0; |
| 379 | pNew->nFullName = i; |
| 380 | if( zUuid!=0 && zPath[i]==0 ){ |
| 381 | pNew->zUuid = pNew->zFullName + i + 1; |
| 382 | memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); |
| 383 | } |
| 384 | pNew->zName = pNew->zFullName + iStart; |
| 385 | if( pTree->pLast ){ |
| 386 | pTree->pLast->pNext = pNew; |
| 387 | }else{ |
| 388 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -315,11 +315,11 @@ | |
| 315 | FileTreeNode *pSibling; /* Next element in the same subdirectory */ |
| 316 | FileTreeNode *pChild; /* List of child nodes */ |
| 317 | FileTreeNode *pLastChild; /* Last child on the pChild list */ |
| 318 | char *zName; /* Name of this entry. The "tail" */ |
| 319 | char *zFullName; /* Full pathname of this entry */ |
| 320 | char *zUuid; /* Artifact hash of this file. May be NULL. */ |
| 321 | double mtime; /* Modification time for this entry */ |
| 322 | unsigned nFullName; /* Length of zFullName */ |
| 323 | unsigned iLevel; /* Levels of parent directories */ |
| 324 | }; |
| 325 | |
| @@ -345,11 +345,11 @@ | |
| 345 | ** the tree to be constructed properly. |
| 346 | */ |
| 347 | static void tree_add_node( |
| 348 | FileTree *pTree, /* Tree into which nodes are added */ |
| 349 | const char *zPath, /* The full pathname of file to add */ |
| 350 | const char *zUuid, /* Hash of the file. Might be NULL. */ |
| 351 | double mtime /* Modification time for this entry */ |
| 352 | ){ |
| 353 | int i; |
| 354 | FileTreeNode *pParent; /* Parent (directory) of the next node to insert */ |
| 355 | |
| @@ -368,20 +368,20 @@ | |
| 368 | FileTreeNode *pNew; |
| 369 | int iStart = i; |
| 370 | int nByte; |
| 371 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 372 | nByte = sizeof(*pNew) + i + 1; |
| 373 | if( zUuid!=0 && zPath[i]==0 ) nByte += HNAME_MAX+1; |
| 374 | pNew = fossil_malloc( nByte ); |
| 375 | memset(pNew, 0, sizeof(*pNew)); |
| 376 | pNew->zFullName = (char*)&pNew[1]; |
| 377 | memcpy(pNew->zFullName, zPath, i); |
| 378 | pNew->zFullName[i] = 0; |
| 379 | pNew->nFullName = i; |
| 380 | if( zUuid!=0 && zPath[i]==0 ){ |
| 381 | pNew->zUuid = pNew->zFullName + i + 1; |
| 382 | memcpy(pNew->zUuid, zUuid, strlen(zUuid)+1); |
| 383 | } |
| 384 | pNew->zName = pNew->zFullName + iStart; |
| 385 | if( pTree->pLast ){ |
| 386 | pTree->pLast->pNext = pNew; |
| 387 | }else{ |
| 388 |
+11
-16
| --- src/bundle.c | ||
| +++ src/bundle.c | ||
| @@ -35,11 +35,11 @@ | ||
| 35 | 35 | @ bcname TEXT, |
| 36 | 36 | @ bcvalue ANY |
| 37 | 37 | @ ); |
| 38 | 38 | @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| 39 | 39 | @ blobid INTEGER PRIMARY KEY, -- Blob ID |
| 40 | -@ uuid TEXT NOT NULL, -- SHA1 hash of expanded blob | |
| 40 | +@ uuid TEXT NOT NULL, -- hash of expanded blob | |
| 41 | 41 | @ sz INT NOT NULL, -- Size of blob after expansion |
| 42 | 42 | @ delta ANY, -- Delta compression basis, or NULL |
| 43 | 43 | @ notes TEXT, -- Description of content |
| 44 | 44 | @ data BLOB -- compressed content |
| 45 | 45 | @ ); |
| @@ -439,19 +439,19 @@ | ||
| 439 | 439 | " WHERE bix.delta=%d" |
| 440 | 440 | " AND bix.blobid=bblob.blobid;", |
| 441 | 441 | iSrc |
| 442 | 442 | ); |
| 443 | 443 | while( db_step(&q)==SQLITE_ROW ){ |
| 444 | - Blob h1, h2, c1, c2; | |
| 444 | + Blob h1, c1, c2; | |
| 445 | 445 | int rid; |
| 446 | 446 | blob_zero(&h1); |
| 447 | 447 | db_column_blob(&q, 0, &h1); |
| 448 | 448 | blob_zero(&c1); |
| 449 | 449 | db_column_blob(&q, 1, &c1); |
| 450 | 450 | blob_uncompress(&c1, &c1); |
| 451 | 451 | blob_zero(&c2); |
| 452 | - if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)==40 ){ | |
| 452 | + if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)>=HNAME_MIN ){ | |
| 453 | 453 | Blob basis; |
| 454 | 454 | rid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q", |
| 455 | 455 | db_column_text(&q,2)); |
| 456 | 456 | content_get(rid, &basis); |
| 457 | 457 | blob_delta_apply(&basis, &c1, &c2); |
| @@ -461,16 +461,13 @@ | ||
| 461 | 461 | blob_delta_apply(pBasis, &c1, &c2); |
| 462 | 462 | blob_reset(&c1); |
| 463 | 463 | }else{ |
| 464 | 464 | c2 = c1; |
| 465 | 465 | } |
| 466 | - sha1sum_blob(&c2, &h2); | |
| 467 | - if( blob_compare(&h1, &h2)!=0 ){ | |
| 468 | - fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", | |
| 469 | - blob_str(&h1), blob_str(&h2)); | |
| 466 | + if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){ | |
| 467 | + fossil_fatal("artifact hash error on %b", &h1); | |
| 470 | 468 | } |
| 471 | - blob_reset(&h2); | |
| 472 | 469 | rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv); |
| 473 | 470 | if( rid==0 ){ |
| 474 | 471 | fossil_fatal("%s", g.zErrMsg); |
| 475 | 472 | }else{ |
| 476 | 473 | if( !isPriv ) content_make_public(rid); |
| @@ -491,11 +488,11 @@ | ||
| 491 | 488 | static void bundle_extract_item( |
| 492 | 489 | int blobid, /* ID of the item to extract */ |
| 493 | 490 | Blob *pOut /* Write the content into this blob */ |
| 494 | 491 | ){ |
| 495 | 492 | Stmt q; |
| 496 | - Blob x, basis, h1, h2; | |
| 493 | + Blob x, basis, h1; | |
| 497 | 494 | static Bag busy; |
| 498 | 495 | |
| 499 | 496 | db_prepare(&q, "SELECT uuid, delta, data FROM bblob" |
| 500 | 497 | " WHERE blobid=%d", blobid); |
| 501 | 498 | if( db_step(&q)!=SQLITE_ROW ){ |
| @@ -525,17 +522,14 @@ | ||
| 525 | 522 | }else{ |
| 526 | 523 | *pOut = x; |
| 527 | 524 | } |
| 528 | 525 | blob_zero(&h1); |
| 529 | 526 | db_column_blob(&q, 0, &h1); |
| 530 | - sha1sum_blob(pOut, &h2); | |
| 531 | - if( blob_compare(&h1, &h2)!=0 ){ | |
| 532 | - fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", | |
| 533 | - blob_str(&h1), blob_str(&h2)); | |
| 527 | + if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){ | |
| 528 | + fossil_fatal("incorrect hash for artifact %b", &h1); | |
| 534 | 529 | } |
| 535 | 530 | blob_reset(&h1); |
| 536 | - blob_reset(&h2); | |
| 537 | 531 | bag_remove(&busy, blobid); |
| 538 | 532 | db_finalize(&q); |
| 539 | 533 | } |
| 540 | 534 | |
| 541 | 535 | /* fossil bundle cat BUNDLE UUID... |
| @@ -597,12 +591,13 @@ | ||
| 597 | 591 | ** repo, then the delta encodings cannot be decoded and the bundle cannot |
| 598 | 592 | ** be extracted. */ |
| 599 | 593 | zMissingDeltas = db_text(0, |
| 600 | 594 | "SELECT group_concat(substr(delta,1,10),' ')" |
| 601 | 595 | " FROM bblob" |
| 602 | - " WHERE typeof(delta)='text' AND length(delta)=40" | |
| 603 | - " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)"); | |
| 596 | + " WHERE typeof(delta)='text' AND length(delta)>=%d" | |
| 597 | + " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)", | |
| 598 | + HNAME_MIN); | |
| 604 | 599 | if( zMissingDeltas && zMissingDeltas[0] ){ |
| 605 | 600 | fossil_fatal("delta basis artifacts not found in repository: %s", |
| 606 | 601 | zMissingDeltas); |
| 607 | 602 | } |
| 608 | 603 | |
| 609 | 604 |
| --- src/bundle.c | |
| +++ src/bundle.c | |
| @@ -35,11 +35,11 @@ | |
| 35 | @ bcname TEXT, |
| 36 | @ bcvalue ANY |
| 37 | @ ); |
| 38 | @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| 39 | @ blobid INTEGER PRIMARY KEY, -- Blob ID |
| 40 | @ uuid TEXT NOT NULL, -- SHA1 hash of expanded blob |
| 41 | @ sz INT NOT NULL, -- Size of blob after expansion |
| 42 | @ delta ANY, -- Delta compression basis, or NULL |
| 43 | @ notes TEXT, -- Description of content |
| 44 | @ data BLOB -- compressed content |
| 45 | @ ); |
| @@ -439,19 +439,19 @@ | |
| 439 | " WHERE bix.delta=%d" |
| 440 | " AND bix.blobid=bblob.blobid;", |
| 441 | iSrc |
| 442 | ); |
| 443 | while( db_step(&q)==SQLITE_ROW ){ |
| 444 | Blob h1, h2, c1, c2; |
| 445 | int rid; |
| 446 | blob_zero(&h1); |
| 447 | db_column_blob(&q, 0, &h1); |
| 448 | blob_zero(&c1); |
| 449 | db_column_blob(&q, 1, &c1); |
| 450 | blob_uncompress(&c1, &c1); |
| 451 | blob_zero(&c2); |
| 452 | if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)==40 ){ |
| 453 | Blob basis; |
| 454 | rid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q", |
| 455 | db_column_text(&q,2)); |
| 456 | content_get(rid, &basis); |
| 457 | blob_delta_apply(&basis, &c1, &c2); |
| @@ -461,16 +461,13 @@ | |
| 461 | blob_delta_apply(pBasis, &c1, &c2); |
| 462 | blob_reset(&c1); |
| 463 | }else{ |
| 464 | c2 = c1; |
| 465 | } |
| 466 | sha1sum_blob(&c2, &h2); |
| 467 | if( blob_compare(&h1, &h2)!=0 ){ |
| 468 | fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", |
| 469 | blob_str(&h1), blob_str(&h2)); |
| 470 | } |
| 471 | blob_reset(&h2); |
| 472 | rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv); |
| 473 | if( rid==0 ){ |
| 474 | fossil_fatal("%s", g.zErrMsg); |
| 475 | }else{ |
| 476 | if( !isPriv ) content_make_public(rid); |
| @@ -491,11 +488,11 @@ | |
| 491 | static void bundle_extract_item( |
| 492 | int blobid, /* ID of the item to extract */ |
| 493 | Blob *pOut /* Write the content into this blob */ |
| 494 | ){ |
| 495 | Stmt q; |
| 496 | Blob x, basis, h1, h2; |
| 497 | static Bag busy; |
| 498 | |
| 499 | db_prepare(&q, "SELECT uuid, delta, data FROM bblob" |
| 500 | " WHERE blobid=%d", blobid); |
| 501 | if( db_step(&q)!=SQLITE_ROW ){ |
| @@ -525,17 +522,14 @@ | |
| 525 | }else{ |
| 526 | *pOut = x; |
| 527 | } |
| 528 | blob_zero(&h1); |
| 529 | db_column_blob(&q, 0, &h1); |
| 530 | sha1sum_blob(pOut, &h2); |
| 531 | if( blob_compare(&h1, &h2)!=0 ){ |
| 532 | fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", |
| 533 | blob_str(&h1), blob_str(&h2)); |
| 534 | } |
| 535 | blob_reset(&h1); |
| 536 | blob_reset(&h2); |
| 537 | bag_remove(&busy, blobid); |
| 538 | db_finalize(&q); |
| 539 | } |
| 540 | |
| 541 | /* fossil bundle cat BUNDLE UUID... |
| @@ -597,12 +591,13 @@ | |
| 597 | ** repo, then the delta encodings cannot be decoded and the bundle cannot |
| 598 | ** be extracted. */ |
| 599 | zMissingDeltas = db_text(0, |
| 600 | "SELECT group_concat(substr(delta,1,10),' ')" |
| 601 | " FROM bblob" |
| 602 | " WHERE typeof(delta)='text' AND length(delta)=40" |
| 603 | " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)"); |
| 604 | if( zMissingDeltas && zMissingDeltas[0] ){ |
| 605 | fossil_fatal("delta basis artifacts not found in repository: %s", |
| 606 | zMissingDeltas); |
| 607 | } |
| 608 | |
| 609 |
| --- src/bundle.c | |
| +++ src/bundle.c | |
| @@ -35,11 +35,11 @@ | |
| 35 | @ bcname TEXT, |
| 36 | @ bcvalue ANY |
| 37 | @ ); |
| 38 | @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| 39 | @ blobid INTEGER PRIMARY KEY, -- Blob ID |
| 40 | @ uuid TEXT NOT NULL, -- hash of expanded blob |
| 41 | @ sz INT NOT NULL, -- Size of blob after expansion |
| 42 | @ delta ANY, -- Delta compression basis, or NULL |
| 43 | @ notes TEXT, -- Description of content |
| 44 | @ data BLOB -- compressed content |
| 45 | @ ); |
| @@ -439,19 +439,19 @@ | |
| 439 | " WHERE bix.delta=%d" |
| 440 | " AND bix.blobid=bblob.blobid;", |
| 441 | iSrc |
| 442 | ); |
| 443 | while( db_step(&q)==SQLITE_ROW ){ |
| 444 | Blob h1, c1, c2; |
| 445 | int rid; |
| 446 | blob_zero(&h1); |
| 447 | db_column_blob(&q, 0, &h1); |
| 448 | blob_zero(&c1); |
| 449 | db_column_blob(&q, 1, &c1); |
| 450 | blob_uncompress(&c1, &c1); |
| 451 | blob_zero(&c2); |
| 452 | if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)>=HNAME_MIN ){ |
| 453 | Blob basis; |
| 454 | rid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q", |
| 455 | db_column_text(&q,2)); |
| 456 | content_get(rid, &basis); |
| 457 | blob_delta_apply(&basis, &c1, &c2); |
| @@ -461,16 +461,13 @@ | |
| 461 | blob_delta_apply(pBasis, &c1, &c2); |
| 462 | blob_reset(&c1); |
| 463 | }else{ |
| 464 | c2 = c1; |
| 465 | } |
| 466 | if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){ |
| 467 | fossil_fatal("artifact hash error on %b", &h1); |
| 468 | } |
| 469 | rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv); |
| 470 | if( rid==0 ){ |
| 471 | fossil_fatal("%s", g.zErrMsg); |
| 472 | }else{ |
| 473 | if( !isPriv ) content_make_public(rid); |
| @@ -491,11 +488,11 @@ | |
| 488 | static void bundle_extract_item( |
| 489 | int blobid, /* ID of the item to extract */ |
| 490 | Blob *pOut /* Write the content into this blob */ |
| 491 | ){ |
| 492 | Stmt q; |
| 493 | Blob x, basis, h1; |
| 494 | static Bag busy; |
| 495 | |
| 496 | db_prepare(&q, "SELECT uuid, delta, data FROM bblob" |
| 497 | " WHERE blobid=%d", blobid); |
| 498 | if( db_step(&q)!=SQLITE_ROW ){ |
| @@ -525,17 +522,14 @@ | |
| 522 | }else{ |
| 523 | *pOut = x; |
| 524 | } |
| 525 | blob_zero(&h1); |
| 526 | db_column_blob(&q, 0, &h1); |
| 527 | if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){ |
| 528 | fossil_fatal("incorrect hash for artifact %b", &h1); |
| 529 | } |
| 530 | blob_reset(&h1); |
| 531 | bag_remove(&busy, blobid); |
| 532 | db_finalize(&q); |
| 533 | } |
| 534 | |
| 535 | /* fossil bundle cat BUNDLE UUID... |
| @@ -597,12 +591,13 @@ | |
| 591 | ** repo, then the delta encodings cannot be decoded and the bundle cannot |
| 592 | ** be extracted. */ |
| 593 | zMissingDeltas = db_text(0, |
| 594 | "SELECT group_concat(substr(delta,1,10),' ')" |
| 595 | " FROM bblob" |
| 596 | " WHERE typeof(delta)='text' AND length(delta)>=%d" |
| 597 | " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)", |
| 598 | HNAME_MIN); |
| 599 | if( zMissingDeltas && zMissingDeltas[0] ){ |
| 600 | fossil_fatal("delta basis artifacts not found in repository: %s", |
| 601 | zMissingDeltas); |
| 602 | } |
| 603 | |
| 604 |
+2
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1444,10 +1444,12 @@ | ||
| 1444 | 1444 | cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal); |
| 1445 | 1445 | }else if( fossil_strcmp(zFieldName,"referer:")==0 ){ |
| 1446 | 1446 | cgi_setenv("HTTP_REFERER", zVal); |
| 1447 | 1447 | }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){ |
| 1448 | 1448 | cgi_setenv("HTTP_USER_AGENT", zVal); |
| 1449 | + }else if( fossil_strcmp(zFieldName,"authorization:")==0 ){ | |
| 1450 | + cgi_setenv("HTTP_AUTHORIZATION", zVal); | |
| 1449 | 1451 | }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){ |
| 1450 | 1452 | const char *zIpAddr = cgi_accept_forwarded_for(zVal); |
| 1451 | 1453 | if( zIpAddr!=0 ){ |
| 1452 | 1454 | g.zIpAddr = mprintf("%s", zIpAddr); |
| 1453 | 1455 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); |
| 1454 | 1456 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1444,10 +1444,12 @@ | |
| 1444 | cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal); |
| 1445 | }else if( fossil_strcmp(zFieldName,"referer:")==0 ){ |
| 1446 | cgi_setenv("HTTP_REFERER", zVal); |
| 1447 | }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){ |
| 1448 | cgi_setenv("HTTP_USER_AGENT", zVal); |
| 1449 | }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){ |
| 1450 | const char *zIpAddr = cgi_accept_forwarded_for(zVal); |
| 1451 | if( zIpAddr!=0 ){ |
| 1452 | g.zIpAddr = mprintf("%s", zIpAddr); |
| 1453 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); |
| 1454 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1444,10 +1444,12 @@ | |
| 1444 | cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal); |
| 1445 | }else if( fossil_strcmp(zFieldName,"referer:")==0 ){ |
| 1446 | cgi_setenv("HTTP_REFERER", zVal); |
| 1447 | }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){ |
| 1448 | cgi_setenv("HTTP_USER_AGENT", zVal); |
| 1449 | }else if( fossil_strcmp(zFieldName,"authorization:")==0 ){ |
| 1450 | cgi_setenv("HTTP_AUTHORIZATION", zVal); |
| 1451 | }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){ |
| 1452 | const char *zIpAddr = cgi_accept_forwarded_for(zVal); |
| 1453 | if( zIpAddr!=0 ){ |
| 1454 | g.zIpAddr = mprintf("%s", zIpAddr); |
| 1455 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); |
| 1456 |
+12
-10
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -377,11 +377,11 @@ | ||
| 377 | 377 | ** As a special case, the --no-merge option does not inhibit this default. |
| 378 | 378 | ** This default shows exactly the set of changes that would be checked |
| 379 | 379 | ** in by the commit command. |
| 380 | 380 | ** |
| 381 | 381 | ** If no filter options are used, or if the --merge option is used, the |
| 382 | -** SHA1 hash of each merge contributor check-in version is displayed at | |
| 382 | +** artifact hash of each merge contributor check-in version is displayed at | |
| 383 | 383 | ** the end of the report. The --no-merge option is useful to display the |
| 384 | 384 | ** default set of changed files without the merge contributors. |
| 385 | 385 | ** |
| 386 | 386 | ** If change type classification is enabled, each output line starts with |
| 387 | 387 | ** a code describing the file's change type, e.g. EDITED or RENAMED. It |
| @@ -412,11 +412,11 @@ | ||
| 412 | 412 | ** |
| 413 | 413 | ** General options: |
| 414 | 414 | ** --abs-paths Display absolute pathnames. |
| 415 | 415 | ** --rel-paths Display pathnames relative to the current working |
| 416 | 416 | ** directory. |
| 417 | -** --sha1sum Verify file status using SHA1 hashing rather than | |
| 417 | +** --hash Verify file status using hashing rather than | |
| 418 | 418 | ** relying on file mtimes. |
| 419 | 419 | ** --case-sensitive <BOOL> Override case-sensitive setting. |
| 420 | 420 | ** --dotfiles Include unmanaged files beginning with a dot. |
| 421 | 421 | ** --ignore <CSG> Ignore unmanaged files matching CSG glob patterns. |
| 422 | 422 | ** --no-dir-symlinks Disables support for directory symlinks. |
| @@ -464,11 +464,12 @@ | ||
| 464 | 464 | {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY }, |
| 465 | 465 | }; |
| 466 | 466 | |
| 467 | 467 | Blob report = BLOB_INITIALIZER; |
| 468 | 468 | enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES; |
| 469 | - int useSha1sum = find_option("sha1sum", 0, 0)!=0; | |
| 469 | + /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */ | |
| 470 | + int useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0; | |
| 470 | 471 | int showHdr = command==CHANGES && find_option("header", 0, 0); |
| 471 | 472 | int verboseFlag = command==CHANGES && find_option("verbose", "v", 0); |
| 472 | 473 | const char *zIgnoreFlag = find_option("ignore", 0, 1); |
| 473 | 474 | unsigned scanFlags = 0; |
| 474 | 475 | unsigned flags = 0; |
| @@ -528,11 +529,11 @@ | ||
| 528 | 529 | |
| 529 | 530 | /* We should be done with options. */ |
| 530 | 531 | verify_all_options(); |
| 531 | 532 | |
| 532 | 533 | /* Check for changed files. */ |
| 533 | - vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0); | |
| 534 | + vfile_check_signature(vid, useHash ? CKSIG_HASH : 0); | |
| 534 | 535 | |
| 535 | 536 | /* Search for unmanaged files if requested. */ |
| 536 | 537 | if( flags & C_EXTRA ){ |
| 537 | 538 | Glob *pIgnore = glob_create(zIgnoreFlag); |
| 538 | 539 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| @@ -1985,12 +1986,12 @@ | ||
| 1985 | 1986 | ** The --private option creates a private check-in that is never synced. |
| 1986 | 1987 | ** Children of private check-ins are automatically private. |
| 1987 | 1988 | ** |
| 1988 | 1989 | ** The --tag option applies the symbolic tag name to the check-in. |
| 1989 | 1990 | ** |
| 1990 | -** The --sha1sum option detects edited files by computing each file's | |
| 1991 | -** SHA1 hash rather than just checking for changes to its size or mtime. | |
| 1991 | +** The --hash option detects edited files by computing each file's | |
| 1992 | +** artifact hash rather than just checking for changes to its size or mtime. | |
| 1992 | 1993 | ** |
| 1993 | 1994 | ** Options: |
| 1994 | 1995 | ** --allow-conflict allow unresolved merge conflicts |
| 1995 | 1996 | ** --allow-empty allow a commit with no changes |
| 1996 | 1997 | ** --allow-fork allow the commit to fork |
| @@ -2010,11 +2011,11 @@ | ||
| 2010 | 2011 | ** input and assumes an answer of 'No' for every |
| 2011 | 2012 | ** question. |
| 2012 | 2013 | ** --no-warnings omit all warnings about file contents |
| 2013 | 2014 | ** --nosign do not attempt to sign this commit with gpg |
| 2014 | 2015 | ** --private do not sync changes and their descendants |
| 2015 | -** --sha1sum verify file status using SHA1 hashing rather | |
| 2016 | +** --hash verify file status using hashing rather | |
| 2016 | 2017 | ** than relying on file mtimes |
| 2017 | 2018 | ** --tag TAG-NAME assign given tag TAG-NAME to the check-in |
| 2018 | 2019 | ** --date-override DATETIME DATE to use instead of 'now' |
| 2019 | 2020 | ** --user-override USER USER to use instead of the current default |
| 2020 | 2021 | ** |
| @@ -2033,11 +2034,11 @@ | ||
| 2033 | 2034 | int nvid; /* Blob-id of the new check-in */ |
| 2034 | 2035 | Blob comment; /* Check-in comment */ |
| 2035 | 2036 | const char *zComment; /* Check-in comment */ |
| 2036 | 2037 | Stmt q; /* Various queries */ |
| 2037 | 2038 | char *zUuid; /* UUID of the new check-in */ |
| 2038 | - int useSha1sum = 0; /* True to verify file status using SHA1 hashing */ | |
| 2039 | + int useHash = 0; /* True to verify file status using hashing */ | |
| 2039 | 2040 | int noSign = 0; /* True to omit signing the manifest using GPG */ |
| 2040 | 2041 | int isAMerge = 0; /* True if checking in a merge */ |
| 2041 | 2042 | int noWarningFlag = 0; /* True if skipping all warnings */ |
| 2042 | 2043 | int noPrompt = 0; /* True if skipping all prompts */ |
| 2043 | 2044 | int forceFlag = 0; /* Undocumented: Disables all checks */ |
| @@ -2068,11 +2069,12 @@ | ||
| 2068 | 2069 | Blob ans; |
| 2069 | 2070 | char cReply; |
| 2070 | 2071 | |
| 2071 | 2072 | memset(&sCiInfo, 0, sizeof(sCiInfo)); |
| 2072 | 2073 | url_proxy_options(); |
| 2073 | - useSha1sum = find_option("sha1sum", 0, 0)!=0; | |
| 2074 | + /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */ | |
| 2075 | + useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0; | |
| 2074 | 2076 | noSign = find_option("nosign",0,0)!=0; |
| 2075 | 2077 | forceDelta = find_option("delta",0,0)!=0; |
| 2076 | 2078 | forceBaseline = find_option("baseline",0,0)!=0; |
| 2077 | 2079 | if( forceDelta && forceBaseline ){ |
| 2078 | 2080 | fossil_fatal("cannot use --delta and --baseline together"); |
| @@ -2232,11 +2234,11 @@ | ||
| 2232 | 2234 | */ |
| 2233 | 2235 | if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ |
| 2234 | 2236 | fossil_fatal("no such user: %s", g.zLogin); |
| 2235 | 2237 | } |
| 2236 | 2238 | |
| 2237 | - hasChanges = unsaved_changes(useSha1sum ? CKSIG_SHA1 : 0); | |
| 2239 | + hasChanges = unsaved_changes(useHash ? CKSIG_HASH : 0); | |
| 2238 | 2240 | db_begin_transaction(); |
| 2239 | 2241 | db_record_repository_filename(0); |
| 2240 | 2242 | if( hasChanges==0 && !isAMerge && !allowEmpty && !forceFlag ){ |
| 2241 | 2243 | fossil_fatal("nothing has changed; use --allow-empty to override"); |
| 2242 | 2244 | } |
| 2243 | 2245 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -377,11 +377,11 @@ | |
| 377 | ** As a special case, the --no-merge option does not inhibit this default. |
| 378 | ** This default shows exactly the set of changes that would be checked |
| 379 | ** in by the commit command. |
| 380 | ** |
| 381 | ** If no filter options are used, or if the --merge option is used, the |
| 382 | ** SHA1 hash of each merge contributor check-in version is displayed at |
| 383 | ** the end of the report. The --no-merge option is useful to display the |
| 384 | ** default set of changed files without the merge contributors. |
| 385 | ** |
| 386 | ** If change type classification is enabled, each output line starts with |
| 387 | ** a code describing the file's change type, e.g. EDITED or RENAMED. It |
| @@ -412,11 +412,11 @@ | |
| 412 | ** |
| 413 | ** General options: |
| 414 | ** --abs-paths Display absolute pathnames. |
| 415 | ** --rel-paths Display pathnames relative to the current working |
| 416 | ** directory. |
| 417 | ** --sha1sum Verify file status using SHA1 hashing rather than |
| 418 | ** relying on file mtimes. |
| 419 | ** --case-sensitive <BOOL> Override case-sensitive setting. |
| 420 | ** --dotfiles Include unmanaged files beginning with a dot. |
| 421 | ** --ignore <CSG> Ignore unmanaged files matching CSG glob patterns. |
| 422 | ** --no-dir-symlinks Disables support for directory symlinks. |
| @@ -464,11 +464,12 @@ | |
| 464 | {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY }, |
| 465 | }; |
| 466 | |
| 467 | Blob report = BLOB_INITIALIZER; |
| 468 | enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES; |
| 469 | int useSha1sum = find_option("sha1sum", 0, 0)!=0; |
| 470 | int showHdr = command==CHANGES && find_option("header", 0, 0); |
| 471 | int verboseFlag = command==CHANGES && find_option("verbose", "v", 0); |
| 472 | const char *zIgnoreFlag = find_option("ignore", 0, 1); |
| 473 | unsigned scanFlags = 0; |
| 474 | unsigned flags = 0; |
| @@ -528,11 +529,11 @@ | |
| 528 | |
| 529 | /* We should be done with options. */ |
| 530 | verify_all_options(); |
| 531 | |
| 532 | /* Check for changed files. */ |
| 533 | vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0); |
| 534 | |
| 535 | /* Search for unmanaged files if requested. */ |
| 536 | if( flags & C_EXTRA ){ |
| 537 | Glob *pIgnore = glob_create(zIgnoreFlag); |
| 538 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| @@ -1985,12 +1986,12 @@ | |
| 1985 | ** The --private option creates a private check-in that is never synced. |
| 1986 | ** Children of private check-ins are automatically private. |
| 1987 | ** |
| 1988 | ** The --tag option applies the symbolic tag name to the check-in. |
| 1989 | ** |
| 1990 | ** The --sha1sum option detects edited files by computing each file's |
| 1991 | ** SHA1 hash rather than just checking for changes to its size or mtime. |
| 1992 | ** |
| 1993 | ** Options: |
| 1994 | ** --allow-conflict allow unresolved merge conflicts |
| 1995 | ** --allow-empty allow a commit with no changes |
| 1996 | ** --allow-fork allow the commit to fork |
| @@ -2010,11 +2011,11 @@ | |
| 2010 | ** input and assumes an answer of 'No' for every |
| 2011 | ** question. |
| 2012 | ** --no-warnings omit all warnings about file contents |
| 2013 | ** --nosign do not attempt to sign this commit with gpg |
| 2014 | ** --private do not sync changes and their descendants |
| 2015 | ** --sha1sum verify file status using SHA1 hashing rather |
| 2016 | ** than relying on file mtimes |
| 2017 | ** --tag TAG-NAME assign given tag TAG-NAME to the check-in |
| 2018 | ** --date-override DATETIME DATE to use instead of 'now' |
| 2019 | ** --user-override USER USER to use instead of the current default |
| 2020 | ** |
| @@ -2033,11 +2034,11 @@ | |
| 2033 | int nvid; /* Blob-id of the new check-in */ |
| 2034 | Blob comment; /* Check-in comment */ |
| 2035 | const char *zComment; /* Check-in comment */ |
| 2036 | Stmt q; /* Various queries */ |
| 2037 | char *zUuid; /* UUID of the new check-in */ |
| 2038 | int useSha1sum = 0; /* True to verify file status using SHA1 hashing */ |
| 2039 | int noSign = 0; /* True to omit signing the manifest using GPG */ |
| 2040 | int isAMerge = 0; /* True if checking in a merge */ |
| 2041 | int noWarningFlag = 0; /* True if skipping all warnings */ |
| 2042 | int noPrompt = 0; /* True if skipping all prompts */ |
| 2043 | int forceFlag = 0; /* Undocumented: Disables all checks */ |
| @@ -2068,11 +2069,12 @@ | |
| 2068 | Blob ans; |
| 2069 | char cReply; |
| 2070 | |
| 2071 | memset(&sCiInfo, 0, sizeof(sCiInfo)); |
| 2072 | url_proxy_options(); |
| 2073 | useSha1sum = find_option("sha1sum", 0, 0)!=0; |
| 2074 | noSign = find_option("nosign",0,0)!=0; |
| 2075 | forceDelta = find_option("delta",0,0)!=0; |
| 2076 | forceBaseline = find_option("baseline",0,0)!=0; |
| 2077 | if( forceDelta && forceBaseline ){ |
| 2078 | fossil_fatal("cannot use --delta and --baseline together"); |
| @@ -2232,11 +2234,11 @@ | |
| 2232 | */ |
| 2233 | if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ |
| 2234 | fossil_fatal("no such user: %s", g.zLogin); |
| 2235 | } |
| 2236 | |
| 2237 | hasChanges = unsaved_changes(useSha1sum ? CKSIG_SHA1 : 0); |
| 2238 | db_begin_transaction(); |
| 2239 | db_record_repository_filename(0); |
| 2240 | if( hasChanges==0 && !isAMerge && !allowEmpty && !forceFlag ){ |
| 2241 | fossil_fatal("nothing has changed; use --allow-empty to override"); |
| 2242 | } |
| 2243 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -377,11 +377,11 @@ | |
| 377 | ** As a special case, the --no-merge option does not inhibit this default. |
| 378 | ** This default shows exactly the set of changes that would be checked |
| 379 | ** in by the commit command. |
| 380 | ** |
| 381 | ** If no filter options are used, or if the --merge option is used, the |
| 382 | ** artifact hash of each merge contributor check-in version is displayed at |
| 383 | ** the end of the report. The --no-merge option is useful to display the |
| 384 | ** default set of changed files without the merge contributors. |
| 385 | ** |
| 386 | ** If change type classification is enabled, each output line starts with |
| 387 | ** a code describing the file's change type, e.g. EDITED or RENAMED. It |
| @@ -412,11 +412,11 @@ | |
| 412 | ** |
| 413 | ** General options: |
| 414 | ** --abs-paths Display absolute pathnames. |
| 415 | ** --rel-paths Display pathnames relative to the current working |
| 416 | ** directory. |
| 417 | ** --hash Verify file status using hashing rather than |
| 418 | ** relying on file mtimes. |
| 419 | ** --case-sensitive <BOOL> Override case-sensitive setting. |
| 420 | ** --dotfiles Include unmanaged files beginning with a dot. |
| 421 | ** --ignore <CSG> Ignore unmanaged files matching CSG glob patterns. |
| 422 | ** --no-dir-symlinks Disables support for directory symlinks. |
| @@ -464,11 +464,12 @@ | |
| 464 | {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY }, |
| 465 | }; |
| 466 | |
| 467 | Blob report = BLOB_INITIALIZER; |
| 468 | enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES; |
| 469 | /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */ |
| 470 | int useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0; |
| 471 | int showHdr = command==CHANGES && find_option("header", 0, 0); |
| 472 | int verboseFlag = command==CHANGES && find_option("verbose", "v", 0); |
| 473 | const char *zIgnoreFlag = find_option("ignore", 0, 1); |
| 474 | unsigned scanFlags = 0; |
| 475 | unsigned flags = 0; |
| @@ -528,11 +529,11 @@ | |
| 529 | |
| 530 | /* We should be done with options. */ |
| 531 | verify_all_options(); |
| 532 | |
| 533 | /* Check for changed files. */ |
| 534 | vfile_check_signature(vid, useHash ? CKSIG_HASH : 0); |
| 535 | |
| 536 | /* Search for unmanaged files if requested. */ |
| 537 | if( flags & C_EXTRA ){ |
| 538 | Glob *pIgnore = glob_create(zIgnoreFlag); |
| 539 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| @@ -1985,12 +1986,12 @@ | |
| 1986 | ** The --private option creates a private check-in that is never synced. |
| 1987 | ** Children of private check-ins are automatically private. |
| 1988 | ** |
| 1989 | ** The --tag option applies the symbolic tag name to the check-in. |
| 1990 | ** |
| 1991 | ** The --hash option detects edited files by computing each file's |
| 1992 | ** artifact hash rather than just checking for changes to its size or mtime. |
| 1993 | ** |
| 1994 | ** Options: |
| 1995 | ** --allow-conflict allow unresolved merge conflicts |
| 1996 | ** --allow-empty allow a commit with no changes |
| 1997 | ** --allow-fork allow the commit to fork |
| @@ -2010,11 +2011,11 @@ | |
| 2011 | ** input and assumes an answer of 'No' for every |
| 2012 | ** question. |
| 2013 | ** --no-warnings omit all warnings about file contents |
| 2014 | ** --nosign do not attempt to sign this commit with gpg |
| 2015 | ** --private do not sync changes and their descendants |
| 2016 | ** --hash verify file status using hashing rather |
| 2017 | ** than relying on file mtimes |
| 2018 | ** --tag TAG-NAME assign given tag TAG-NAME to the check-in |
| 2019 | ** --date-override DATETIME DATE to use instead of 'now' |
| 2020 | ** --user-override USER USER to use instead of the current default |
| 2021 | ** |
| @@ -2033,11 +2034,11 @@ | |
| 2034 | int nvid; /* Blob-id of the new check-in */ |
| 2035 | Blob comment; /* Check-in comment */ |
| 2036 | const char *zComment; /* Check-in comment */ |
| 2037 | Stmt q; /* Various queries */ |
| 2038 | char *zUuid; /* UUID of the new check-in */ |
| 2039 | int useHash = 0; /* True to verify file status using hashing */ |
| 2040 | int noSign = 0; /* True to omit signing the manifest using GPG */ |
| 2041 | int isAMerge = 0; /* True if checking in a merge */ |
| 2042 | int noWarningFlag = 0; /* True if skipping all warnings */ |
| 2043 | int noPrompt = 0; /* True if skipping all prompts */ |
| 2044 | int forceFlag = 0; /* Undocumented: Disables all checks */ |
| @@ -2068,11 +2069,12 @@ | |
| 2069 | Blob ans; |
| 2070 | char cReply; |
| 2071 | |
| 2072 | memset(&sCiInfo, 0, sizeof(sCiInfo)); |
| 2073 | url_proxy_options(); |
| 2074 | /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */ |
| 2075 | useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0; |
| 2076 | noSign = find_option("nosign",0,0)!=0; |
| 2077 | forceDelta = find_option("delta",0,0)!=0; |
| 2078 | forceBaseline = find_option("baseline",0,0)!=0; |
| 2079 | if( forceDelta && forceBaseline ){ |
| 2080 | fossil_fatal("cannot use --delta and --baseline together"); |
| @@ -2232,11 +2234,11 @@ | |
| 2234 | */ |
| 2235 | if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ |
| 2236 | fossil_fatal("no such user: %s", g.zLogin); |
| 2237 | } |
| 2238 | |
| 2239 | hasChanges = unsaved_changes(useHash ? CKSIG_HASH : 0); |
| 2240 | db_begin_transaction(); |
| 2241 | db_record_repository_filename(0); |
| 2242 | if( hasChanges==0 && !isAMerge && !allowEmpty && !forceFlag ){ |
| 2243 | fossil_fatal("nothing has changed; use --allow-empty to override"); |
| 2244 | } |
| 2245 |
+3
-6
| --- src/checkout.c | ||
| +++ src/checkout.c | ||
| @@ -134,24 +134,19 @@ | ||
| 134 | 134 | ** "manifest.tags". |
| 135 | 135 | */ |
| 136 | 136 | void manifest_to_disk(int vid){ |
| 137 | 137 | char *zManFile; |
| 138 | 138 | Blob manifest; |
| 139 | - Blob hash; | |
| 140 | 139 | Blob taglist; |
| 141 | 140 | int flg; |
| 142 | 141 | |
| 143 | 142 | flg = db_get_manifest_setting(); |
| 144 | 143 | |
| 145 | - if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ | |
| 144 | + if( flg & MFESTFLG_RAW ){ | |
| 146 | 145 | blob_zero(&manifest); |
| 147 | 146 | content_get(vid, &manifest); |
| 148 | - blob_zero(&hash); | |
| 149 | - sha1sum_blob(&manifest, &hash); | |
| 150 | 147 | sterilize_manifest(&manifest); |
| 151 | - } | |
| 152 | - if( flg & MFESTFLG_RAW ){ | |
| 153 | 148 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 154 | 149 | blob_write_to_file(&manifest, zManFile); |
| 155 | 150 | free(zManFile); |
| 156 | 151 | }else{ |
| 157 | 152 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ |
| @@ -159,11 +154,13 @@ | ||
| 159 | 154 | file_delete(zManFile); |
| 160 | 155 | free(zManFile); |
| 161 | 156 | } |
| 162 | 157 | } |
| 163 | 158 | if( flg & MFESTFLG_UUID ){ |
| 159 | + Blob hash; | |
| 164 | 160 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 161 | + blob_set_dynamic(&hash, rid_to_uuid(vid)); | |
| 165 | 162 | blob_append(&hash, "\n", 1); |
| 166 | 163 | blob_write_to_file(&hash, zManFile); |
| 167 | 164 | free(zManFile); |
| 168 | 165 | blob_reset(&hash); |
| 169 | 166 | }else{ |
| 170 | 167 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -134,24 +134,19 @@ | |
| 134 | ** "manifest.tags". |
| 135 | */ |
| 136 | void manifest_to_disk(int vid){ |
| 137 | char *zManFile; |
| 138 | Blob manifest; |
| 139 | Blob hash; |
| 140 | Blob taglist; |
| 141 | int flg; |
| 142 | |
| 143 | flg = db_get_manifest_setting(); |
| 144 | |
| 145 | if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 146 | blob_zero(&manifest); |
| 147 | content_get(vid, &manifest); |
| 148 | blob_zero(&hash); |
| 149 | sha1sum_blob(&manifest, &hash); |
| 150 | sterilize_manifest(&manifest); |
| 151 | } |
| 152 | if( flg & MFESTFLG_RAW ){ |
| 153 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 154 | blob_write_to_file(&manifest, zManFile); |
| 155 | free(zManFile); |
| 156 | }else{ |
| 157 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ |
| @@ -159,11 +154,13 @@ | |
| 159 | file_delete(zManFile); |
| 160 | free(zManFile); |
| 161 | } |
| 162 | } |
| 163 | if( flg & MFESTFLG_UUID ){ |
| 164 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 165 | blob_append(&hash, "\n", 1); |
| 166 | blob_write_to_file(&hash, zManFile); |
| 167 | free(zManFile); |
| 168 | blob_reset(&hash); |
| 169 | }else{ |
| 170 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -134,24 +134,19 @@ | |
| 134 | ** "manifest.tags". |
| 135 | */ |
| 136 | void manifest_to_disk(int vid){ |
| 137 | char *zManFile; |
| 138 | Blob manifest; |
| 139 | Blob taglist; |
| 140 | int flg; |
| 141 | |
| 142 | flg = db_get_manifest_setting(); |
| 143 | |
| 144 | if( flg & MFESTFLG_RAW ){ |
| 145 | blob_zero(&manifest); |
| 146 | content_get(vid, &manifest); |
| 147 | sterilize_manifest(&manifest); |
| 148 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 149 | blob_write_to_file(&manifest, zManFile); |
| 150 | free(zManFile); |
| 151 | }else{ |
| 152 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ |
| @@ -159,11 +154,13 @@ | |
| 154 | file_delete(zManFile); |
| 155 | free(zManFile); |
| 156 | } |
| 157 | } |
| 158 | if( flg & MFESTFLG_UUID ){ |
| 159 | Blob hash; |
| 160 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 161 | blob_set_dynamic(&hash, rid_to_uuid(vid)); |
| 162 | blob_append(&hash, "\n", 1); |
| 163 | blob_write_to_file(&hash, zManFile); |
| 164 | free(zManFile); |
| 165 | blob_reset(&hash); |
| 166 | }else{ |
| 167 |
+1
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -175,10 +175,11 @@ | ||
| 175 | 175 | db_initial_setup(0, 0, zDefaultUser); |
| 176 | 176 | user_select(); |
| 177 | 177 | db_set("content-schema", CONTENT_SCHEMA, 0); |
| 178 | 178 | db_set("aux-schema", AUX_SCHEMA_MAX, 0); |
| 179 | 179 | db_set("rebuilt", get_version(), 0); |
| 180 | + db_unset("hash-policy", 0); | |
| 180 | 181 | remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]); |
| 181 | 182 | url_remember(); |
| 182 | 183 | if( g.zSSLIdentity!=0 ){ |
| 183 | 184 | /* If the --ssl-identity option was specified, store it as a setting */ |
| 184 | 185 | Blob fn; |
| 185 | 186 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -175,10 +175,11 @@ | |
| 175 | db_initial_setup(0, 0, zDefaultUser); |
| 176 | user_select(); |
| 177 | db_set("content-schema", CONTENT_SCHEMA, 0); |
| 178 | db_set("aux-schema", AUX_SCHEMA_MAX, 0); |
| 179 | db_set("rebuilt", get_version(), 0); |
| 180 | remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]); |
| 181 | url_remember(); |
| 182 | if( g.zSSLIdentity!=0 ){ |
| 183 | /* If the --ssl-identity option was specified, store it as a setting */ |
| 184 | Blob fn; |
| 185 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -175,10 +175,11 @@ | |
| 175 | db_initial_setup(0, 0, zDefaultUser); |
| 176 | user_select(); |
| 177 | db_set("content-schema", CONTENT_SCHEMA, 0); |
| 178 | db_set("aux-schema", AUX_SCHEMA_MAX, 0); |
| 179 | db_set("rebuilt", get_version(), 0); |
| 180 | db_unset("hash-policy", 0); |
| 181 | remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]); |
| 182 | url_remember(); |
| 183 | if( g.zSSLIdentity!=0 ){ |
| 184 | /* If the --ssl-identity option was specified, store it as a setting */ |
| 185 | Blob fn; |
| 186 |
+6
| --- src/config.h | ||
| +++ src/config.h | ||
| @@ -38,10 +38,15 @@ | ||
| 38 | 38 | #endif |
| 39 | 39 | |
| 40 | 40 | #ifdef HAVE_AUTOCONFIG_H |
| 41 | 41 | #include "autoconfig.h" |
| 42 | 42 | #endif |
| 43 | + | |
| 44 | +/* Enable the hardened SHA1 implemenation by default */ | |
| 45 | +#ifndef FOSSIL_HARDENED_SHA1 | |
| 46 | +# define FOSSIL_HARDENED_SHA1 1 | |
| 47 | +#endif | |
| 43 | 48 | |
| 44 | 49 | #ifndef _RC_COMPILE_ |
| 45 | 50 | |
| 46 | 51 | /* |
| 47 | 52 | ** System header files used by all modules |
| @@ -168,10 +173,11 @@ | ||
| 168 | 173 | # endif |
| 169 | 174 | #endif |
| 170 | 175 | |
| 171 | 176 | #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION) |
| 172 | 177 | |
| 178 | +#include <stdint.h> | |
| 173 | 179 | #include "sqlite3.h" |
| 174 | 180 | |
| 175 | 181 | /* |
| 176 | 182 | ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257. |
| 177 | 183 | */ |
| 178 | 184 |
| --- src/config.h | |
| +++ src/config.h | |
| @@ -38,10 +38,15 @@ | |
| 38 | #endif |
| 39 | |
| 40 | #ifdef HAVE_AUTOCONFIG_H |
| 41 | #include "autoconfig.h" |
| 42 | #endif |
| 43 | |
| 44 | #ifndef _RC_COMPILE_ |
| 45 | |
| 46 | /* |
| 47 | ** System header files used by all modules |
| @@ -168,10 +173,11 @@ | |
| 168 | # endif |
| 169 | #endif |
| 170 | |
| 171 | #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION) |
| 172 | |
| 173 | #include "sqlite3.h" |
| 174 | |
| 175 | /* |
| 176 | ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257. |
| 177 | */ |
| 178 |
| --- src/config.h | |
| +++ src/config.h | |
| @@ -38,10 +38,15 @@ | |
| 38 | #endif |
| 39 | |
| 40 | #ifdef HAVE_AUTOCONFIG_H |
| 41 | #include "autoconfig.h" |
| 42 | #endif |
| 43 | |
| 44 | /* Enable the hardened SHA1 implemenation by default */ |
| 45 | #ifndef FOSSIL_HARDENED_SHA1 |
| 46 | # define FOSSIL_HARDENED_SHA1 1 |
| 47 | #endif |
| 48 | |
| 49 | #ifndef _RC_COMPILE_ |
| 50 | |
| 51 | /* |
| 52 | ** System header files used by all modules |
| @@ -168,10 +173,11 @@ | |
| 173 | # endif |
| 174 | #endif |
| 175 | |
| 176 | #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION) |
| 177 | |
| 178 | #include <stdint.h> |
| 179 | #include "sqlite3.h" |
| 180 | |
| 181 | /* |
| 182 | ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257. |
| 183 | */ |
| 184 |
+1
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -129,10 +129,11 @@ | ||
| 129 | 129 | { "empty-dirs", CONFIGSET_PROJ }, |
| 130 | 130 | { "allow-symlinks", CONFIGSET_PROJ }, |
| 131 | 131 | { "dotfiles", CONFIGSET_PROJ }, |
| 132 | 132 | { "parent-project-code", CONFIGSET_PROJ }, |
| 133 | 133 | { "parent-project-name", CONFIGSET_PROJ }, |
| 134 | + { "hash-policy", CONFIGSET_PROJ }, | |
| 134 | 135 | |
| 135 | 136 | #ifdef FOSSIL_ENABLE_LEGACY_MV_RM |
| 136 | 137 | { "mv-rm-files", CONFIGSET_PROJ }, |
| 137 | 138 | #endif |
| 138 | 139 | |
| 139 | 140 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -129,10 +129,11 @@ | |
| 129 | { "empty-dirs", CONFIGSET_PROJ }, |
| 130 | { "allow-symlinks", CONFIGSET_PROJ }, |
| 131 | { "dotfiles", CONFIGSET_PROJ }, |
| 132 | { "parent-project-code", CONFIGSET_PROJ }, |
| 133 | { "parent-project-name", CONFIGSET_PROJ }, |
| 134 | |
| 135 | #ifdef FOSSIL_ENABLE_LEGACY_MV_RM |
| 136 | { "mv-rm-files", CONFIGSET_PROJ }, |
| 137 | #endif |
| 138 | |
| 139 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -129,10 +129,11 @@ | |
| 129 | { "empty-dirs", CONFIGSET_PROJ }, |
| 130 | { "allow-symlinks", CONFIGSET_PROJ }, |
| 131 | { "dotfiles", CONFIGSET_PROJ }, |
| 132 | { "parent-project-code", CONFIGSET_PROJ }, |
| 133 | { "parent-project-name", CONFIGSET_PROJ }, |
| 134 | { "hash-policy", CONFIGSET_PROJ }, |
| 135 | |
| 136 | #ifdef FOSSIL_ENABLE_LEGACY_MV_RM |
| 137 | { "mv-rm-files", CONFIGSET_PROJ }, |
| 138 | #endif |
| 139 | |
| 140 |
+22
-12
| --- src/content.c | ||
| +++ src/content.c | ||
| @@ -312,11 +312,11 @@ | ||
| 312 | 312 | /* |
| 313 | 313 | ** COMMAND: artifact* |
| 314 | 314 | ** |
| 315 | 315 | ** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS? |
| 316 | 316 | ** |
| 317 | -** Extract an artifact by its SHA1 hash and write the results on | |
| 317 | +** Extract an artifact by its artifact hash and write the results on | |
| 318 | 318 | ** standard output, or if the optional 4th argument is given, in |
| 319 | 319 | ** the named output file. |
| 320 | 320 | ** |
| 321 | 321 | ** Options: |
| 322 | 322 | ** -R|--repository FILE Extract artifacts from repository FILE |
| @@ -497,11 +497,11 @@ | ||
| 497 | 497 | ** to be responsible for pBlob. This routine does *not* take over |
| 498 | 498 | ** responsibility for freeing pBlob. |
| 499 | 499 | */ |
| 500 | 500 | int content_put_ex( |
| 501 | 501 | Blob *pBlob, /* Content to add to the repository */ |
| 502 | - const char *zUuid, /* SHA1 hash of reconstructed pBlob */ | |
| 502 | + const char *zUuid, /* artifact hash of reconstructed pBlob */ | |
| 503 | 503 | int srcId, /* pBlob is a delta from this entry */ |
| 504 | 504 | int nBlob, /* pBlob is compressed. Original size is this */ |
| 505 | 505 | int isPrivate /* The content should be marked private */ |
| 506 | 506 | ){ |
| 507 | 507 | int size; |
| @@ -513,25 +513,38 @@ | ||
| 513 | 513 | int isDephantomize = 0; |
| 514 | 514 | |
| 515 | 515 | assert( g.repositoryOpen ); |
| 516 | 516 | assert( pBlob!=0 ); |
| 517 | 517 | assert( srcId==0 || zUuid!=0 ); |
| 518 | + db_begin_transaction(); | |
| 518 | 519 | if( zUuid==0 ){ |
| 519 | 520 | assert( nBlob==0 ); |
| 520 | - sha1sum_blob(pBlob, &hash); | |
| 521 | + /* First check the auxiliary hash to see if there is already an artifact | |
| 522 | + ** that uses the auxiliary hash name */ | |
| 523 | + hname_hash(pBlob, 1, &hash); | |
| 524 | + rid = fast_uuid_to_rid(blob_str(&hash)); | |
| 525 | + if( rid==0 ){ | |
| 526 | + /* No existing artifact with the auxiliary hash name. Therefore, use | |
| 527 | + ** the primary hash name. */ | |
| 528 | + blob_reset(&hash); | |
| 529 | + hname_hash(pBlob, 0, &hash); | |
| 530 | + } | |
| 521 | 531 | }else{ |
| 522 | 532 | blob_init(&hash, zUuid, -1); |
| 533 | + } | |
| 534 | + if( g.eHashPolicy==HPOLICY_AUTO && blob_size(&hash)>HNAME_LEN_SHA1 ){ | |
| 535 | + g.eHashPolicy = HPOLICY_SHA3; | |
| 536 | + db_set_int("hash-policy", HPOLICY_SHA3, 0); | |
| 523 | 537 | } |
| 524 | 538 | if( nBlob ){ |
| 525 | 539 | size = nBlob; |
| 526 | 540 | }else{ |
| 527 | 541 | size = blob_size(pBlob); |
| 528 | 542 | if( srcId ){ |
| 529 | 543 | size = delta_output_size(blob_buffer(pBlob), size); |
| 530 | 544 | } |
| 531 | 545 | } |
| 532 | - db_begin_transaction(); | |
| 533 | 546 | |
| 534 | 547 | /* Check to see if the entry already exists and if it does whether |
| 535 | 548 | ** or not the entry is a phantom |
| 536 | 549 | */ |
| 537 | 550 | db_prepare(&s1, "SELECT rid, size FROM blob WHERE uuid=%B", &hash); |
| @@ -868,11 +881,10 @@ | ||
| 868 | 881 | ** so forth, reporting any errors found. |
| 869 | 882 | */ |
| 870 | 883 | void test_integrity(void){ |
| 871 | 884 | Stmt q; |
| 872 | 885 | Blob content; |
| 873 | - Blob cksum; | |
| 874 | 886 | int n1 = 0; |
| 875 | 887 | int n2 = 0; |
| 876 | 888 | int nErr = 0; |
| 877 | 889 | int total; |
| 878 | 890 | int nCA = 0; |
| @@ -905,10 +917,11 @@ | ||
| 905 | 917 | db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid"); |
| 906 | 918 | total = db_int(0, "SELECT max(rid) FROM blob"); |
| 907 | 919 | while( db_step(&q)==SQLITE_ROW ){ |
| 908 | 920 | int rid = db_column_int(&q, 0); |
| 909 | 921 | const char *zUuid = db_column_text(&q, 1); |
| 922 | + int nUuid = db_column_bytes(&q, 1); | |
| 910 | 923 | int size = db_column_int(&q, 2); |
| 911 | 924 | n1++; |
| 912 | 925 | fossil_print(" %d/%d\r", n1, total); |
| 913 | 926 | fflush(stdout); |
| 914 | 927 | if( size<0 ){ |
| @@ -919,14 +932,12 @@ | ||
| 919 | 932 | if( blob_size(&content)!=size ){ |
| 920 | 933 | fossil_print("size mismatch on artifact %d: wanted %d but got %d\n", |
| 921 | 934 | rid, size, blob_size(&content)); |
| 922 | 935 | nErr++; |
| 923 | 936 | } |
| 924 | - sha1sum_blob(&content, &cksum); | |
| 925 | - if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){ | |
| 926 | - fossil_print("wrong hash on artifact %d: wanted %s but got %s\n", | |
| 927 | - rid, zUuid, blob_str(&cksum)); | |
| 937 | + if( !hname_verify_hash(&content, zUuid, nUuid) ){ | |
| 938 | + fossil_print("wrong hash on artifact %d\n",rid); | |
| 928 | 939 | nErr++; |
| 929 | 940 | } |
| 930 | 941 | if( bParse && looks_like_control_artifact(&content) ){ |
| 931 | 942 | Blob err; |
| 932 | 943 | int i, n; |
| @@ -941,11 +952,11 @@ | ||
| 941 | 952 | memcpy(zFirstLine, z, i); |
| 942 | 953 | zFirstLine[i] = 0; |
| 943 | 954 | p = manifest_parse(&content, 0, &err); |
| 944 | 955 | if( p==0 ){ |
| 945 | 956 | fossil_print("manifest_parse failed for %s:\n%s\n", |
| 946 | - blob_str(&cksum), blob_str(&err)); | |
| 957 | + zUuid, blob_str(&err)); | |
| 947 | 958 | if( strncmp(blob_str(&err), "line 1:", 7)==0 ){ |
| 948 | 959 | fossil_print("\"%s\"\n", zFirstLine); |
| 949 | 960 | } |
| 950 | 961 | }else{ |
| 951 | 962 | anCA[p->type]++; |
| @@ -954,11 +965,10 @@ | ||
| 954 | 965 | } |
| 955 | 966 | blob_reset(&err); |
| 956 | 967 | }else{ |
| 957 | 968 | blob_reset(&content); |
| 958 | 969 | } |
| 959 | - blob_reset(&cksum); | |
| 960 | 970 | n2++; |
| 961 | 971 | } |
| 962 | 972 | db_finalize(&q); |
| 963 | 973 | fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n", |
| 964 | 974 | n2, n1, nErr); |
| @@ -1157,11 +1167,11 @@ | ||
| 1157 | 1167 | ** |
| 1158 | 1168 | ** WARNING: You must run "fossil rebuild" after this command to rebuild |
| 1159 | 1169 | ** the metadata. |
| 1160 | 1170 | ** |
| 1161 | 1171 | ** Note that the arguments are the integer raw RID values from the BLOB table, |
| 1162 | -** not SHA1 hashs or labels. | |
| 1172 | +** not artifact hashs or labels. | |
| 1163 | 1173 | */ |
| 1164 | 1174 | void test_content_erase(void){ |
| 1165 | 1175 | int i; |
| 1166 | 1176 | Blob x; |
| 1167 | 1177 | char c; |
| 1168 | 1178 |
| --- src/content.c | |
| +++ src/content.c | |
| @@ -312,11 +312,11 @@ | |
| 312 | /* |
| 313 | ** COMMAND: artifact* |
| 314 | ** |
| 315 | ** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS? |
| 316 | ** |
| 317 | ** Extract an artifact by its SHA1 hash and write the results on |
| 318 | ** standard output, or if the optional 4th argument is given, in |
| 319 | ** the named output file. |
| 320 | ** |
| 321 | ** Options: |
| 322 | ** -R|--repository FILE Extract artifacts from repository FILE |
| @@ -497,11 +497,11 @@ | |
| 497 | ** to be responsible for pBlob. This routine does *not* take over |
| 498 | ** responsibility for freeing pBlob. |
| 499 | */ |
| 500 | int content_put_ex( |
| 501 | Blob *pBlob, /* Content to add to the repository */ |
| 502 | const char *zUuid, /* SHA1 hash of reconstructed pBlob */ |
| 503 | int srcId, /* pBlob is a delta from this entry */ |
| 504 | int nBlob, /* pBlob is compressed. Original size is this */ |
| 505 | int isPrivate /* The content should be marked private */ |
| 506 | ){ |
| 507 | int size; |
| @@ -513,25 +513,38 @@ | |
| 513 | int isDephantomize = 0; |
| 514 | |
| 515 | assert( g.repositoryOpen ); |
| 516 | assert( pBlob!=0 ); |
| 517 | assert( srcId==0 || zUuid!=0 ); |
| 518 | if( zUuid==0 ){ |
| 519 | assert( nBlob==0 ); |
| 520 | sha1sum_blob(pBlob, &hash); |
| 521 | }else{ |
| 522 | blob_init(&hash, zUuid, -1); |
| 523 | } |
| 524 | if( nBlob ){ |
| 525 | size = nBlob; |
| 526 | }else{ |
| 527 | size = blob_size(pBlob); |
| 528 | if( srcId ){ |
| 529 | size = delta_output_size(blob_buffer(pBlob), size); |
| 530 | } |
| 531 | } |
| 532 | db_begin_transaction(); |
| 533 | |
| 534 | /* Check to see if the entry already exists and if it does whether |
| 535 | ** or not the entry is a phantom |
| 536 | */ |
| 537 | db_prepare(&s1, "SELECT rid, size FROM blob WHERE uuid=%B", &hash); |
| @@ -868,11 +881,10 @@ | |
| 868 | ** so forth, reporting any errors found. |
| 869 | */ |
| 870 | void test_integrity(void){ |
| 871 | Stmt q; |
| 872 | Blob content; |
| 873 | Blob cksum; |
| 874 | int n1 = 0; |
| 875 | int n2 = 0; |
| 876 | int nErr = 0; |
| 877 | int total; |
| 878 | int nCA = 0; |
| @@ -905,10 +917,11 @@ | |
| 905 | db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid"); |
| 906 | total = db_int(0, "SELECT max(rid) FROM blob"); |
| 907 | while( db_step(&q)==SQLITE_ROW ){ |
| 908 | int rid = db_column_int(&q, 0); |
| 909 | const char *zUuid = db_column_text(&q, 1); |
| 910 | int size = db_column_int(&q, 2); |
| 911 | n1++; |
| 912 | fossil_print(" %d/%d\r", n1, total); |
| 913 | fflush(stdout); |
| 914 | if( size<0 ){ |
| @@ -919,14 +932,12 @@ | |
| 919 | if( blob_size(&content)!=size ){ |
| 920 | fossil_print("size mismatch on artifact %d: wanted %d but got %d\n", |
| 921 | rid, size, blob_size(&content)); |
| 922 | nErr++; |
| 923 | } |
| 924 | sha1sum_blob(&content, &cksum); |
| 925 | if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){ |
| 926 | fossil_print("wrong hash on artifact %d: wanted %s but got %s\n", |
| 927 | rid, zUuid, blob_str(&cksum)); |
| 928 | nErr++; |
| 929 | } |
| 930 | if( bParse && looks_like_control_artifact(&content) ){ |
| 931 | Blob err; |
| 932 | int i, n; |
| @@ -941,11 +952,11 @@ | |
| 941 | memcpy(zFirstLine, z, i); |
| 942 | zFirstLine[i] = 0; |
| 943 | p = manifest_parse(&content, 0, &err); |
| 944 | if( p==0 ){ |
| 945 | fossil_print("manifest_parse failed for %s:\n%s\n", |
| 946 | blob_str(&cksum), blob_str(&err)); |
| 947 | if( strncmp(blob_str(&err), "line 1:", 7)==0 ){ |
| 948 | fossil_print("\"%s\"\n", zFirstLine); |
| 949 | } |
| 950 | }else{ |
| 951 | anCA[p->type]++; |
| @@ -954,11 +965,10 @@ | |
| 954 | } |
| 955 | blob_reset(&err); |
| 956 | }else{ |
| 957 | blob_reset(&content); |
| 958 | } |
| 959 | blob_reset(&cksum); |
| 960 | n2++; |
| 961 | } |
| 962 | db_finalize(&q); |
| 963 | fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n", |
| 964 | n2, n1, nErr); |
| @@ -1157,11 +1167,11 @@ | |
| 1157 | ** |
| 1158 | ** WARNING: You must run "fossil rebuild" after this command to rebuild |
| 1159 | ** the metadata. |
| 1160 | ** |
| 1161 | ** Note that the arguments are the integer raw RID values from the BLOB table, |
| 1162 | ** not SHA1 hashs or labels. |
| 1163 | */ |
| 1164 | void test_content_erase(void){ |
| 1165 | int i; |
| 1166 | Blob x; |
| 1167 | char c; |
| 1168 |
| --- src/content.c | |
| +++ src/content.c | |
| @@ -312,11 +312,11 @@ | |
| 312 | /* |
| 313 | ** COMMAND: artifact* |
| 314 | ** |
| 315 | ** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS? |
| 316 | ** |
| 317 | ** Extract an artifact by its artifact hash and write the results on |
| 318 | ** standard output, or if the optional 4th argument is given, in |
| 319 | ** the named output file. |
| 320 | ** |
| 321 | ** Options: |
| 322 | ** -R|--repository FILE Extract artifacts from repository FILE |
| @@ -497,11 +497,11 @@ | |
| 497 | ** to be responsible for pBlob. This routine does *not* take over |
| 498 | ** responsibility for freeing pBlob. |
| 499 | */ |
| 500 | int content_put_ex( |
| 501 | Blob *pBlob, /* Content to add to the repository */ |
| 502 | const char *zUuid, /* artifact hash of reconstructed pBlob */ |
| 503 | int srcId, /* pBlob is a delta from this entry */ |
| 504 | int nBlob, /* pBlob is compressed. Original size is this */ |
| 505 | int isPrivate /* The content should be marked private */ |
| 506 | ){ |
| 507 | int size; |
| @@ -513,25 +513,38 @@ | |
| 513 | int isDephantomize = 0; |
| 514 | |
| 515 | assert( g.repositoryOpen ); |
| 516 | assert( pBlob!=0 ); |
| 517 | assert( srcId==0 || zUuid!=0 ); |
| 518 | db_begin_transaction(); |
| 519 | if( zUuid==0 ){ |
| 520 | assert( nBlob==0 ); |
| 521 | /* First check the auxiliary hash to see if there is already an artifact |
| 522 | ** that uses the auxiliary hash name */ |
| 523 | hname_hash(pBlob, 1, &hash); |
| 524 | rid = fast_uuid_to_rid(blob_str(&hash)); |
| 525 | if( rid==0 ){ |
| 526 | /* No existing artifact with the auxiliary hash name. Therefore, use |
| 527 | ** the primary hash name. */ |
| 528 | blob_reset(&hash); |
| 529 | hname_hash(pBlob, 0, &hash); |
| 530 | } |
| 531 | }else{ |
| 532 | blob_init(&hash, zUuid, -1); |
| 533 | } |
| 534 | if( g.eHashPolicy==HPOLICY_AUTO && blob_size(&hash)>HNAME_LEN_SHA1 ){ |
| 535 | g.eHashPolicy = HPOLICY_SHA3; |
| 536 | db_set_int("hash-policy", HPOLICY_SHA3, 0); |
| 537 | } |
| 538 | if( nBlob ){ |
| 539 | size = nBlob; |
| 540 | }else{ |
| 541 | size = blob_size(pBlob); |
| 542 | if( srcId ){ |
| 543 | size = delta_output_size(blob_buffer(pBlob), size); |
| 544 | } |
| 545 | } |
| 546 | |
| 547 | /* Check to see if the entry already exists and if it does whether |
| 548 | ** or not the entry is a phantom |
| 549 | */ |
| 550 | db_prepare(&s1, "SELECT rid, size FROM blob WHERE uuid=%B", &hash); |
| @@ -868,11 +881,10 @@ | |
| 881 | ** so forth, reporting any errors found. |
| 882 | */ |
| 883 | void test_integrity(void){ |
| 884 | Stmt q; |
| 885 | Blob content; |
| 886 | int n1 = 0; |
| 887 | int n2 = 0; |
| 888 | int nErr = 0; |
| 889 | int total; |
| 890 | int nCA = 0; |
| @@ -905,10 +917,11 @@ | |
| 917 | db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid"); |
| 918 | total = db_int(0, "SELECT max(rid) FROM blob"); |
| 919 | while( db_step(&q)==SQLITE_ROW ){ |
| 920 | int rid = db_column_int(&q, 0); |
| 921 | const char *zUuid = db_column_text(&q, 1); |
| 922 | int nUuid = db_column_bytes(&q, 1); |
| 923 | int size = db_column_int(&q, 2); |
| 924 | n1++; |
| 925 | fossil_print(" %d/%d\r", n1, total); |
| 926 | fflush(stdout); |
| 927 | if( size<0 ){ |
| @@ -919,14 +932,12 @@ | |
| 932 | if( blob_size(&content)!=size ){ |
| 933 | fossil_print("size mismatch on artifact %d: wanted %d but got %d\n", |
| 934 | rid, size, blob_size(&content)); |
| 935 | nErr++; |
| 936 | } |
| 937 | if( !hname_verify_hash(&content, zUuid, nUuid) ){ |
| 938 | fossil_print("wrong hash on artifact %d\n",rid); |
| 939 | nErr++; |
| 940 | } |
| 941 | if( bParse && looks_like_control_artifact(&content) ){ |
| 942 | Blob err; |
| 943 | int i, n; |
| @@ -941,11 +952,11 @@ | |
| 952 | memcpy(zFirstLine, z, i); |
| 953 | zFirstLine[i] = 0; |
| 954 | p = manifest_parse(&content, 0, &err); |
| 955 | if( p==0 ){ |
| 956 | fossil_print("manifest_parse failed for %s:\n%s\n", |
| 957 | zUuid, blob_str(&err)); |
| 958 | if( strncmp(blob_str(&err), "line 1:", 7)==0 ){ |
| 959 | fossil_print("\"%s\"\n", zFirstLine); |
| 960 | } |
| 961 | }else{ |
| 962 | anCA[p->type]++; |
| @@ -954,11 +965,10 @@ | |
| 965 | } |
| 966 | blob_reset(&err); |
| 967 | }else{ |
| 968 | blob_reset(&content); |
| 969 | } |
| 970 | n2++; |
| 971 | } |
| 972 | db_finalize(&q); |
| 973 | fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n", |
| 974 | n2, n1, nErr); |
| @@ -1157,11 +1167,11 @@ | |
| 1167 | ** |
| 1168 | ** WARNING: You must run "fossil rebuild" after this command to rebuild |
| 1169 | ** the metadata. |
| 1170 | ** |
| 1171 | ** Note that the arguments are the integer raw RID values from the BLOB table, |
| 1172 | ** not artifact hashs or labels. |
| 1173 | */ |
| 1174 | void test_content_erase(void){ |
| 1175 | int i; |
| 1176 | Blob x; |
| 1177 | char c; |
| 1178 |
M
src/db.c
+29
-34
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | 3 | ** |
| 4 | 4 | ** This program is free software; you can redistribute it and/or |
| 5 | 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | - | |
| 7 | +** | |
| 8 | 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | 9 | ** but without any warranty; without even the implied warranty of |
| 10 | 10 | ** merchantability or fitness for a particular purpose. |
| 11 | 11 | ** |
| 12 | 12 | ** Author contact information: |
| @@ -1485,35 +1485,20 @@ | ||
| 1485 | 1485 | g.repositoryOpen = 1; |
| 1486 | 1486 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1487 | 1487 | g.allowSymlinks = db_get_boolean("allow-symlinks", |
| 1488 | 1488 | db_allow_symlinks_by_default()); |
| 1489 | 1489 | g.zAuxSchema = db_get("aux-schema",""); |
| 1490 | - | |
| 1491 | - /* Verify that the PLINK table has a new column added by the | |
| 1492 | - ** 2014-11-28 schema change. Create it if necessary. This code | |
| 1493 | - ** can be removed in the future, once all users have upgraded to the | |
| 1494 | - ** 2014-11-28 or later schema. | |
| 1495 | - */ | |
| 1496 | - if( !db_table_has_column("repository","plink","baseid") ){ | |
| 1497 | - db_multi_exec( | |
| 1498 | - "ALTER TABLE repository.plink ADD COLUMN baseid;" | |
| 1499 | - ); | |
| 1500 | - } | |
| 1501 | - | |
| 1502 | - /* Verify that the MLINK table has the newer columns added by the | |
| 1503 | - ** 2015-01-24 schema change. Create them if necessary. This code | |
| 1504 | - ** can be removed in the future, once all users have upgraded to the | |
| 1505 | - ** 2015-01-24 or later schema. | |
| 1506 | - */ | |
| 1507 | - if( !db_table_has_column("repository","mlink","isaux") ){ | |
| 1508 | - db_begin_transaction(); | |
| 1509 | - db_multi_exec( | |
| 1510 | - "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;" | |
| 1511 | - "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;" | |
| 1512 | - ); | |
| 1513 | - db_end_transaction(0); | |
| 1514 | - } | |
| 1490 | + g.eHashPolicy = db_get_int("hash-policy",-1); | |
| 1491 | + if( g.eHashPolicy<0 ){ | |
| 1492 | + g.eHashPolicy = hname_default_policy(); | |
| 1493 | + db_set_int("hash-policy", g.eHashPolicy, 0); | |
| 1494 | + } | |
| 1495 | + | |
| 1496 | + /* Make a change to the CHECK constraint on the BLOB table for | |
| 1497 | + ** version 2.0 and later. | |
| 1498 | + */ | |
| 1499 | + rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */ | |
| 1515 | 1500 | } |
| 1516 | 1501 | |
| 1517 | 1502 | /* |
| 1518 | 1503 | ** Flags for the db_find_and_open_repository() function. |
| 1519 | 1504 | */ |
| @@ -1677,10 +1662,11 @@ | ||
| 1677 | 1662 | while( db.pAllStmt ){ |
| 1678 | 1663 | db_finalize(db.pAllStmt); |
| 1679 | 1664 | } |
| 1680 | 1665 | db_end_transaction(1); |
| 1681 | 1666 | pStmt = 0; |
| 1667 | + sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0); | |
| 1682 | 1668 | db_close_config(); |
| 1683 | 1669 | |
| 1684 | 1670 | /* If the localdb has a lot of unused free space, |
| 1685 | 1671 | ** then VACUUM it as we shut down. |
| 1686 | 1672 | */ |
| @@ -1848,10 +1834,11 @@ | ||
| 1848 | 1834 | " AND name NOT GLOB 'project-*'" |
| 1849 | 1835 | " AND name NOT GLOB 'short-project-*';", |
| 1850 | 1836 | configure_inop_rhs(CONFIGSET_ALL), |
| 1851 | 1837 | db_setting_inop_rhs() |
| 1852 | 1838 | ); |
| 1839 | + g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy); | |
| 1853 | 1840 | db_multi_exec( |
| 1854 | 1841 | "REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;" |
| 1855 | 1842 | ); |
| 1856 | 1843 | |
| 1857 | 1844 | /* |
| @@ -1920,13 +1907,14 @@ | ||
| 1920 | 1907 | ** their associated permissions will not be copied; however, the system |
| 1921 | 1908 | ** default users "anonymous", "nobody", "reader", "developer", and their |
| 1922 | 1909 | ** associated permissions will be copied. |
| 1923 | 1910 | ** |
| 1924 | 1911 | ** Options: |
| 1925 | -** --template FILE copy settings from repository file | |
| 1926 | -** --admin-user|-A USERNAME select given USERNAME as admin user | |
| 1927 | -** --date-override DATETIME use DATETIME as time of the initial check-in | |
| 1912 | +** --template FILE Copy settings from repository file | |
| 1913 | +** --admin-user|-A USERNAME Select given USERNAME as admin user | |
| 1914 | +** --date-override DATETIME Use DATETIME as time of the initial check-in | |
| 1915 | +** --sha1 Use a initial hash policy of "sha1" | |
| 1928 | 1916 | ** |
| 1929 | 1917 | ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| 1930 | 1918 | ** year-month-day form, it may be truncated, the "T" may be replaced by |
| 1931 | 1919 | ** a space, and it may also name a timezone offset from UTC as "-HH:MM" |
| 1932 | 1920 | ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z" |
| @@ -1937,14 +1925,17 @@ | ||
| 1937 | 1925 | void create_repository_cmd(void){ |
| 1938 | 1926 | char *zPassword; |
| 1939 | 1927 | const char *zTemplate; /* Repository from which to copy settings */ |
| 1940 | 1928 | const char *zDate; /* Date of the initial check-in */ |
| 1941 | 1929 | const char *zDefaultUser; /* Optional name of the default user */ |
| 1930 | + int bUseSha1 = 0; /* True to set the hash-policy to sha1 */ | |
| 1931 | + | |
| 1942 | 1932 | |
| 1943 | 1933 | zTemplate = find_option("template",0,1); |
| 1944 | 1934 | zDate = find_option("date-override",0,1); |
| 1945 | 1935 | zDefaultUser = find_option("admin-user","A",1); |
| 1936 | + bUseSha1 = find_option("sha1",0,0)!=0; | |
| 1946 | 1937 | /* We should be done with options.. */ |
| 1947 | 1938 | verify_all_options(); |
| 1948 | 1939 | |
| 1949 | 1940 | if( g.argc!=3 ){ |
| 1950 | 1941 | usage("REPOSITORY-NAME"); |
| @@ -1957,10 +1948,14 @@ | ||
| 1957 | 1948 | db_create_repository(g.argv[2]); |
| 1958 | 1949 | db_open_repository(g.argv[2]); |
| 1959 | 1950 | db_open_config(0, 0); |
| 1960 | 1951 | if( zTemplate ) db_attach(zTemplate, "settingSrc"); |
| 1961 | 1952 | db_begin_transaction(); |
| 1953 | + if( bUseSha1 ){ | |
| 1954 | + g.eHashPolicy = HPOLICY_SHA1; | |
| 1955 | + db_set_int("hash-policy", HPOLICY_SHA1, 0); | |
| 1956 | + } | |
| 1962 | 1957 | if( zDate==0 ) zDate = "now"; |
| 1963 | 1958 | db_initial_setup(zTemplate, zDate, zDefaultUser); |
| 1964 | 1959 | db_end_transaction(0); |
| 1965 | 1960 | if( zTemplate ) db_detach("settingSrc"); |
| 1966 | 1961 | fossil_print("project-id: %s\n", db_get("project-code", 0)); |
| @@ -2082,29 +2077,29 @@ | ||
| 2082 | 2077 | sqlite3_result_value(context, argv[2-rc]); |
| 2083 | 2078 | } |
| 2084 | 2079 | } |
| 2085 | 2080 | |
| 2086 | 2081 | /* |
| 2087 | -** Convert the input string into an SHA1. Make a notation in the | |
| 2082 | +** Convert the input string into a artifact hash. Make a notation in the | |
| 2088 | 2083 | ** CONCEALED table so that the hash can be undo using the db_reveal() |
| 2089 | 2084 | ** function at some later time. |
| 2090 | 2085 | ** |
| 2091 | 2086 | ** The value returned is stored in static space and will be overwritten |
| 2092 | 2087 | ** on subsequent calls. |
| 2093 | 2088 | ** |
| 2094 | -** If zContent is already a well-formed SHA1 hash, then return a copy | |
| 2089 | +** If zContent is already a well-formed artifact hash, then return a copy | |
| 2095 | 2090 | ** of that hash, not a hash of the hash. |
| 2096 | 2091 | ** |
| 2097 | 2092 | ** The CONCEALED table is meant to obscure email addresses. Every valid |
| 2098 | 2093 | ** email address will contain a "@" character and "@" is not valid within |
| 2099 | -** an SHA1 hash so there is no chance that a valid email address will go | |
| 2094 | +** a SHA1 hash so there is no chance that a valid email address will go | |
| 2100 | 2095 | ** unconcealed. |
| 2101 | 2096 | */ |
| 2102 | 2097 | char *db_conceal(const char *zContent, int n){ |
| 2103 | - static char zHash[42]; | |
| 2098 | + static char zHash[HNAME_MAX+1]; | |
| 2104 | 2099 | Blob out; |
| 2105 | - if( n==40 && validate16(zContent, n) ){ | |
| 2100 | + if( hname_validate(zContent, n) ){ | |
| 2106 | 2101 | memcpy(zHash, zContent, n); |
| 2107 | 2102 | zHash[n] = 0; |
| 2108 | 2103 | }else{ |
| 2109 | 2104 | sha1sum_step_text(zContent, n); |
| 2110 | 2105 | sha1sum_finish(&out); |
| 2111 | 2106 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| @@ -1485,35 +1485,20 @@ | |
| 1485 | g.repositoryOpen = 1; |
| 1486 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1487 | g.allowSymlinks = db_get_boolean("allow-symlinks", |
| 1488 | db_allow_symlinks_by_default()); |
| 1489 | g.zAuxSchema = db_get("aux-schema",""); |
| 1490 | |
| 1491 | /* Verify that the PLINK table has a new column added by the |
| 1492 | ** 2014-11-28 schema change. Create it if necessary. This code |
| 1493 | ** can be removed in the future, once all users have upgraded to the |
| 1494 | ** 2014-11-28 or later schema. |
| 1495 | */ |
| 1496 | if( !db_table_has_column("repository","plink","baseid") ){ |
| 1497 | db_multi_exec( |
| 1498 | "ALTER TABLE repository.plink ADD COLUMN baseid;" |
| 1499 | ); |
| 1500 | } |
| 1501 | |
| 1502 | /* Verify that the MLINK table has the newer columns added by the |
| 1503 | ** 2015-01-24 schema change. Create them if necessary. This code |
| 1504 | ** can be removed in the future, once all users have upgraded to the |
| 1505 | ** 2015-01-24 or later schema. |
| 1506 | */ |
| 1507 | if( !db_table_has_column("repository","mlink","isaux") ){ |
| 1508 | db_begin_transaction(); |
| 1509 | db_multi_exec( |
| 1510 | "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;" |
| 1511 | "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;" |
| 1512 | ); |
| 1513 | db_end_transaction(0); |
| 1514 | } |
| 1515 | } |
| 1516 | |
| 1517 | /* |
| 1518 | ** Flags for the db_find_and_open_repository() function. |
| 1519 | */ |
| @@ -1677,10 +1662,11 @@ | |
| 1677 | while( db.pAllStmt ){ |
| 1678 | db_finalize(db.pAllStmt); |
| 1679 | } |
| 1680 | db_end_transaction(1); |
| 1681 | pStmt = 0; |
| 1682 | db_close_config(); |
| 1683 | |
| 1684 | /* If the localdb has a lot of unused free space, |
| 1685 | ** then VACUUM it as we shut down. |
| 1686 | */ |
| @@ -1848,10 +1834,11 @@ | |
| 1848 | " AND name NOT GLOB 'project-*'" |
| 1849 | " AND name NOT GLOB 'short-project-*';", |
| 1850 | configure_inop_rhs(CONFIGSET_ALL), |
| 1851 | db_setting_inop_rhs() |
| 1852 | ); |
| 1853 | db_multi_exec( |
| 1854 | "REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;" |
| 1855 | ); |
| 1856 | |
| 1857 | /* |
| @@ -1920,13 +1907,14 @@ | |
| 1920 | ** their associated permissions will not be copied; however, the system |
| 1921 | ** default users "anonymous", "nobody", "reader", "developer", and their |
| 1922 | ** associated permissions will be copied. |
| 1923 | ** |
| 1924 | ** Options: |
| 1925 | ** --template FILE copy settings from repository file |
| 1926 | ** --admin-user|-A USERNAME select given USERNAME as admin user |
| 1927 | ** --date-override DATETIME use DATETIME as time of the initial check-in |
| 1928 | ** |
| 1929 | ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| 1930 | ** year-month-day form, it may be truncated, the "T" may be replaced by |
| 1931 | ** a space, and it may also name a timezone offset from UTC as "-HH:MM" |
| 1932 | ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z" |
| @@ -1937,14 +1925,17 @@ | |
| 1937 | void create_repository_cmd(void){ |
| 1938 | char *zPassword; |
| 1939 | const char *zTemplate; /* Repository from which to copy settings */ |
| 1940 | const char *zDate; /* Date of the initial check-in */ |
| 1941 | const char *zDefaultUser; /* Optional name of the default user */ |
| 1942 | |
| 1943 | zTemplate = find_option("template",0,1); |
| 1944 | zDate = find_option("date-override",0,1); |
| 1945 | zDefaultUser = find_option("admin-user","A",1); |
| 1946 | /* We should be done with options.. */ |
| 1947 | verify_all_options(); |
| 1948 | |
| 1949 | if( g.argc!=3 ){ |
| 1950 | usage("REPOSITORY-NAME"); |
| @@ -1957,10 +1948,14 @@ | |
| 1957 | db_create_repository(g.argv[2]); |
| 1958 | db_open_repository(g.argv[2]); |
| 1959 | db_open_config(0, 0); |
| 1960 | if( zTemplate ) db_attach(zTemplate, "settingSrc"); |
| 1961 | db_begin_transaction(); |
| 1962 | if( zDate==0 ) zDate = "now"; |
| 1963 | db_initial_setup(zTemplate, zDate, zDefaultUser); |
| 1964 | db_end_transaction(0); |
| 1965 | if( zTemplate ) db_detach("settingSrc"); |
| 1966 | fossil_print("project-id: %s\n", db_get("project-code", 0)); |
| @@ -2082,29 +2077,29 @@ | |
| 2082 | sqlite3_result_value(context, argv[2-rc]); |
| 2083 | } |
| 2084 | } |
| 2085 | |
| 2086 | /* |
| 2087 | ** Convert the input string into an SHA1. Make a notation in the |
| 2088 | ** CONCEALED table so that the hash can be undo using the db_reveal() |
| 2089 | ** function at some later time. |
| 2090 | ** |
| 2091 | ** The value returned is stored in static space and will be overwritten |
| 2092 | ** on subsequent calls. |
| 2093 | ** |
| 2094 | ** If zContent is already a well-formed SHA1 hash, then return a copy |
| 2095 | ** of that hash, not a hash of the hash. |
| 2096 | ** |
| 2097 | ** The CONCEALED table is meant to obscure email addresses. Every valid |
| 2098 | ** email address will contain a "@" character and "@" is not valid within |
| 2099 | ** an SHA1 hash so there is no chance that a valid email address will go |
| 2100 | ** unconcealed. |
| 2101 | */ |
| 2102 | char *db_conceal(const char *zContent, int n){ |
| 2103 | static char zHash[42]; |
| 2104 | Blob out; |
| 2105 | if( n==40 && validate16(zContent, n) ){ |
| 2106 | memcpy(zHash, zContent, n); |
| 2107 | zHash[n] = 0; |
| 2108 | }else{ |
| 2109 | sha1sum_step_text(zContent, n); |
| 2110 | sha1sum_finish(&out); |
| 2111 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | ** |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| @@ -1485,35 +1485,20 @@ | |
| 1485 | g.repositoryOpen = 1; |
| 1486 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1487 | g.allowSymlinks = db_get_boolean("allow-symlinks", |
| 1488 | db_allow_symlinks_by_default()); |
| 1489 | g.zAuxSchema = db_get("aux-schema",""); |
| 1490 | g.eHashPolicy = db_get_int("hash-policy",-1); |
| 1491 | if( g.eHashPolicy<0 ){ |
| 1492 | g.eHashPolicy = hname_default_policy(); |
| 1493 | db_set_int("hash-policy", g.eHashPolicy, 0); |
| 1494 | } |
| 1495 | |
| 1496 | /* Make a change to the CHECK constraint on the BLOB table for |
| 1497 | ** version 2.0 and later. |
| 1498 | */ |
| 1499 | rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */ |
| 1500 | } |
| 1501 | |
| 1502 | /* |
| 1503 | ** Flags for the db_find_and_open_repository() function. |
| 1504 | */ |
| @@ -1677,10 +1662,11 @@ | |
| 1662 | while( db.pAllStmt ){ |
| 1663 | db_finalize(db.pAllStmt); |
| 1664 | } |
| 1665 | db_end_transaction(1); |
| 1666 | pStmt = 0; |
| 1667 | sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0); |
| 1668 | db_close_config(); |
| 1669 | |
| 1670 | /* If the localdb has a lot of unused free space, |
| 1671 | ** then VACUUM it as we shut down. |
| 1672 | */ |
| @@ -1848,10 +1834,11 @@ | |
| 1834 | " AND name NOT GLOB 'project-*'" |
| 1835 | " AND name NOT GLOB 'short-project-*';", |
| 1836 | configure_inop_rhs(CONFIGSET_ALL), |
| 1837 | db_setting_inop_rhs() |
| 1838 | ); |
| 1839 | g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy); |
| 1840 | db_multi_exec( |
| 1841 | "REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;" |
| 1842 | ); |
| 1843 | |
| 1844 | /* |
| @@ -1920,13 +1907,14 @@ | |
| 1907 | ** their associated permissions will not be copied; however, the system |
| 1908 | ** default users "anonymous", "nobody", "reader", "developer", and their |
| 1909 | ** associated permissions will be copied. |
| 1910 | ** |
| 1911 | ** Options: |
| 1912 | ** --template FILE Copy settings from repository file |
| 1913 | ** --admin-user|-A USERNAME Select given USERNAME as admin user |
| 1914 | ** --date-override DATETIME Use DATETIME as time of the initial check-in |
| 1915 | ** --sha1 Use a initial hash policy of "sha1" |
| 1916 | ** |
| 1917 | ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| 1918 | ** year-month-day form, it may be truncated, the "T" may be replaced by |
| 1919 | ** a space, and it may also name a timezone offset from UTC as "-HH:MM" |
| 1920 | ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z" |
| @@ -1937,14 +1925,17 @@ | |
| 1925 | void create_repository_cmd(void){ |
| 1926 | char *zPassword; |
| 1927 | const char *zTemplate; /* Repository from which to copy settings */ |
| 1928 | const char *zDate; /* Date of the initial check-in */ |
| 1929 | const char *zDefaultUser; /* Optional name of the default user */ |
| 1930 | int bUseSha1 = 0; /* True to set the hash-policy to sha1 */ |
| 1931 | |
| 1932 | |
| 1933 | zTemplate = find_option("template",0,1); |
| 1934 | zDate = find_option("date-override",0,1); |
| 1935 | zDefaultUser = find_option("admin-user","A",1); |
| 1936 | bUseSha1 = find_option("sha1",0,0)!=0; |
| 1937 | /* We should be done with options.. */ |
| 1938 | verify_all_options(); |
| 1939 | |
| 1940 | if( g.argc!=3 ){ |
| 1941 | usage("REPOSITORY-NAME"); |
| @@ -1957,10 +1948,14 @@ | |
| 1948 | db_create_repository(g.argv[2]); |
| 1949 | db_open_repository(g.argv[2]); |
| 1950 | db_open_config(0, 0); |
| 1951 | if( zTemplate ) db_attach(zTemplate, "settingSrc"); |
| 1952 | db_begin_transaction(); |
| 1953 | if( bUseSha1 ){ |
| 1954 | g.eHashPolicy = HPOLICY_SHA1; |
| 1955 | db_set_int("hash-policy", HPOLICY_SHA1, 0); |
| 1956 | } |
| 1957 | if( zDate==0 ) zDate = "now"; |
| 1958 | db_initial_setup(zTemplate, zDate, zDefaultUser); |
| 1959 | db_end_transaction(0); |
| 1960 | if( zTemplate ) db_detach("settingSrc"); |
| 1961 | fossil_print("project-id: %s\n", db_get("project-code", 0)); |
| @@ -2082,29 +2077,29 @@ | |
| 2077 | sqlite3_result_value(context, argv[2-rc]); |
| 2078 | } |
| 2079 | } |
| 2080 | |
| 2081 | /* |
| 2082 | ** Convert the input string into a artifact hash. Make a notation in the |
| 2083 | ** CONCEALED table so that the hash can be undo using the db_reveal() |
| 2084 | ** function at some later time. |
| 2085 | ** |
| 2086 | ** The value returned is stored in static space and will be overwritten |
| 2087 | ** on subsequent calls. |
| 2088 | ** |
| 2089 | ** If zContent is already a well-formed artifact hash, then return a copy |
| 2090 | ** of that hash, not a hash of the hash. |
| 2091 | ** |
| 2092 | ** The CONCEALED table is meant to obscure email addresses. Every valid |
| 2093 | ** email address will contain a "@" character and "@" is not valid within |
| 2094 | ** a SHA1 hash so there is no chance that a valid email address will go |
| 2095 | ** unconcealed. |
| 2096 | */ |
| 2097 | char *db_conceal(const char *zContent, int n){ |
| 2098 | static char zHash[HNAME_MAX+1]; |
| 2099 | Blob out; |
| 2100 | if( hname_validate(zContent, n) ){ |
| 2101 | memcpy(zHash, zContent, n); |
| 2102 | zHash[n] = 0; |
| 2103 | }else{ |
| 2104 | sha1sum_step_text(zContent, n); |
| 2105 | sha1sum_finish(&out); |
| 2106 |
+1
-1
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -2278,11 +2278,11 @@ | ||
| 2278 | 2278 | ** URL: /annotate?checkin=ID&filename=FILENAME |
| 2279 | 2279 | ** URL: /blame?checkin=ID&filename=FILENAME |
| 2280 | 2280 | ** URL: /praise?checkin=ID&filename=FILENAME |
| 2281 | 2281 | ** |
| 2282 | 2282 | ** Show the most recent change to each line of a text file. /annotate shows |
| 2283 | -** the date of the changes and the check-in SHA1 hash (with a link to the | |
| 2283 | +** the date of the changes and the check-in hash (with a link to the | |
| 2284 | 2284 | ** check-in). /blame and /praise also show the user who made the check-in. |
| 2285 | 2285 | ** |
| 2286 | 2286 | ** Query parameters: |
| 2287 | 2287 | ** |
| 2288 | 2288 | ** checkin=ID The manifest ID at which to start the annotation |
| 2289 | 2289 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2278,11 +2278,11 @@ | |
| 2278 | ** URL: /annotate?checkin=ID&filename=FILENAME |
| 2279 | ** URL: /blame?checkin=ID&filename=FILENAME |
| 2280 | ** URL: /praise?checkin=ID&filename=FILENAME |
| 2281 | ** |
| 2282 | ** Show the most recent change to each line of a text file. /annotate shows |
| 2283 | ** the date of the changes and the check-in SHA1 hash (with a link to the |
| 2284 | ** check-in). /blame and /praise also show the user who made the check-in. |
| 2285 | ** |
| 2286 | ** Query parameters: |
| 2287 | ** |
| 2288 | ** checkin=ID The manifest ID at which to start the annotation |
| 2289 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2278,11 +2278,11 @@ | |
| 2278 | ** URL: /annotate?checkin=ID&filename=FILENAME |
| 2279 | ** URL: /blame?checkin=ID&filename=FILENAME |
| 2280 | ** URL: /praise?checkin=ID&filename=FILENAME |
| 2281 | ** |
| 2282 | ** Show the most recent change to each line of a text file. /annotate shows |
| 2283 | ** the date of the changes and the check-in hash (with a link to the |
| 2284 | ** check-in). /blame and /praise also show the user who made the check-in. |
| 2285 | ** |
| 2286 | ** Query parameters: |
| 2287 | ** |
| 2288 | ** checkin=ID The manifest ID at which to start the annotation |
| 2289 |
+22
-8
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -151,10 +151,13 @@ | ||
| 151 | 151 | /* |
| 152 | 152 | ** Show the difference between two files, one in memory and one on disk. |
| 153 | 153 | ** |
| 154 | 154 | ** The difference is the set of edits needed to transform pFile1 into |
| 155 | 155 | ** zFile2. The content of pFile1 is in memory. zFile2 exists on disk. |
| 156 | +** | |
| 157 | +** If fSwapDiff is 1, show the set of edits to transform zFile2 into pFile1 | |
| 158 | +** instead of the opposite. | |
| 156 | 159 | ** |
| 157 | 160 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 158 | 161 | ** command zDiffCmd to do the diffing. |
| 159 | 162 | ** |
| 160 | 163 | ** When using an external diff program, zBinGlob contains the GLOB patterns |
| @@ -167,11 +170,12 @@ | ||
| 167 | 170 | const char *zFile2, /* On disk content to compare to */ |
| 168 | 171 | const char *zName, /* Display name of the file */ |
| 169 | 172 | const char *zDiffCmd, /* Command for comparison */ |
| 170 | 173 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 171 | 174 | int fIncludeBinary, /* Include binary files for external diff */ |
| 172 | - u64 diffFlags /* Flags to control the diff */ | |
| 175 | + u64 diffFlags, /* Flags to control the diff */ | |
| 176 | + int fSwapDiff /* Diff from Zfile2 to Pfile1 */ | |
| 173 | 177 | ){ |
| 174 | 178 | if( zDiffCmd==0 ){ |
| 175 | 179 | Blob out; /* Diff output text */ |
| 176 | 180 | Blob file2; /* Content of zFile2 */ |
| 177 | 181 | const char *zName2; /* Name of zFile2 for display */ |
| @@ -194,11 +198,15 @@ | ||
| 194 | 198 | if( blob_compare(pFile1, &file2) ){ |
| 195 | 199 | fossil_print("CHANGED %s\n", zName); |
| 196 | 200 | } |
| 197 | 201 | }else{ |
| 198 | 202 | blob_zero(&out); |
| 199 | - text_diff(pFile1, &file2, &out, 0, diffFlags); | |
| 203 | + if( fSwapDiff ){ | |
| 204 | + text_diff(&file2, pFile1, &out, 0, diffFlags); | |
| 205 | + }else{ | |
| 206 | + text_diff(pFile1, &file2, &out, 0, diffFlags); | |
| 207 | + } | |
| 200 | 208 | if( blob_size(&out) ){ |
| 201 | 209 | diff_print_filenames(zName, zName2, diffFlags); |
| 202 | 210 | fossil_print("%s\n", blob_str(&out)); |
| 203 | 211 | } |
| 204 | 212 | blob_reset(&out); |
| @@ -252,13 +260,19 @@ | ||
| 252 | 260 | blob_write_to_file(pFile1, blob_str(&nameFile1)); |
| 253 | 261 | |
| 254 | 262 | /* Construct the external diff command */ |
| 255 | 263 | blob_zero(&cmd); |
| 256 | 264 | blob_appendf(&cmd, "%s ", zDiffCmd); |
| 257 | - shell_escape(&cmd, blob_str(&nameFile1)); | |
| 258 | - blob_append(&cmd, " ", 1); | |
| 259 | - shell_escape(&cmd, zFile2); | |
| 265 | + if( fSwapDiff ){ | |
| 266 | + shell_escape(&cmd, zFile2); | |
| 267 | + blob_append(&cmd, " ", 1); | |
| 268 | + shell_escape(&cmd, blob_str(&nameFile1)); | |
| 269 | + }else{ | |
| 270 | + shell_escape(&cmd, blob_str(&nameFile1)); | |
| 271 | + blob_append(&cmd, " ", 1); | |
| 272 | + shell_escape(&cmd, zFile2); | |
| 273 | + } | |
| 260 | 274 | |
| 261 | 275 | /* Run the external diff command */ |
| 262 | 276 | fossil_system(blob_str(&cmd)); |
| 263 | 277 | |
| 264 | 278 | /* Delete the temporary file and clean up memory used */ |
| @@ -482,11 +496,11 @@ | ||
| 482 | 496 | blob_zero(&content); |
| 483 | 497 | } |
| 484 | 498 | isBin = fIncludeBinary ? 0 : looks_like_binary(&content); |
| 485 | 499 | diff_print_index(zPathname, diffFlags); |
| 486 | 500 | diff_file(&content, isBin, zFullName, zPathname, zDiffCmd, |
| 487 | - zBinGlob, fIncludeBinary, diffFlags); | |
| 501 | + zBinGlob, fIncludeBinary, diffFlags, 0); | |
| 488 | 502 | blob_reset(&content); |
| 489 | 503 | } |
| 490 | 504 | blob_reset(&fname); |
| 491 | 505 | } |
| 492 | 506 | db_finalize(&q); |
| @@ -519,11 +533,11 @@ | ||
| 519 | 533 | const char *zFile = (const char*)db_column_text(&q, 0); |
| 520 | 534 | if( !file_dir_match(pFileDir, zFile) ) continue; |
| 521 | 535 | zFullName = mprintf("%s%s", g.zLocalRoot, zFile); |
| 522 | 536 | db_column_blob(&q, 1, &content); |
| 523 | 537 | diff_file(&content, 0, zFullName, zFile, |
| 524 | - zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); | |
| 538 | + zDiffCmd, zBinGlob, fIncludeBinary, diffFlags, 0); | |
| 525 | 539 | fossil_free(zFullName); |
| 526 | 540 | blob_reset(&content); |
| 527 | 541 | } |
| 528 | 542 | db_finalize(&q); |
| 529 | 543 | } |
| @@ -750,11 +764,11 @@ | ||
| 750 | 764 | ** Returns non-zero if files that may be binary should be used with external |
| 751 | 765 | ** diff programs. |
| 752 | 766 | */ |
| 753 | 767 | int diff_include_binary_files(void){ |
| 754 | 768 | const char* zArgIncludeBinary = find_option("diff-binary", 0, 1); |
| 755 | - | |
| 769 | + | |
| 756 | 770 | /* Command line argument have priority on settings */ |
| 757 | 771 | if( zArgIncludeBinary ){ |
| 758 | 772 | return is_truth(zArgIncludeBinary); |
| 759 | 773 | }else{ |
| 760 | 774 | return db_get_boolean("diff-binary", 1); |
| 761 | 775 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -151,10 +151,13 @@ | |
| 151 | /* |
| 152 | ** Show the difference between two files, one in memory and one on disk. |
| 153 | ** |
| 154 | ** The difference is the set of edits needed to transform pFile1 into |
| 155 | ** zFile2. The content of pFile1 is in memory. zFile2 exists on disk. |
| 156 | ** |
| 157 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 158 | ** command zDiffCmd to do the diffing. |
| 159 | ** |
| 160 | ** When using an external diff program, zBinGlob contains the GLOB patterns |
| @@ -167,11 +170,12 @@ | |
| 167 | const char *zFile2, /* On disk content to compare to */ |
| 168 | const char *zName, /* Display name of the file */ |
| 169 | const char *zDiffCmd, /* Command for comparison */ |
| 170 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 171 | int fIncludeBinary, /* Include binary files for external diff */ |
| 172 | u64 diffFlags /* Flags to control the diff */ |
| 173 | ){ |
| 174 | if( zDiffCmd==0 ){ |
| 175 | Blob out; /* Diff output text */ |
| 176 | Blob file2; /* Content of zFile2 */ |
| 177 | const char *zName2; /* Name of zFile2 for display */ |
| @@ -194,11 +198,15 @@ | |
| 194 | if( blob_compare(pFile1, &file2) ){ |
| 195 | fossil_print("CHANGED %s\n", zName); |
| 196 | } |
| 197 | }else{ |
| 198 | blob_zero(&out); |
| 199 | text_diff(pFile1, &file2, &out, 0, diffFlags); |
| 200 | if( blob_size(&out) ){ |
| 201 | diff_print_filenames(zName, zName2, diffFlags); |
| 202 | fossil_print("%s\n", blob_str(&out)); |
| 203 | } |
| 204 | blob_reset(&out); |
| @@ -252,13 +260,19 @@ | |
| 252 | blob_write_to_file(pFile1, blob_str(&nameFile1)); |
| 253 | |
| 254 | /* Construct the external diff command */ |
| 255 | blob_zero(&cmd); |
| 256 | blob_appendf(&cmd, "%s ", zDiffCmd); |
| 257 | shell_escape(&cmd, blob_str(&nameFile1)); |
| 258 | blob_append(&cmd, " ", 1); |
| 259 | shell_escape(&cmd, zFile2); |
| 260 | |
| 261 | /* Run the external diff command */ |
| 262 | fossil_system(blob_str(&cmd)); |
| 263 | |
| 264 | /* Delete the temporary file and clean up memory used */ |
| @@ -482,11 +496,11 @@ | |
| 482 | blob_zero(&content); |
| 483 | } |
| 484 | isBin = fIncludeBinary ? 0 : looks_like_binary(&content); |
| 485 | diff_print_index(zPathname, diffFlags); |
| 486 | diff_file(&content, isBin, zFullName, zPathname, zDiffCmd, |
| 487 | zBinGlob, fIncludeBinary, diffFlags); |
| 488 | blob_reset(&content); |
| 489 | } |
| 490 | blob_reset(&fname); |
| 491 | } |
| 492 | db_finalize(&q); |
| @@ -519,11 +533,11 @@ | |
| 519 | const char *zFile = (const char*)db_column_text(&q, 0); |
| 520 | if( !file_dir_match(pFileDir, zFile) ) continue; |
| 521 | zFullName = mprintf("%s%s", g.zLocalRoot, zFile); |
| 522 | db_column_blob(&q, 1, &content); |
| 523 | diff_file(&content, 0, zFullName, zFile, |
| 524 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); |
| 525 | fossil_free(zFullName); |
| 526 | blob_reset(&content); |
| 527 | } |
| 528 | db_finalize(&q); |
| 529 | } |
| @@ -750,11 +764,11 @@ | |
| 750 | ** Returns non-zero if files that may be binary should be used with external |
| 751 | ** diff programs. |
| 752 | */ |
| 753 | int diff_include_binary_files(void){ |
| 754 | const char* zArgIncludeBinary = find_option("diff-binary", 0, 1); |
| 755 | |
| 756 | /* Command line argument have priority on settings */ |
| 757 | if( zArgIncludeBinary ){ |
| 758 | return is_truth(zArgIncludeBinary); |
| 759 | }else{ |
| 760 | return db_get_boolean("diff-binary", 1); |
| 761 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -151,10 +151,13 @@ | |
| 151 | /* |
| 152 | ** Show the difference between two files, one in memory and one on disk. |
| 153 | ** |
| 154 | ** The difference is the set of edits needed to transform pFile1 into |
| 155 | ** zFile2. The content of pFile1 is in memory. zFile2 exists on disk. |
| 156 | ** |
| 157 | ** If fSwapDiff is 1, show the set of edits to transform zFile2 into pFile1 |
| 158 | ** instead of the opposite. |
| 159 | ** |
| 160 | ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the |
| 161 | ** command zDiffCmd to do the diffing. |
| 162 | ** |
| 163 | ** When using an external diff program, zBinGlob contains the GLOB patterns |
| @@ -167,11 +170,12 @@ | |
| 170 | const char *zFile2, /* On disk content to compare to */ |
| 171 | const char *zName, /* Display name of the file */ |
| 172 | const char *zDiffCmd, /* Command for comparison */ |
| 173 | const char *zBinGlob, /* Treat file names matching this as binary */ |
| 174 | int fIncludeBinary, /* Include binary files for external diff */ |
| 175 | u64 diffFlags, /* Flags to control the diff */ |
| 176 | int fSwapDiff /* Diff from Zfile2 to Pfile1 */ |
| 177 | ){ |
| 178 | if( zDiffCmd==0 ){ |
| 179 | Blob out; /* Diff output text */ |
| 180 | Blob file2; /* Content of zFile2 */ |
| 181 | const char *zName2; /* Name of zFile2 for display */ |
| @@ -194,11 +198,15 @@ | |
| 198 | if( blob_compare(pFile1, &file2) ){ |
| 199 | fossil_print("CHANGED %s\n", zName); |
| 200 | } |
| 201 | }else{ |
| 202 | blob_zero(&out); |
| 203 | if( fSwapDiff ){ |
| 204 | text_diff(&file2, pFile1, &out, 0, diffFlags); |
| 205 | }else{ |
| 206 | text_diff(pFile1, &file2, &out, 0, diffFlags); |
| 207 | } |
| 208 | if( blob_size(&out) ){ |
| 209 | diff_print_filenames(zName, zName2, diffFlags); |
| 210 | fossil_print("%s\n", blob_str(&out)); |
| 211 | } |
| 212 | blob_reset(&out); |
| @@ -252,13 +260,19 @@ | |
| 260 | blob_write_to_file(pFile1, blob_str(&nameFile1)); |
| 261 | |
| 262 | /* Construct the external diff command */ |
| 263 | blob_zero(&cmd); |
| 264 | blob_appendf(&cmd, "%s ", zDiffCmd); |
| 265 | if( fSwapDiff ){ |
| 266 | shell_escape(&cmd, zFile2); |
| 267 | blob_append(&cmd, " ", 1); |
| 268 | shell_escape(&cmd, blob_str(&nameFile1)); |
| 269 | }else{ |
| 270 | shell_escape(&cmd, blob_str(&nameFile1)); |
| 271 | blob_append(&cmd, " ", 1); |
| 272 | shell_escape(&cmd, zFile2); |
| 273 | } |
| 274 | |
| 275 | /* Run the external diff command */ |
| 276 | fossil_system(blob_str(&cmd)); |
| 277 | |
| 278 | /* Delete the temporary file and clean up memory used */ |
| @@ -482,11 +496,11 @@ | |
| 496 | blob_zero(&content); |
| 497 | } |
| 498 | isBin = fIncludeBinary ? 0 : looks_like_binary(&content); |
| 499 | diff_print_index(zPathname, diffFlags); |
| 500 | diff_file(&content, isBin, zFullName, zPathname, zDiffCmd, |
| 501 | zBinGlob, fIncludeBinary, diffFlags, 0); |
| 502 | blob_reset(&content); |
| 503 | } |
| 504 | blob_reset(&fname); |
| 505 | } |
| 506 | db_finalize(&q); |
| @@ -519,11 +533,11 @@ | |
| 533 | const char *zFile = (const char*)db_column_text(&q, 0); |
| 534 | if( !file_dir_match(pFileDir, zFile) ) continue; |
| 535 | zFullName = mprintf("%s%s", g.zLocalRoot, zFile); |
| 536 | db_column_blob(&q, 1, &content); |
| 537 | diff_file(&content, 0, zFullName, zFile, |
| 538 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags, 0); |
| 539 | fossil_free(zFullName); |
| 540 | blob_reset(&content); |
| 541 | } |
| 542 | db_finalize(&q); |
| 543 | } |
| @@ -750,11 +764,11 @@ | |
| 764 | ** Returns non-zero if files that may be binary should be used with external |
| 765 | ** diff programs. |
| 766 | */ |
| 767 | int diff_include_binary_files(void){ |
| 768 | const char* zArgIncludeBinary = find_option("diff-binary", 0, 1); |
| 769 | |
| 770 | /* Command line argument have priority on settings */ |
| 771 | if( zArgIncludeBinary ){ |
| 772 | return is_truth(zArgIncludeBinary); |
| 773 | }else{ |
| 774 | return db_get_boolean("diff-binary", 1); |
| 775 |
+12
-4
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -527,11 +527,11 @@ | ||
| 527 | 527 | ** WEBPAGE: uv |
| 528 | 528 | ** WEBPAGE: doc |
| 529 | 529 | ** URL: /uv/FILE |
| 530 | 530 | ** URL: /doc/CHECKIN/FILE |
| 531 | 531 | ** |
| 532 | -** CHECKIN can be either tag or SHA1 hash or timestamp identifying a | |
| 532 | +** CHECKIN can be either tag or hash prefix or timestamp identifying a | |
| 533 | 533 | ** particular check, or the name of a branch (meaning the most recent |
| 534 | 534 | ** check-in on that branch) or one of various magic words: |
| 535 | 535 | ** |
| 536 | 536 | ** "tip" means the most recent check-in |
| 537 | 537 | ** |
| @@ -708,13 +708,21 @@ | ||
| 708 | 708 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 709 | 709 | }else if( Th_AreDocsEnabled() && |
| 710 | 710 | fossil_strcmp(zMime, "application/x-th1")==0 ){ |
| 711 | 711 | int raw = P("raw")!=0; |
| 712 | 712 | if( !raw ){ |
| 713 | - style_header("%h", zName); | |
| 713 | + Blob tail; | |
| 714 | + blob_zero(&tail); | |
| 715 | + if( wiki_find_title(&filebody, &title, &tail) ){ | |
| 716 | + style_header("%s", blob_str(&title)); | |
| 717 | + Th_Render(blob_str(&tail)); | |
| 718 | + blob_reset(&tail); | |
| 719 | + }else{ | |
| 720 | + style_header("%h", zName); | |
| 721 | + Th_Render(blob_str(&filebody)); | |
| 722 | + } | |
| 714 | 723 | } |
| 715 | - Th_Render(blob_str(&filebody)); | |
| 716 | 724 | if( !raw ){ |
| 717 | 725 | style_footer(); |
| 718 | 726 | } |
| 719 | 727 | #endif |
| 720 | 728 | }else{ |
| @@ -727,11 +735,11 @@ | ||
| 727 | 735 | |
| 728 | 736 | /* Jump here when unable to locate the document */ |
| 729 | 737 | doc_not_found: |
| 730 | 738 | db_end_transaction(0); |
| 731 | 739 | if( isUV && P("name")==0 ){ |
| 732 | - uvstat_page(); | |
| 740 | + uvlist_page(); | |
| 733 | 741 | return; |
| 734 | 742 | } |
| 735 | 743 | cgi_set_status(404, "Not Found"); |
| 736 | 744 | style_header("Not Found"); |
| 737 | 745 | @ <p>Document %h(zOrigName) not found |
| 738 | 746 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -527,11 +527,11 @@ | |
| 527 | ** WEBPAGE: uv |
| 528 | ** WEBPAGE: doc |
| 529 | ** URL: /uv/FILE |
| 530 | ** URL: /doc/CHECKIN/FILE |
| 531 | ** |
| 532 | ** CHECKIN can be either tag or SHA1 hash or timestamp identifying a |
| 533 | ** particular check, or the name of a branch (meaning the most recent |
| 534 | ** check-in on that branch) or one of various magic words: |
| 535 | ** |
| 536 | ** "tip" means the most recent check-in |
| 537 | ** |
| @@ -708,13 +708,21 @@ | |
| 708 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 709 | }else if( Th_AreDocsEnabled() && |
| 710 | fossil_strcmp(zMime, "application/x-th1")==0 ){ |
| 711 | int raw = P("raw")!=0; |
| 712 | if( !raw ){ |
| 713 | style_header("%h", zName); |
| 714 | } |
| 715 | Th_Render(blob_str(&filebody)); |
| 716 | if( !raw ){ |
| 717 | style_footer(); |
| 718 | } |
| 719 | #endif |
| 720 | }else{ |
| @@ -727,11 +735,11 @@ | |
| 727 | |
| 728 | /* Jump here when unable to locate the document */ |
| 729 | doc_not_found: |
| 730 | db_end_transaction(0); |
| 731 | if( isUV && P("name")==0 ){ |
| 732 | uvstat_page(); |
| 733 | return; |
| 734 | } |
| 735 | cgi_set_status(404, "Not Found"); |
| 736 | style_header("Not Found"); |
| 737 | @ <p>Document %h(zOrigName) not found |
| 738 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -527,11 +527,11 @@ | |
| 527 | ** WEBPAGE: uv |
| 528 | ** WEBPAGE: doc |
| 529 | ** URL: /uv/FILE |
| 530 | ** URL: /doc/CHECKIN/FILE |
| 531 | ** |
| 532 | ** CHECKIN can be either tag or hash prefix or timestamp identifying a |
| 533 | ** particular check, or the name of a branch (meaning the most recent |
| 534 | ** check-in on that branch) or one of various magic words: |
| 535 | ** |
| 536 | ** "tip" means the most recent check-in |
| 537 | ** |
| @@ -708,13 +708,21 @@ | |
| 708 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 709 | }else if( Th_AreDocsEnabled() && |
| 710 | fossil_strcmp(zMime, "application/x-th1")==0 ){ |
| 711 | int raw = P("raw")!=0; |
| 712 | if( !raw ){ |
| 713 | Blob tail; |
| 714 | blob_zero(&tail); |
| 715 | if( wiki_find_title(&filebody, &title, &tail) ){ |
| 716 | style_header("%s", blob_str(&title)); |
| 717 | Th_Render(blob_str(&tail)); |
| 718 | blob_reset(&tail); |
| 719 | }else{ |
| 720 | style_header("%h", zName); |
| 721 | Th_Render(blob_str(&filebody)); |
| 722 | } |
| 723 | } |
| 724 | if( !raw ){ |
| 725 | style_footer(); |
| 726 | } |
| 727 | #endif |
| 728 | }else{ |
| @@ -727,11 +735,11 @@ | |
| 735 | |
| 736 | /* Jump here when unable to locate the document */ |
| 737 | doc_not_found: |
| 738 | db_end_transaction(0); |
| 739 | if( isUV && P("name")==0 ){ |
| 740 | uvlist_page(); |
| 741 | return; |
| 742 | } |
| 743 | cgi_set_status(404, "Not Found"); |
| 744 | style_header("Not Found"); |
| 745 | @ <p>Document %h(zOrigName) not found |
| 746 |
+90
| --- src/encode.c | ||
| +++ src/encode.c | ||
| @@ -336,10 +336,100 @@ | ||
| 336 | 336 | z[j++] = c; |
| 337 | 337 | } |
| 338 | 338 | if( z[j] ) z[j] = 0; |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | + | |
| 342 | +/* | |
| 343 | +** The *pz variable points to a UTF8 string. Read the next character | |
| 344 | +** off of that string and return its codepoint value. Advance *pz to the | |
| 345 | +** next character | |
| 346 | +*/ | |
| 347 | +u32 fossil_utf8_read( | |
| 348 | + const unsigned char **pz /* Pointer to string from which to read char */ | |
| 349 | +){ | |
| 350 | + unsigned int c; | |
| 351 | + | |
| 352 | + /* | |
| 353 | + ** This lookup table is used to help decode the first byte of | |
| 354 | + ** a multi-byte UTF8 character. | |
| 355 | + */ | |
| 356 | + static const unsigned char utf8Trans1[] = { | |
| 357 | + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |
| 358 | + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | |
| 359 | + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |
| 360 | + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | |
| 361 | + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |
| 362 | + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | |
| 363 | + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |
| 364 | + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, | |
| 365 | + }; | |
| 366 | + | |
| 367 | + c = *((*pz)++); | |
| 368 | + if( c>=0xc0 ){ | |
| 369 | + c = utf8Trans1[c-0xc0]; | |
| 370 | + while( (*(*pz) & 0xc0)==0x80 ){ | |
| 371 | + c = (c<<6) + (0x3f & *((*pz)++)); | |
| 372 | + } | |
| 373 | + if( c<0x80 | |
| 374 | + || (c&0xFFFFF800)==0xD800 | |
| 375 | + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } | |
| 376 | + } | |
| 377 | + return c; | |
| 378 | +} | |
| 379 | + | |
| 380 | +/* | |
| 381 | +** Encode a UTF8 string for JSON. All special characters are escaped. | |
| 382 | +*/ | |
| 383 | +void blob_append_json_string(Blob *pBlob, const char *zStr){ | |
| 384 | + const unsigned char *z; | |
| 385 | + char *zOut; | |
| 386 | + u32 c; | |
| 387 | + int n, i, j; | |
| 388 | + z = (const unsigned char*)zStr; | |
| 389 | + n = 0; | |
| 390 | + while( (c = fossil_utf8_read(&z))!=0 ){ | |
| 391 | + if( c=='\\' || c=='"' ){ | |
| 392 | + n += 2; | |
| 393 | + }else if( c<' ' || c>=0x7f ){ | |
| 394 | + if( c=='\n' || c=='\r' ){ | |
| 395 | + n += 2; | |
| 396 | + }else{ | |
| 397 | + n += 6; | |
| 398 | + } | |
| 399 | + }else{ | |
| 400 | + n++; | |
| 401 | + } | |
| 402 | + } | |
| 403 | + i = blob_size(pBlob); | |
| 404 | + blob_resize(pBlob, i+n); | |
| 405 | + zOut = blob_buffer(pBlob); | |
| 406 | + z = (const unsigned char*)zStr; | |
| 407 | + while( (c = fossil_utf8_read(&z))!=0 ){ | |
| 408 | + if( c=='\\' ){ | |
| 409 | + zOut[i++] = '\\'; | |
| 410 | + zOut[i++] = c; | |
| 411 | + }else if( c<' ' || c>=0x7f ){ | |
| 412 | + zOut[i++] = '\\'; | |
| 413 | + if( c=='\n' ){ | |
| 414 | + zOut[i++] = 'n'; | |
| 415 | + }else if( c=='\r' ){ | |
| 416 | + zOut[i++] = 'r'; | |
| 417 | + }else{ | |
| 418 | + zOut[i++] = 'u'; | |
| 419 | + for(j=3; j>=0; j--){ | |
| 420 | + zOut[i+j] = "0123456789abcdef"[c&0xf]; | |
| 421 | + c >>= 4; | |
| 422 | + } | |
| 423 | + i += 4; | |
| 424 | + } | |
| 425 | + }else{ | |
| 426 | + zOut[i++] = c; | |
| 427 | + } | |
| 428 | + } | |
| 429 | + zOut[i] = 0; | |
| 430 | +} | |
| 341 | 431 | |
| 342 | 432 | /* |
| 343 | 433 | ** The characters used for HTTP base64 encoding. |
| 344 | 434 | */ |
| 345 | 435 | static unsigned char zBase[] = |
| 346 | 436 |
| --- src/encode.c | |
| +++ src/encode.c | |
| @@ -336,10 +336,100 @@ | |
| 336 | z[j++] = c; |
| 337 | } |
| 338 | if( z[j] ) z[j] = 0; |
| 339 | } |
| 340 | |
| 341 | |
| 342 | /* |
| 343 | ** The characters used for HTTP base64 encoding. |
| 344 | */ |
| 345 | static unsigned char zBase[] = |
| 346 |
| --- src/encode.c | |
| +++ src/encode.c | |
| @@ -336,10 +336,100 @@ | |
| 336 | z[j++] = c; |
| 337 | } |
| 338 | if( z[j] ) z[j] = 0; |
| 339 | } |
| 340 | |
| 341 | |
| 342 | /* |
| 343 | ** The *pz variable points to a UTF8 string. Read the next character |
| 344 | ** off of that string and return its codepoint value. Advance *pz to the |
| 345 | ** next character |
| 346 | */ |
| 347 | u32 fossil_utf8_read( |
| 348 | const unsigned char **pz /* Pointer to string from which to read char */ |
| 349 | ){ |
| 350 | unsigned int c; |
| 351 | |
| 352 | /* |
| 353 | ** This lookup table is used to help decode the first byte of |
| 354 | ** a multi-byte UTF8 character. |
| 355 | */ |
| 356 | static const unsigned char utf8Trans1[] = { |
| 357 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 358 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 359 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 360 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
| 361 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 362 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 363 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 364 | 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, |
| 365 | }; |
| 366 | |
| 367 | c = *((*pz)++); |
| 368 | if( c>=0xc0 ){ |
| 369 | c = utf8Trans1[c-0xc0]; |
| 370 | while( (*(*pz) & 0xc0)==0x80 ){ |
| 371 | c = (c<<6) + (0x3f & *((*pz)++)); |
| 372 | } |
| 373 | if( c<0x80 |
| 374 | || (c&0xFFFFF800)==0xD800 |
| 375 | || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } |
| 376 | } |
| 377 | return c; |
| 378 | } |
| 379 | |
| 380 | /* |
| 381 | ** Encode a UTF8 string for JSON. All special characters are escaped. |
| 382 | */ |
| 383 | void blob_append_json_string(Blob *pBlob, const char *zStr){ |
| 384 | const unsigned char *z; |
| 385 | char *zOut; |
| 386 | u32 c; |
| 387 | int n, i, j; |
| 388 | z = (const unsigned char*)zStr; |
| 389 | n = 0; |
| 390 | while( (c = fossil_utf8_read(&z))!=0 ){ |
| 391 | if( c=='\\' || c=='"' ){ |
| 392 | n += 2; |
| 393 | }else if( c<' ' || c>=0x7f ){ |
| 394 | if( c=='\n' || c=='\r' ){ |
| 395 | n += 2; |
| 396 | }else{ |
| 397 | n += 6; |
| 398 | } |
| 399 | }else{ |
| 400 | n++; |
| 401 | } |
| 402 | } |
| 403 | i = blob_size(pBlob); |
| 404 | blob_resize(pBlob, i+n); |
| 405 | zOut = blob_buffer(pBlob); |
| 406 | z = (const unsigned char*)zStr; |
| 407 | while( (c = fossil_utf8_read(&z))!=0 ){ |
| 408 | if( c=='\\' ){ |
| 409 | zOut[i++] = '\\'; |
| 410 | zOut[i++] = c; |
| 411 | }else if( c<' ' || c>=0x7f ){ |
| 412 | zOut[i++] = '\\'; |
| 413 | if( c=='\n' ){ |
| 414 | zOut[i++] = 'n'; |
| 415 | }else if( c=='\r' ){ |
| 416 | zOut[i++] = 'r'; |
| 417 | }else{ |
| 418 | zOut[i++] = 'u'; |
| 419 | for(j=3; j>=0; j--){ |
| 420 | zOut[i+j] = "0123456789abcdef"[c&0xf]; |
| 421 | c >>= 4; |
| 422 | } |
| 423 | i += 4; |
| 424 | } |
| 425 | }else{ |
| 426 | zOut[i++] = c; |
| 427 | } |
| 428 | } |
| 429 | zOut[i] = 0; |
| 430 | } |
| 431 | |
| 432 | /* |
| 433 | ** The characters used for HTTP base64 encoding. |
| 434 | */ |
| 435 | static unsigned char zBase[] = |
| 436 |
+1
-1
| --- src/event.c | ||
| +++ src/event.c | ||
| @@ -384,11 +384,11 @@ | ||
| 384 | 384 | rid = db_int(0, |
| 385 | 385 | "SELECT rid FROM tagxref" |
| 386 | 386 | " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')" |
| 387 | 387 | " ORDER BY mtime DESC", zTag |
| 388 | 388 | ); |
| 389 | - if( rid && strlen(zId)<40 ){ | |
| 389 | + if( rid && strlen(zId)<HNAME_MIN ){ | |
| 390 | 390 | zId = db_text(0, |
| 391 | 391 | "SELECT substr(tagname,7) FROM tag WHERE tagname GLOB '%q*'", |
| 392 | 392 | zTag |
| 393 | 393 | ); |
| 394 | 394 | } |
| 395 | 395 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -384,11 +384,11 @@ | |
| 384 | rid = db_int(0, |
| 385 | "SELECT rid FROM tagxref" |
| 386 | " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')" |
| 387 | " ORDER BY mtime DESC", zTag |
| 388 | ); |
| 389 | if( rid && strlen(zId)<40 ){ |
| 390 | zId = db_text(0, |
| 391 | "SELECT substr(tagname,7) FROM tag WHERE tagname GLOB '%q*'", |
| 392 | zTag |
| 393 | ); |
| 394 | } |
| 395 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -384,11 +384,11 @@ | |
| 384 | rid = db_int(0, |
| 385 | "SELECT rid FROM tagxref" |
| 386 | " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')" |
| 387 | " ORDER BY mtime DESC", zTag |
| 388 | ); |
| 389 | if( rid && strlen(zId)<HNAME_MIN ){ |
| 390 | zId = db_text(0, |
| 391 | "SELECT substr(tagname,7) FROM tag WHERE tagname GLOB '%q*'", |
| 392 | zTag |
| 393 | ); |
| 394 | } |
| 395 |
+1
-1
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -261,11 +261,11 @@ | ||
| 261 | 261 | cur_tok = strtok(NULL, " \t"); |
| 262 | 262 | if( !cur_tok ){ |
| 263 | 263 | /* This mark was generated by an older version of Fossil and doesn't |
| 264 | 264 | ** include the mark name and uuid. create_mark() will name the new mark |
| 265 | 265 | ** exactly as it was when exported to git, so that we should have a |
| 266 | - ** valid mapping from git sha1<->mark name<->fossil sha1. */ | |
| 266 | + ** valid mapping from git hash<->mark name<->fossil hash. */ | |
| 267 | 267 | unsigned int mid; |
| 268 | 268 | if( type_=='c' ){ |
| 269 | 269 | mid = COMMITMARK(mark->rid); |
| 270 | 270 | } |
| 271 | 271 | else{ |
| 272 | 272 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -261,11 +261,11 @@ | |
| 261 | cur_tok = strtok(NULL, " \t"); |
| 262 | if( !cur_tok ){ |
| 263 | /* This mark was generated by an older version of Fossil and doesn't |
| 264 | ** include the mark name and uuid. create_mark() will name the new mark |
| 265 | ** exactly as it was when exported to git, so that we should have a |
| 266 | ** valid mapping from git sha1<->mark name<->fossil sha1. */ |
| 267 | unsigned int mid; |
| 268 | if( type_=='c' ){ |
| 269 | mid = COMMITMARK(mark->rid); |
| 270 | } |
| 271 | else{ |
| 272 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -261,11 +261,11 @@ | |
| 261 | cur_tok = strtok(NULL, " \t"); |
| 262 | if( !cur_tok ){ |
| 263 | /* This mark was generated by an older version of Fossil and doesn't |
| 264 | ** include the mark name and uuid. create_mark() will name the new mark |
| 265 | ** exactly as it was when exported to git, so that we should have a |
| 266 | ** valid mapping from git hash<->mark name<->fossil hash. */ |
| 267 | unsigned int mid; |
| 268 | if( type_=='c' ){ |
| 269 | mid = COMMITMARK(mark->rid); |
| 270 | } |
| 271 | else{ |
| 272 |
+2
-2
| --- src/foci.c | ||
| +++ src/foci.c | ||
| @@ -28,11 +28,11 @@ | ||
| 28 | 28 | ** The "schema" for the temp.foci table is: |
| 29 | 29 | ** |
| 30 | 30 | ** CREATE TABLE files_of_checkin( |
| 31 | 31 | ** checkinID INTEGER, -- RID for the check-in manifest |
| 32 | 32 | ** filename TEXT, -- Name of a file |
| 33 | -** uuid TEXT, -- SHA1 hash of the file | |
| 33 | +** uuid TEXT, -- hash of the file | |
| 34 | 34 | ** previousName TEXT, -- Name of the file in previous check-in |
| 35 | 35 | ** perm TEXT, -- Permissions on the file |
| 36 | 36 | ** symname TEXT HIDDEN -- Symbolic name of the check-in. |
| 37 | 37 | ** ); |
| 38 | 38 | ** |
| @@ -54,11 +54,11 @@ | ||
| 54 | 54 | */ |
| 55 | 55 | static const char zFociSchema[] = |
| 56 | 56 | @ CREATE TABLE files_of_checkin( |
| 57 | 57 | @ checkinID INTEGER, -- RID for the check-in manifest |
| 58 | 58 | @ filename TEXT, -- Name of a file |
| 59 | -@ uuid TEXT, -- SHA1 hash of the file | |
| 59 | +@ uuid TEXT, -- hash of the file | |
| 60 | 60 | @ previousName TEXT, -- Name of the file in previous check-in |
| 61 | 61 | @ perm TEXT, -- Permissions on the file |
| 62 | 62 | @ symname TEXT HIDDEN -- Symbolic name of the check-in |
| 63 | 63 | @ ); |
| 64 | 64 | ; |
| 65 | 65 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -28,11 +28,11 @@ | |
| 28 | ** The "schema" for the temp.foci table is: |
| 29 | ** |
| 30 | ** CREATE TABLE files_of_checkin( |
| 31 | ** checkinID INTEGER, -- RID for the check-in manifest |
| 32 | ** filename TEXT, -- Name of a file |
| 33 | ** uuid TEXT, -- SHA1 hash of the file |
| 34 | ** previousName TEXT, -- Name of the file in previous check-in |
| 35 | ** perm TEXT, -- Permissions on the file |
| 36 | ** symname TEXT HIDDEN -- Symbolic name of the check-in. |
| 37 | ** ); |
| 38 | ** |
| @@ -54,11 +54,11 @@ | |
| 54 | */ |
| 55 | static const char zFociSchema[] = |
| 56 | @ CREATE TABLE files_of_checkin( |
| 57 | @ checkinID INTEGER, -- RID for the check-in manifest |
| 58 | @ filename TEXT, -- Name of a file |
| 59 | @ uuid TEXT, -- SHA1 hash of the file |
| 60 | @ previousName TEXT, -- Name of the file in previous check-in |
| 61 | @ perm TEXT, -- Permissions on the file |
| 62 | @ symname TEXT HIDDEN -- Symbolic name of the check-in |
| 63 | @ ); |
| 64 | ; |
| 65 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -28,11 +28,11 @@ | |
| 28 | ** The "schema" for the temp.foci table is: |
| 29 | ** |
| 30 | ** CREATE TABLE files_of_checkin( |
| 31 | ** checkinID INTEGER, -- RID for the check-in manifest |
| 32 | ** filename TEXT, -- Name of a file |
| 33 | ** uuid TEXT, -- hash of the file |
| 34 | ** previousName TEXT, -- Name of the file in previous check-in |
| 35 | ** perm TEXT, -- Permissions on the file |
| 36 | ** symname TEXT HIDDEN -- Symbolic name of the check-in. |
| 37 | ** ); |
| 38 | ** |
| @@ -54,11 +54,11 @@ | |
| 54 | */ |
| 55 | static const char zFociSchema[] = |
| 56 | @ CREATE TABLE files_of_checkin( |
| 57 | @ checkinID INTEGER, -- RID for the check-in manifest |
| 58 | @ filename TEXT, -- Name of a file |
| 59 | @ uuid TEXT, -- hash of the file |
| 60 | @ previousName TEXT, -- Name of the file in previous check-in |
| 61 | @ perm TEXT, -- Permissions on the file |
| 62 | @ symname TEXT HIDDEN -- Symbolic name of the check-in |
| 63 | @ ); |
| 64 | ; |
| 65 |
+1
-1
| --- src/fusefs.c | ||
| +++ src/fusefs.c | ||
| @@ -294,11 +294,11 @@ | ||
| 294 | 294 | ** This command uses the Fuse Filesystem (FuseFS) to mount a directory |
| 295 | 295 | ** at DIRECTORY that contains the content of all check-ins in the |
| 296 | 296 | ** repository. The names of files are DIRECTORY/checkins/VERSION/PATH |
| 297 | 297 | ** where DIRECTORY is the root of the mount, VERSION is any valid |
| 298 | 298 | ** check-in name (examples: "trunk" or "tip" or a tag or any unique |
| 299 | -** prefix of a SHA1 hash, etc) and PATH is the pathname of the file in | |
| 299 | +** prefix of an artifact hash, etc) and PATH is the pathname of the file in | |
| 300 | 300 | ** the check-in. If DIRECTORY does not exist, then an attempt is made |
| 301 | 301 | ** to create it. |
| 302 | 302 | ** |
| 303 | 303 | ** The DIRECTORY/checkins directory is not searchable so one cannot |
| 304 | 304 | ** do "ls DIRECTORY/checkins" to get a listing of all possible check-in |
| 305 | 305 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -294,11 +294,11 @@ | |
| 294 | ** This command uses the Fuse Filesystem (FuseFS) to mount a directory |
| 295 | ** at DIRECTORY that contains the content of all check-ins in the |
| 296 | ** repository. The names of files are DIRECTORY/checkins/VERSION/PATH |
| 297 | ** where DIRECTORY is the root of the mount, VERSION is any valid |
| 298 | ** check-in name (examples: "trunk" or "tip" or a tag or any unique |
| 299 | ** prefix of a SHA1 hash, etc) and PATH is the pathname of the file in |
| 300 | ** the check-in. If DIRECTORY does not exist, then an attempt is made |
| 301 | ** to create it. |
| 302 | ** |
| 303 | ** The DIRECTORY/checkins directory is not searchable so one cannot |
| 304 | ** do "ls DIRECTORY/checkins" to get a listing of all possible check-in |
| 305 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -294,11 +294,11 @@ | |
| 294 | ** This command uses the Fuse Filesystem (FuseFS) to mount a directory |
| 295 | ** at DIRECTORY that contains the content of all check-ins in the |
| 296 | ** repository. The names of files are DIRECTORY/checkins/VERSION/PATH |
| 297 | ** where DIRECTORY is the root of the mount, VERSION is any valid |
| 298 | ** check-in name (examples: "trunk" or "tip" or a tag or any unique |
| 299 | ** prefix of an artifact hash, etc) and PATH is the pathname of the file in |
| 300 | ** the check-in. If DIRECTORY does not exist, then an attempt is made |
| 301 | ** to create it. |
| 302 | ** |
| 303 | ** The DIRECTORY/checkins directory is not searchable so one cannot |
| 304 | ** do "ls DIRECTORY/checkins" to get a listing of all possible check-in |
| 305 |
+1
-1
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -179,11 +179,11 @@ | ||
| 179 | 179 | int rid, /* RID for the check-in */ |
| 180 | 180 | int nParent, /* Number of parents */ |
| 181 | 181 | int *aParent, /* Array of parents */ |
| 182 | 182 | const char *zBranch, /* Branch for this check-in */ |
| 183 | 183 | const char *zBgClr, /* Background color. NULL or "" for white. */ |
| 184 | - const char *zUuid, /* SHA1 hash of the object being graphed */ | |
| 184 | + const char *zUuid, /* hash name of the object being graphed */ | |
| 185 | 185 | int isLeaf /* True if this row is a leaf */ |
| 186 | 186 | ){ |
| 187 | 187 | GraphRow *pRow; |
| 188 | 188 | int nByte; |
| 189 | 189 | |
| 190 | 190 | |
| 191 | 191 | ADDED src/hname.c |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -179,11 +179,11 @@ | |
| 179 | int rid, /* RID for the check-in */ |
| 180 | int nParent, /* Number of parents */ |
| 181 | int *aParent, /* Array of parents */ |
| 182 | const char *zBranch, /* Branch for this check-in */ |
| 183 | const char *zBgClr, /* Background color. NULL or "" for white. */ |
| 184 | const char *zUuid, /* SHA1 hash of the object being graphed */ |
| 185 | int isLeaf /* True if this row is a leaf */ |
| 186 | ){ |
| 187 | GraphRow *pRow; |
| 188 | int nByte; |
| 189 | |
| 190 | |
| 191 | DDED src/hname.c |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -179,11 +179,11 @@ | |
| 179 | int rid, /* RID for the check-in */ |
| 180 | int nParent, /* Number of parents */ |
| 181 | int *aParent, /* Array of parents */ |
| 182 | const char *zBranch, /* Branch for this check-in */ |
| 183 | const char *zBgClr, /* Background color. NULL or "" for white. */ |
| 184 | const char *zUuid, /* hash name of the object being graphed */ |
| 185 | int isLeaf /* True if this row is a leaf */ |
| 186 | ){ |
| 187 | GraphRow *pRow; |
| 188 | int nByte; |
| 189 | |
| 190 | |
| 191 | DDED src/hname.c |
+11
| --- a/src/hname.c | ||
| +++ b/src/hname.c | ||
| @@ -0,0 +1,11 @@ | ||
| 1 | +/* | |
| 2 | +** Copyright (c) 2017 D. Richard Hipp | |
| 3 | +** | |
| 4 | +** This program is free software; you can redistribute it and/or | |
| 5 | +** modify it under the termoftware; you can redistribute it and/or | |
| 6 | +** modify it under the term/* | |
| 7 | +** Copyright (c) 2017 D. Richard Hipp | |
| 8 | +** | |
| 9 | +** This program is free software; you can redistribute it and/or | |
| 10 | +** modify it under the termsha1sum_file(zFileBlob hash; | |
| 11 | + |
| --- a/src/hname.c | |
| +++ b/src/hname.c | |
| @@ -0,0 +1,11 @@ | |
| --- a/src/hname.c | |
| +++ b/src/hname.c | |
| @@ -0,0 +1,11 @@ | |
| 1 | /* |
| 2 | ** Copyright (c) 2017 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the termoftware; you can redistribute it and/or |
| 6 | ** modify it under the term/* |
| 7 | ** Copyright (c) 2017 D. Richard Hipp |
| 8 | ** |
| 9 | ** This program is free software; you can redistribute it and/or |
| 10 | ** modify it under the termsha1sum_file(zFileBlob hash; |
| 11 |
+5
-6
| --- src/http_ssl.c | ||
| +++ src/http_ssl.c | ||
| @@ -252,14 +252,12 @@ | ||
| 252 | 252 | hasSavedCertificate = 1; |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | 255 | if( pUrlData->useProxy ){ |
| 256 | 256 | int rc; |
| 257 | - BIO *sBio; | |
| 258 | - char *connStr; | |
| 259 | - connStr = mprintf("%s:%d", g.url.name, pUrlData->port); | |
| 260 | - sBio = BIO_new_connect(connStr); | |
| 257 | + char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port); | |
| 258 | + BIO *sBio = BIO_new_connect(connStr); | |
| 261 | 259 | free(connStr); |
| 262 | 260 | if( BIO_do_connect(sBio)<=0 ){ |
| 263 | 261 | ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)", |
| 264 | 262 | pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); |
| 265 | 263 | ssl_close(); |
| @@ -293,12 +291,13 @@ | ||
| 293 | 291 | #endif |
| 294 | 292 | |
| 295 | 293 | SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); |
| 296 | 294 | |
| 297 | 295 | if( !pUrlData->useProxy ){ |
| 298 | - BIO_set_conn_hostname(iBio, pUrlData->name); | |
| 299 | - BIO_ctrl(iBio,BIO_C_SET_CONNECT,3,(char *)&pUrlData->port); | |
| 296 | + char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port); | |
| 297 | + BIO_set_conn_hostname(iBio, connStr); | |
| 298 | + free(connStr); | |
| 300 | 299 | if( BIO_do_connect(iBio)<=0 ){ |
| 301 | 300 | ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", |
| 302 | 301 | pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); |
| 303 | 302 | ssl_close(); |
| 304 | 303 | return 1; |
| 305 | 304 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -252,14 +252,12 @@ | |
| 252 | hasSavedCertificate = 1; |
| 253 | } |
| 254 | |
| 255 | if( pUrlData->useProxy ){ |
| 256 | int rc; |
| 257 | BIO *sBio; |
| 258 | char *connStr; |
| 259 | connStr = mprintf("%s:%d", g.url.name, pUrlData->port); |
| 260 | sBio = BIO_new_connect(connStr); |
| 261 | free(connStr); |
| 262 | if( BIO_do_connect(sBio)<=0 ){ |
| 263 | ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)", |
| 264 | pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); |
| 265 | ssl_close(); |
| @@ -293,12 +291,13 @@ | |
| 293 | #endif |
| 294 | |
| 295 | SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); |
| 296 | |
| 297 | if( !pUrlData->useProxy ){ |
| 298 | BIO_set_conn_hostname(iBio, pUrlData->name); |
| 299 | BIO_ctrl(iBio,BIO_C_SET_CONNECT,3,(char *)&pUrlData->port); |
| 300 | if( BIO_do_connect(iBio)<=0 ){ |
| 301 | ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", |
| 302 | pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); |
| 303 | ssl_close(); |
| 304 | return 1; |
| 305 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -252,14 +252,12 @@ | |
| 252 | hasSavedCertificate = 1; |
| 253 | } |
| 254 | |
| 255 | if( pUrlData->useProxy ){ |
| 256 | int rc; |
| 257 | char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port); |
| 258 | BIO *sBio = BIO_new_connect(connStr); |
| 259 | free(connStr); |
| 260 | if( BIO_do_connect(sBio)<=0 ){ |
| 261 | ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)", |
| 262 | pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); |
| 263 | ssl_close(); |
| @@ -293,12 +291,13 @@ | |
| 291 | #endif |
| 292 | |
| 293 | SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); |
| 294 | |
| 295 | if( !pUrlData->useProxy ){ |
| 296 | char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port); |
| 297 | BIO_set_conn_hostname(iBio, connStr); |
| 298 | free(connStr); |
| 299 | if( BIO_do_connect(iBio)<=0 ){ |
| 300 | ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", |
| 301 | pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); |
| 302 | ssl_close(); |
| 303 | return 1; |
| 304 |
+3
-3
| --- src/import.c | ||
| +++ src/import.c | ||
| @@ -149,18 +149,18 @@ | ||
| 149 | 149 | ** UUID in gg.zPrevCheckin. |
| 150 | 150 | */ |
| 151 | 151 | static int fast_insert_content( |
| 152 | 152 | Blob *pContent, /* Content to insert */ |
| 153 | 153 | const char *zMark, /* Label using this mark, if not NULL */ |
| 154 | - int saveUuid, /* Save SHA1 hash in gg.zPrevCheckin */ | |
| 154 | + int saveUuid, /* Save artifact hash in gg.zPrevCheckin */ | |
| 155 | 155 | int doParse /* Invoke manifest_crosslink() */ |
| 156 | 156 | ){ |
| 157 | 157 | Blob hash; |
| 158 | 158 | Blob cmpr; |
| 159 | 159 | int rid; |
| 160 | 160 | |
| 161 | - sha1sum_blob(pContent, &hash); | |
| 161 | + hname_hash(pContent, 0, &hash); | |
| 162 | 162 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &hash); |
| 163 | 163 | if( rid==0 ){ |
| 164 | 164 | static Stmt ins; |
| 165 | 165 | db_static_prepare(&ins, |
| 166 | 166 | "INSERT INTO blob(uuid, size, content) VALUES(:uuid, :size, :content)" |
| @@ -1652,11 +1652,11 @@ | ||
| 1652 | 1652 | */ |
| 1653 | 1653 | const char *zIgnTree; |
| 1654 | 1654 | unsigned nIgnTree = 0; |
| 1655 | 1655 | while( (zIgnTree = find_option("ignore-tree", 0, 1)) ){ |
| 1656 | 1656 | if ( *zIgnTree ){ |
| 1657 | - gsvn.azIgnTree = fossil_realloc(gsvn.azIgnTree, | |
| 1657 | + gsvn.azIgnTree = fossil_realloc((void *)gsvn.azIgnTree, | |
| 1658 | 1658 | sizeof(*gsvn.azIgnTree) * (nIgnTree + 2)); |
| 1659 | 1659 | gsvn.azIgnTree[nIgnTree++] = zIgnTree; |
| 1660 | 1660 | gsvn.azIgnTree[nIgnTree] = 0; |
| 1661 | 1661 | } |
| 1662 | 1662 | } |
| 1663 | 1663 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -149,18 +149,18 @@ | |
| 149 | ** UUID in gg.zPrevCheckin. |
| 150 | */ |
| 151 | static int fast_insert_content( |
| 152 | Blob *pContent, /* Content to insert */ |
| 153 | const char *zMark, /* Label using this mark, if not NULL */ |
| 154 | int saveUuid, /* Save SHA1 hash in gg.zPrevCheckin */ |
| 155 | int doParse /* Invoke manifest_crosslink() */ |
| 156 | ){ |
| 157 | Blob hash; |
| 158 | Blob cmpr; |
| 159 | int rid; |
| 160 | |
| 161 | sha1sum_blob(pContent, &hash); |
| 162 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &hash); |
| 163 | if( rid==0 ){ |
| 164 | static Stmt ins; |
| 165 | db_static_prepare(&ins, |
| 166 | "INSERT INTO blob(uuid, size, content) VALUES(:uuid, :size, :content)" |
| @@ -1652,11 +1652,11 @@ | |
| 1652 | */ |
| 1653 | const char *zIgnTree; |
| 1654 | unsigned nIgnTree = 0; |
| 1655 | while( (zIgnTree = find_option("ignore-tree", 0, 1)) ){ |
| 1656 | if ( *zIgnTree ){ |
| 1657 | gsvn.azIgnTree = fossil_realloc(gsvn.azIgnTree, |
| 1658 | sizeof(*gsvn.azIgnTree) * (nIgnTree + 2)); |
| 1659 | gsvn.azIgnTree[nIgnTree++] = zIgnTree; |
| 1660 | gsvn.azIgnTree[nIgnTree] = 0; |
| 1661 | } |
| 1662 | } |
| 1663 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -149,18 +149,18 @@ | |
| 149 | ** UUID in gg.zPrevCheckin. |
| 150 | */ |
| 151 | static int fast_insert_content( |
| 152 | Blob *pContent, /* Content to insert */ |
| 153 | const char *zMark, /* Label using this mark, if not NULL */ |
| 154 | int saveUuid, /* Save artifact hash in gg.zPrevCheckin */ |
| 155 | int doParse /* Invoke manifest_crosslink() */ |
| 156 | ){ |
| 157 | Blob hash; |
| 158 | Blob cmpr; |
| 159 | int rid; |
| 160 | |
| 161 | hname_hash(pContent, 0, &hash); |
| 162 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &hash); |
| 163 | if( rid==0 ){ |
| 164 | static Stmt ins; |
| 165 | db_static_prepare(&ins, |
| 166 | "INSERT INTO blob(uuid, size, content) VALUES(:uuid, :size, :content)" |
| @@ -1652,11 +1652,11 @@ | |
| 1652 | */ |
| 1653 | const char *zIgnTree; |
| 1654 | unsigned nIgnTree = 0; |
| 1655 | while( (zIgnTree = find_option("ignore-tree", 0, 1)) ){ |
| 1656 | if ( *zIgnTree ){ |
| 1657 | gsvn.azIgnTree = fossil_realloc((void *)gsvn.azIgnTree, |
| 1658 | sizeof(*gsvn.azIgnTree) * (nIgnTree + 2)); |
| 1659 | gsvn.azIgnTree[nIgnTree++] = zIgnTree; |
| 1660 | gsvn.azIgnTree[nIgnTree] = 0; |
| 1661 | } |
| 1662 | } |
| 1663 |
+7
-5
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -68,11 +68,11 @@ | ||
| 68 | 68 | zDate = db_text(0, |
| 69 | 69 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 70 | 70 | rid |
| 71 | 71 | ); |
| 72 | 72 | /* 01234567890123 */ |
| 73 | - fossil_print("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : ""); | |
| 73 | + fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : ""); | |
| 74 | 74 | free(zDate); |
| 75 | 75 | if( showComment ){ |
| 76 | 76 | zComment = db_text(0, |
| 77 | 77 | "SELECT coalesce(ecomment,comment) || " |
| 78 | 78 | " ' (user: ' || coalesce(euser,user,'?') || ')' " |
| @@ -91,11 +91,11 @@ | ||
| 91 | 91 | const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:"; |
| 92 | 92 | zDate = db_text("", |
| 93 | 93 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 94 | 94 | db_column_int(&q, 1) |
| 95 | 95 | ); |
| 96 | - fossil_print("%-13s %s %s\n", zType, zUuid, zDate); | |
| 96 | + fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate); | |
| 97 | 97 | free(zDate); |
| 98 | 98 | } |
| 99 | 99 | db_finalize(&q); |
| 100 | 100 | db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid " |
| 101 | 101 | " WHERE pid=%d" |
| @@ -105,11 +105,11 @@ | ||
| 105 | 105 | const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:"; |
| 106 | 106 | zDate = db_text("", |
| 107 | 107 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 108 | 108 | db_column_int(&q, 1) |
| 109 | 109 | ); |
| 110 | - fossil_print("%-13s %s %s\n", zType, zUuid, zDate); | |
| 110 | + fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate); | |
| 111 | 111 | free(zDate); |
| 112 | 112 | } |
| 113 | 113 | db_finalize(&q); |
| 114 | 114 | } |
| 115 | 115 | zTags = info_tags_of_checkin(rid, 0); |
| @@ -572,10 +572,11 @@ | ||
| 572 | 572 | rid, rid |
| 573 | 573 | ); |
| 574 | 574 | sideBySide = !is_false(PD("sbs","1")); |
| 575 | 575 | if( db_step(&q1)==SQLITE_ROW ){ |
| 576 | 576 | const char *zUuid = db_column_text(&q1, 0); |
| 577 | + int nUuid = db_column_bytes(&q1, 0); | |
| 577 | 578 | char *zEUser, *zEComment; |
| 578 | 579 | const char *zUser; |
| 579 | 580 | const char *zComment; |
| 580 | 581 | const char *zDate; |
| 581 | 582 | const char *zOrigDate; |
| @@ -593,11 +594,11 @@ | ||
| 593 | 594 | zComment = db_column_text(&q1, 3); |
| 594 | 595 | zDate = db_column_text(&q1,1); |
| 595 | 596 | zOrigDate = db_column_text(&q1, 4); |
| 596 | 597 | @ <div class="section">Overview</div> |
| 597 | 598 | @ <table class="label-value"> |
| 598 | - @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) | |
| 599 | + @ <tr><th>%s(hname_alg(nUuid)):</th><td>%s(zUuid) | |
| 599 | 600 | if( g.perm.Setup ){ |
| 600 | 601 | @ (Record ID: %d(rid)) |
| 601 | 602 | } |
| 602 | 603 | @ </td></tr> |
| 603 | 604 | @ <tr><th>Date:</th><td> |
| @@ -1385,10 +1386,11 @@ | ||
| 1385 | 1386 | " ORDER BY mtime DESC /*sort*/", |
| 1386 | 1387 | rid |
| 1387 | 1388 | ); |
| 1388 | 1389 | while( db_step(&q)==SQLITE_ROW ){ |
| 1389 | 1390 | const char *zTarget = db_column_text(&q, 0); |
| 1391 | + int nTarget = db_column_bytes(&q, 0); | |
| 1390 | 1392 | const char *zFilename = db_column_text(&q, 1); |
| 1391 | 1393 | const char *zDate = db_column_text(&q, 2); |
| 1392 | 1394 | const char *zUser = db_column_text(&q, 3); |
| 1393 | 1395 | /* const char *zSrc = db_column_text(&q, 4); */ |
| 1394 | 1396 | if( cnt>0 ){ |
| @@ -1395,11 +1397,11 @@ | ||
| 1395 | 1397 | @ Also attachment "%h(zFilename)" to |
| 1396 | 1398 | }else{ |
| 1397 | 1399 | @ Attachment "%h(zFilename)" to |
| 1398 | 1400 | } |
| 1399 | 1401 | objType |= OBJTYPE_ATTACHMENT; |
| 1400 | - if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ | |
| 1402 | + if( nTarget==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ | |
| 1401 | 1403 | if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", |
| 1402 | 1404 | zTarget) |
| 1403 | 1405 | ){ |
| 1404 | 1406 | if( g.perm.Hyperlink && g.anon.RdTkt ){ |
| 1405 | 1407 | @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>] |
| 1406 | 1408 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -68,11 +68,11 @@ | |
| 68 | zDate = db_text(0, |
| 69 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 70 | rid |
| 71 | ); |
| 72 | /* 01234567890123 */ |
| 73 | fossil_print("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : ""); |
| 74 | free(zDate); |
| 75 | if( showComment ){ |
| 76 | zComment = db_text(0, |
| 77 | "SELECT coalesce(ecomment,comment) || " |
| 78 | " ' (user: ' || coalesce(euser,user,'?') || ')' " |
| @@ -91,11 +91,11 @@ | |
| 91 | const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:"; |
| 92 | zDate = db_text("", |
| 93 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 94 | db_column_int(&q, 1) |
| 95 | ); |
| 96 | fossil_print("%-13s %s %s\n", zType, zUuid, zDate); |
| 97 | free(zDate); |
| 98 | } |
| 99 | db_finalize(&q); |
| 100 | db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid " |
| 101 | " WHERE pid=%d" |
| @@ -105,11 +105,11 @@ | |
| 105 | const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:"; |
| 106 | zDate = db_text("", |
| 107 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 108 | db_column_int(&q, 1) |
| 109 | ); |
| 110 | fossil_print("%-13s %s %s\n", zType, zUuid, zDate); |
| 111 | free(zDate); |
| 112 | } |
| 113 | db_finalize(&q); |
| 114 | } |
| 115 | zTags = info_tags_of_checkin(rid, 0); |
| @@ -572,10 +572,11 @@ | |
| 572 | rid, rid |
| 573 | ); |
| 574 | sideBySide = !is_false(PD("sbs","1")); |
| 575 | if( db_step(&q1)==SQLITE_ROW ){ |
| 576 | const char *zUuid = db_column_text(&q1, 0); |
| 577 | char *zEUser, *zEComment; |
| 578 | const char *zUser; |
| 579 | const char *zComment; |
| 580 | const char *zDate; |
| 581 | const char *zOrigDate; |
| @@ -593,11 +594,11 @@ | |
| 593 | zComment = db_column_text(&q1, 3); |
| 594 | zDate = db_column_text(&q1,1); |
| 595 | zOrigDate = db_column_text(&q1, 4); |
| 596 | @ <div class="section">Overview</div> |
| 597 | @ <table class="label-value"> |
| 598 | @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) |
| 599 | if( g.perm.Setup ){ |
| 600 | @ (Record ID: %d(rid)) |
| 601 | } |
| 602 | @ </td></tr> |
| 603 | @ <tr><th>Date:</th><td> |
| @@ -1385,10 +1386,11 @@ | |
| 1385 | " ORDER BY mtime DESC /*sort*/", |
| 1386 | rid |
| 1387 | ); |
| 1388 | while( db_step(&q)==SQLITE_ROW ){ |
| 1389 | const char *zTarget = db_column_text(&q, 0); |
| 1390 | const char *zFilename = db_column_text(&q, 1); |
| 1391 | const char *zDate = db_column_text(&q, 2); |
| 1392 | const char *zUser = db_column_text(&q, 3); |
| 1393 | /* const char *zSrc = db_column_text(&q, 4); */ |
| 1394 | if( cnt>0 ){ |
| @@ -1395,11 +1397,11 @@ | |
| 1395 | @ Also attachment "%h(zFilename)" to |
| 1396 | }else{ |
| 1397 | @ Attachment "%h(zFilename)" to |
| 1398 | } |
| 1399 | objType |= OBJTYPE_ATTACHMENT; |
| 1400 | if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 1401 | if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", |
| 1402 | zTarget) |
| 1403 | ){ |
| 1404 | if( g.perm.Hyperlink && g.anon.RdTkt ){ |
| 1405 | @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>] |
| 1406 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -68,11 +68,11 @@ | |
| 68 | zDate = db_text(0, |
| 69 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 70 | rid |
| 71 | ); |
| 72 | /* 01234567890123 */ |
| 73 | fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : ""); |
| 74 | free(zDate); |
| 75 | if( showComment ){ |
| 76 | zComment = db_text(0, |
| 77 | "SELECT coalesce(ecomment,comment) || " |
| 78 | " ' (user: ' || coalesce(euser,user,'?') || ')' " |
| @@ -91,11 +91,11 @@ | |
| 91 | const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:"; |
| 92 | zDate = db_text("", |
| 93 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 94 | db_column_int(&q, 1) |
| 95 | ); |
| 96 | fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate); |
| 97 | free(zDate); |
| 98 | } |
| 99 | db_finalize(&q); |
| 100 | db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid " |
| 101 | " WHERE pid=%d" |
| @@ -105,11 +105,11 @@ | |
| 105 | const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:"; |
| 106 | zDate = db_text("", |
| 107 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 108 | db_column_int(&q, 1) |
| 109 | ); |
| 110 | fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate); |
| 111 | free(zDate); |
| 112 | } |
| 113 | db_finalize(&q); |
| 114 | } |
| 115 | zTags = info_tags_of_checkin(rid, 0); |
| @@ -572,10 +572,11 @@ | |
| 572 | rid, rid |
| 573 | ); |
| 574 | sideBySide = !is_false(PD("sbs","1")); |
| 575 | if( db_step(&q1)==SQLITE_ROW ){ |
| 576 | const char *zUuid = db_column_text(&q1, 0); |
| 577 | int nUuid = db_column_bytes(&q1, 0); |
| 578 | char *zEUser, *zEComment; |
| 579 | const char *zUser; |
| 580 | const char *zComment; |
| 581 | const char *zDate; |
| 582 | const char *zOrigDate; |
| @@ -593,11 +594,11 @@ | |
| 594 | zComment = db_column_text(&q1, 3); |
| 595 | zDate = db_column_text(&q1,1); |
| 596 | zOrigDate = db_column_text(&q1, 4); |
| 597 | @ <div class="section">Overview</div> |
| 598 | @ <table class="label-value"> |
| 599 | @ <tr><th>%s(hname_alg(nUuid)):</th><td>%s(zUuid) |
| 600 | if( g.perm.Setup ){ |
| 601 | @ (Record ID: %d(rid)) |
| 602 | } |
| 603 | @ </td></tr> |
| 604 | @ <tr><th>Date:</th><td> |
| @@ -1385,10 +1386,11 @@ | |
| 1386 | " ORDER BY mtime DESC /*sort*/", |
| 1387 | rid |
| 1388 | ); |
| 1389 | while( db_step(&q)==SQLITE_ROW ){ |
| 1390 | const char *zTarget = db_column_text(&q, 0); |
| 1391 | int nTarget = db_column_bytes(&q, 0); |
| 1392 | const char *zFilename = db_column_text(&q, 1); |
| 1393 | const char *zDate = db_column_text(&q, 2); |
| 1394 | const char *zUser = db_column_text(&q, 3); |
| 1395 | /* const char *zSrc = db_column_text(&q, 4); */ |
| 1396 | if( cnt>0 ){ |
| @@ -1395,11 +1397,11 @@ | |
| 1397 | @ Also attachment "%h(zFilename)" to |
| 1398 | }else{ |
| 1399 | @ Attachment "%h(zFilename)" to |
| 1400 | } |
| 1401 | objType |= OBJTYPE_ATTACHMENT; |
| 1402 | if( nTarget==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 1403 | if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", |
| 1404 | zTarget) |
| 1405 | ){ |
| 1406 | if( g.perm.Hyperlink && g.anon.RdTkt ){ |
| 1407 | @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>] |
| 1408 |
+97
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -49,10 +49,48 @@ | ||
| 49 | 49 | # define sleep Sleep /* windows does not have sleep, but Sleep */ |
| 50 | 50 | # endif |
| 51 | 51 | #endif |
| 52 | 52 | #include <time.h> |
| 53 | 53 | |
| 54 | +#if defined(__MINGW32__) || defined(_MSC_VER) | |
| 55 | +/* | |
| 56 | +** MinGW doesn't have strtok_r in its libc. Here's a public domain one | |
| 57 | +** found at StackOverflow as a work-around, with formatting adjusted to | |
| 58 | +** make it more like the usual style here. This is certainly the wrong | |
| 59 | +** place for it, which is emphasized by making the function static. | |
| 60 | +** | |
| 61 | +** See http://stackoverflow.com/a/12979321/68204 | |
| 62 | +** | |
| 63 | +** public domain strtok_r() by Charlie Gordon | |
| 64 | +** from comp.lang.c 9/14/2007 | |
| 65 | +** http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684 | |
| 66 | +** (Declaration that it's public domain): | |
| 67 | +** http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c | |
| 68 | +*/ | |
| 69 | +static char* strtok_r( | |
| 70 | + char *str, | |
| 71 | + const char *delim, | |
| 72 | + char **nextp | |
| 73 | +){ | |
| 74 | + char *ret; | |
| 75 | + if( str == NULL ){ | |
| 76 | + str = *nextp; | |
| 77 | + } | |
| 78 | + str += strspn(str, delim); | |
| 79 | + if( *str == '\0' ){ | |
| 80 | + return NULL; | |
| 81 | + } | |
| 82 | + ret = str; | |
| 83 | + str += strcspn(str, delim); | |
| 84 | + if( *str ){ | |
| 85 | + *str++ = '\0'; | |
| 86 | + } | |
| 87 | + *nextp = str; | |
| 88 | + return ret; | |
| 89 | +} | |
| 90 | +#endif | |
| 91 | + | |
| 54 | 92 | /* |
| 55 | 93 | ** Return the login-group name. Or return 0 if this repository is |
| 56 | 94 | ** not a member of a login-group. |
| 57 | 95 | */ |
| 58 | 96 | const char *login_group_name(void){ |
| @@ -966,10 +1004,69 @@ | ||
| 966 | 1004 | if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){ |
| 967 | 1005 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q" |
| 968 | 1006 | " AND length(cap)>0 AND length(pw)>0", zRemoteUser); |
| 969 | 1007 | } |
| 970 | 1008 | } |
| 1009 | + | |
| 1010 | + /* If the request didn't provide a login cookie or the login cookie didn't | |
| 1011 | + ** match a known valid user, check the HTTP "Authorization" header and | |
| 1012 | + ** see if those credentials are valid for a known user. | |
| 1013 | + */ | |
| 1014 | + if( uid==0 ){ | |
| 1015 | + const char *zHTTPAuth = PD("HTTP_AUTHORIZATION", 0); | |
| 1016 | + | |
| 1017 | + /* Check to see if the HTTP "Authorization" header is present | |
| 1018 | + */ | |
| 1019 | + if( zHTTPAuth!=0 && zHTTPAuth[0]!=0 | |
| 1020 | + && db_get_boolean("http_authentication_ok",0) | |
| 1021 | + ){ | |
| 1022 | + char *zBuf = fossil_strdup(zHTTPAuth); | |
| 1023 | + | |
| 1024 | + if( zBuf!=0 ){ | |
| 1025 | + char *zPos; | |
| 1026 | + char *zTok = strtok_r(zBuf, " ", &zPos); | |
| 1027 | + | |
| 1028 | + if( zTok != 0 ){ | |
| 1029 | + /* Check to see if the authorization scheme is HTTP | |
| 1030 | + ** basic auth. | |
| 1031 | + */ | |
| 1032 | + if (strncmp(zTok, "Basic", zTok - zBuf) == 0) { | |
| 1033 | + zTok = strtok_r(NULL, " ", &zPos); | |
| 1034 | + int zBytesDecoded = 0; | |
| 1035 | + char *zDecodedAuth = decode64(zTok, &zBytesDecoded); | |
| 1036 | + | |
| 1037 | + char *zUsername = strtok_r(zDecodedAuth, ":", &zPos); | |
| 1038 | + char *zPasswd = strtok_r(NULL, ":", &zPos); | |
| 1039 | + | |
| 1040 | + if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ | |
| 1041 | + /* Attempting to log in as the user provided by HTTP | |
| 1042 | + ** basic auth | |
| 1043 | + */ | |
| 1044 | + uid = login_search_uid(zUsername, zPasswd); | |
| 1045 | + if( uid>0 ){ | |
| 1046 | + record_login_attempt(zUsername, zIpAddr, 1); | |
| 1047 | + }else{ | |
| 1048 | + record_login_attempt(zUsername, zIpAddr, 0); | |
| 1049 | + | |
| 1050 | + /* The user attempted to login specifically with HTTP basic | |
| 1051 | + ** auth, but provided invalid credentials. Inform them of | |
| 1052 | + ** the failed login attempt via 401. | |
| 1053 | + */ | |
| 1054 | + cgi_set_status(401, "Unauthorized"); | |
| 1055 | + cgi_reply(); | |
| 1056 | + fossil_exit(0); | |
| 1057 | + } | |
| 1058 | + } | |
| 1059 | + | |
| 1060 | + fossil_free(zDecodedAuth); | |
| 1061 | + } | |
| 1062 | + } | |
| 1063 | + | |
| 1064 | + fossil_free(zBuf); | |
| 1065 | + } | |
| 1066 | + } | |
| 1067 | + } | |
| 971 | 1068 | |
| 972 | 1069 | /* If no user found yet, try to log in as "nobody" */ |
| 973 | 1070 | if( uid==0 ){ |
| 974 | 1071 | uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| 975 | 1072 | if( uid==0 ){ |
| 976 | 1073 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -49,10 +49,48 @@ | |
| 49 | # define sleep Sleep /* windows does not have sleep, but Sleep */ |
| 50 | # endif |
| 51 | #endif |
| 52 | #include <time.h> |
| 53 | |
| 54 | /* |
| 55 | ** Return the login-group name. Or return 0 if this repository is |
| 56 | ** not a member of a login-group. |
| 57 | */ |
| 58 | const char *login_group_name(void){ |
| @@ -966,10 +1004,69 @@ | |
| 966 | if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){ |
| 967 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q" |
| 968 | " AND length(cap)>0 AND length(pw)>0", zRemoteUser); |
| 969 | } |
| 970 | } |
| 971 | |
| 972 | /* If no user found yet, try to log in as "nobody" */ |
| 973 | if( uid==0 ){ |
| 974 | uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| 975 | if( uid==0 ){ |
| 976 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -49,10 +49,48 @@ | |
| 49 | # define sleep Sleep /* windows does not have sleep, but Sleep */ |
| 50 | # endif |
| 51 | #endif |
| 52 | #include <time.h> |
| 53 | |
| 54 | #if defined(__MINGW32__) || defined(_MSC_VER) |
| 55 | /* |
| 56 | ** MinGW doesn't have strtok_r in its libc. Here's a public domain one |
| 57 | ** found at StackOverflow as a work-around, with formatting adjusted to |
| 58 | ** make it more like the usual style here. This is certainly the wrong |
| 59 | ** place for it, which is emphasized by making the function static. |
| 60 | ** |
| 61 | ** See http://stackoverflow.com/a/12979321/68204 |
| 62 | ** |
| 63 | ** public domain strtok_r() by Charlie Gordon |
| 64 | ** from comp.lang.c 9/14/2007 |
| 65 | ** http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684 |
| 66 | ** (Declaration that it's public domain): |
| 67 | ** http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c |
| 68 | */ |
| 69 | static char* strtok_r( |
| 70 | char *str, |
| 71 | const char *delim, |
| 72 | char **nextp |
| 73 | ){ |
| 74 | char *ret; |
| 75 | if( str == NULL ){ |
| 76 | str = *nextp; |
| 77 | } |
| 78 | str += strspn(str, delim); |
| 79 | if( *str == '\0' ){ |
| 80 | return NULL; |
| 81 | } |
| 82 | ret = str; |
| 83 | str += strcspn(str, delim); |
| 84 | if( *str ){ |
| 85 | *str++ = '\0'; |
| 86 | } |
| 87 | *nextp = str; |
| 88 | return ret; |
| 89 | } |
| 90 | #endif |
| 91 | |
| 92 | /* |
| 93 | ** Return the login-group name. Or return 0 if this repository is |
| 94 | ** not a member of a login-group. |
| 95 | */ |
| 96 | const char *login_group_name(void){ |
| @@ -966,10 +1004,69 @@ | |
| 1004 | if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){ |
| 1005 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q" |
| 1006 | " AND length(cap)>0 AND length(pw)>0", zRemoteUser); |
| 1007 | } |
| 1008 | } |
| 1009 | |
| 1010 | /* If the request didn't provide a login cookie or the login cookie didn't |
| 1011 | ** match a known valid user, check the HTTP "Authorization" header and |
| 1012 | ** see if those credentials are valid for a known user. |
| 1013 | */ |
| 1014 | if( uid==0 ){ |
| 1015 | const char *zHTTPAuth = PD("HTTP_AUTHORIZATION", 0); |
| 1016 | |
| 1017 | /* Check to see if the HTTP "Authorization" header is present |
| 1018 | */ |
| 1019 | if( zHTTPAuth!=0 && zHTTPAuth[0]!=0 |
| 1020 | && db_get_boolean("http_authentication_ok",0) |
| 1021 | ){ |
| 1022 | char *zBuf = fossil_strdup(zHTTPAuth); |
| 1023 | |
| 1024 | if( zBuf!=0 ){ |
| 1025 | char *zPos; |
| 1026 | char *zTok = strtok_r(zBuf, " ", &zPos); |
| 1027 | |
| 1028 | if( zTok != 0 ){ |
| 1029 | /* Check to see if the authorization scheme is HTTP |
| 1030 | ** basic auth. |
| 1031 | */ |
| 1032 | if (strncmp(zTok, "Basic", zTok - zBuf) == 0) { |
| 1033 | zTok = strtok_r(NULL, " ", &zPos); |
| 1034 | int zBytesDecoded = 0; |
| 1035 | char *zDecodedAuth = decode64(zTok, &zBytesDecoded); |
| 1036 | |
| 1037 | char *zUsername = strtok_r(zDecodedAuth, ":", &zPos); |
| 1038 | char *zPasswd = strtok_r(NULL, ":", &zPos); |
| 1039 | |
| 1040 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 1041 | /* Attempting to log in as the user provided by HTTP |
| 1042 | ** basic auth |
| 1043 | */ |
| 1044 | uid = login_search_uid(zUsername, zPasswd); |
| 1045 | if( uid>0 ){ |
| 1046 | record_login_attempt(zUsername, zIpAddr, 1); |
| 1047 | }else{ |
| 1048 | record_login_attempt(zUsername, zIpAddr, 0); |
| 1049 | |
| 1050 | /* The user attempted to login specifically with HTTP basic |
| 1051 | ** auth, but provided invalid credentials. Inform them of |
| 1052 | ** the failed login attempt via 401. |
| 1053 | */ |
| 1054 | cgi_set_status(401, "Unauthorized"); |
| 1055 | cgi_reply(); |
| 1056 | fossil_exit(0); |
| 1057 | } |
| 1058 | } |
| 1059 | |
| 1060 | fossil_free(zDecodedAuth); |
| 1061 | } |
| 1062 | } |
| 1063 | |
| 1064 | fossil_free(zBuf); |
| 1065 | } |
| 1066 | } |
| 1067 | } |
| 1068 | |
| 1069 | /* If no user found yet, try to log in as "nobody" */ |
| 1070 | if( uid==0 ){ |
| 1071 | uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| 1072 | if( uid==0 ){ |
| 1073 |
+13
-2
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -50,11 +50,16 @@ | ||
| 50 | 50 | # include "cson_amalgamation.h" /* JSON API. */ |
| 51 | 51 | # include "json_detail.h" |
| 52 | 52 | #endif |
| 53 | 53 | |
| 54 | 54 | /* |
| 55 | -** Size of a UUID in characters | |
| 55 | +** Size of a UUID in characters. A UUID is a randomly generated | |
| 56 | +** lower-case hexadecimal number used to identify tickets. | |
| 57 | +** | |
| 58 | +** In Fossil 1.x, UUID also referred to a SHA1 artifact hash. But that | |
| 59 | +** usage is now obsolete. The term UUID should now mean only a very large | |
| 60 | +** random number used as a unique identifier for tickets or other objects. | |
| 56 | 61 | */ |
| 57 | 62 | #define UUID_SIZE 40 |
| 58 | 63 | |
| 59 | 64 | /* |
| 60 | 65 | ** Maximum number of auxiliary parameters on reports |
| @@ -135,10 +140,11 @@ | ||
| 135 | 140 | char *zLocalDbName; /* Name of the local database file */ |
| 136 | 141 | char *zOpenRevision; /* Check-in version to use during database open */ |
| 137 | 142 | int localOpen; /* True if the local database is open */ |
| 138 | 143 | char *zLocalRoot; /* The directory holding the local database */ |
| 139 | 144 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 145 | + int eHashPolicy; /* Current hash policy. One of HPOLICY_* */ | |
| 140 | 146 | int fNoDirSymlinks; /* True if --no-dir-symlinks flag is present */ |
| 141 | 147 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| 142 | 148 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| 143 | 149 | int fSqlPrint; /* True if -sqlprint flag is present */ |
| 144 | 150 | int fQuiet; /* True if -quiet flag is present */ |
| @@ -930,10 +936,13 @@ | ||
| 930 | 936 | #if defined(FOSSIL_ENABLE_MINIZ) |
| 931 | 937 | blob_appendf(pOut, "miniz %s, loaded %s\n", MZ_VERSION, mz_version()); |
| 932 | 938 | #else |
| 933 | 939 | blob_appendf(pOut, "zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion()); |
| 934 | 940 | #endif |
| 941 | +#if FOSSIL_HARDENED_SHA1 | |
| 942 | + blob_appendf(pOut, "hardened-SHA1 by Marc Stevens and Dan Shumow\n"); | |
| 943 | +#endif | |
| 935 | 944 | #if defined(FOSSIL_ENABLE_SSL) |
| 936 | 945 | blob_appendf(pOut, "SSL (%s)\n", SSLeay_version(SSLEAY_VERSION)); |
| 937 | 946 | #endif |
| 938 | 947 | #if defined(FOSSIL_HAVE_FUSEFS) |
| 939 | 948 | blob_appendf(pOut, "libfuse %s, loaded %s\n", fusefs_inc_version(), |
| @@ -1997,11 +2006,11 @@ | ||
| 1997 | 2006 | ** the name of that directory and the specific repository will be |
| 1998 | 2007 | ** opened later by process_one_web_page() based on the content of |
| 1999 | 2008 | ** the PATH_INFO variable. |
| 2000 | 2009 | ** |
| 2001 | 2010 | ** If the fCreate flag is set, then create the repository if it |
| 2002 | -** does not already exist. | |
| 2011 | +** does not already exist. Always use "auto" hash-policy in this case. | |
| 2003 | 2012 | */ |
| 2004 | 2013 | static void find_server_repository(int arg, int fCreate){ |
| 2005 | 2014 | if( g.argc<=arg ){ |
| 2006 | 2015 | db_must_be_within_tree(); |
| 2007 | 2016 | }else{ |
| @@ -2014,10 +2023,12 @@ | ||
| 2014 | 2023 | if( isDir==0 && fCreate ){ |
| 2015 | 2024 | const char *zPassword; |
| 2016 | 2025 | db_create_repository(zRepo); |
| 2017 | 2026 | db_open_repository(zRepo); |
| 2018 | 2027 | db_begin_transaction(); |
| 2028 | + g.eHashPolicy = HPOLICY_AUTO; | |
| 2029 | + db_set_int("hash-policy", HPOLICY_AUTO, 0); | |
| 2019 | 2030 | db_initial_setup(0, "now", g.zLogin); |
| 2020 | 2031 | db_end_transaction(0); |
| 2021 | 2032 | fossil_print("project-id: %s\n", db_get("project-code", 0)); |
| 2022 | 2033 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 2023 | 2034 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 2024 | 2035 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -50,11 +50,16 @@ | |
| 50 | # include "cson_amalgamation.h" /* JSON API. */ |
| 51 | # include "json_detail.h" |
| 52 | #endif |
| 53 | |
| 54 | /* |
| 55 | ** Size of a UUID in characters |
| 56 | */ |
| 57 | #define UUID_SIZE 40 |
| 58 | |
| 59 | /* |
| 60 | ** Maximum number of auxiliary parameters on reports |
| @@ -135,10 +140,11 @@ | |
| 135 | char *zLocalDbName; /* Name of the local database file */ |
| 136 | char *zOpenRevision; /* Check-in version to use during database open */ |
| 137 | int localOpen; /* True if the local database is open */ |
| 138 | char *zLocalRoot; /* The directory holding the local database */ |
| 139 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 140 | int fNoDirSymlinks; /* True if --no-dir-symlinks flag is present */ |
| 141 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| 142 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| 143 | int fSqlPrint; /* True if -sqlprint flag is present */ |
| 144 | int fQuiet; /* True if -quiet flag is present */ |
| @@ -930,10 +936,13 @@ | |
| 930 | #if defined(FOSSIL_ENABLE_MINIZ) |
| 931 | blob_appendf(pOut, "miniz %s, loaded %s\n", MZ_VERSION, mz_version()); |
| 932 | #else |
| 933 | blob_appendf(pOut, "zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion()); |
| 934 | #endif |
| 935 | #if defined(FOSSIL_ENABLE_SSL) |
| 936 | blob_appendf(pOut, "SSL (%s)\n", SSLeay_version(SSLEAY_VERSION)); |
| 937 | #endif |
| 938 | #if defined(FOSSIL_HAVE_FUSEFS) |
| 939 | blob_appendf(pOut, "libfuse %s, loaded %s\n", fusefs_inc_version(), |
| @@ -1997,11 +2006,11 @@ | |
| 1997 | ** the name of that directory and the specific repository will be |
| 1998 | ** opened later by process_one_web_page() based on the content of |
| 1999 | ** the PATH_INFO variable. |
| 2000 | ** |
| 2001 | ** If the fCreate flag is set, then create the repository if it |
| 2002 | ** does not already exist. |
| 2003 | */ |
| 2004 | static void find_server_repository(int arg, int fCreate){ |
| 2005 | if( g.argc<=arg ){ |
| 2006 | db_must_be_within_tree(); |
| 2007 | }else{ |
| @@ -2014,10 +2023,12 @@ | |
| 2014 | if( isDir==0 && fCreate ){ |
| 2015 | const char *zPassword; |
| 2016 | db_create_repository(zRepo); |
| 2017 | db_open_repository(zRepo); |
| 2018 | db_begin_transaction(); |
| 2019 | db_initial_setup(0, "now", g.zLogin); |
| 2020 | db_end_transaction(0); |
| 2021 | fossil_print("project-id: %s\n", db_get("project-code", 0)); |
| 2022 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 2023 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 2024 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -50,11 +50,16 @@ | |
| 50 | # include "cson_amalgamation.h" /* JSON API. */ |
| 51 | # include "json_detail.h" |
| 52 | #endif |
| 53 | |
| 54 | /* |
| 55 | ** Size of a UUID in characters. A UUID is a randomly generated |
| 56 | ** lower-case hexadecimal number used to identify tickets. |
| 57 | ** |
| 58 | ** In Fossil 1.x, UUID also referred to a SHA1 artifact hash. But that |
| 59 | ** usage is now obsolete. The term UUID should now mean only a very large |
| 60 | ** random number used as a unique identifier for tickets or other objects. |
| 61 | */ |
| 62 | #define UUID_SIZE 40 |
| 63 | |
| 64 | /* |
| 65 | ** Maximum number of auxiliary parameters on reports |
| @@ -135,10 +140,11 @@ | |
| 140 | char *zLocalDbName; /* Name of the local database file */ |
| 141 | char *zOpenRevision; /* Check-in version to use during database open */ |
| 142 | int localOpen; /* True if the local database is open */ |
| 143 | char *zLocalRoot; /* The directory holding the local database */ |
| 144 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 145 | int eHashPolicy; /* Current hash policy. One of HPOLICY_* */ |
| 146 | int fNoDirSymlinks; /* True if --no-dir-symlinks flag is present */ |
| 147 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| 148 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| 149 | int fSqlPrint; /* True if -sqlprint flag is present */ |
| 150 | int fQuiet; /* True if -quiet flag is present */ |
| @@ -930,10 +936,13 @@ | |
| 936 | #if defined(FOSSIL_ENABLE_MINIZ) |
| 937 | blob_appendf(pOut, "miniz %s, loaded %s\n", MZ_VERSION, mz_version()); |
| 938 | #else |
| 939 | blob_appendf(pOut, "zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion()); |
| 940 | #endif |
| 941 | #if FOSSIL_HARDENED_SHA1 |
| 942 | blob_appendf(pOut, "hardened-SHA1 by Marc Stevens and Dan Shumow\n"); |
| 943 | #endif |
| 944 | #if defined(FOSSIL_ENABLE_SSL) |
| 945 | blob_appendf(pOut, "SSL (%s)\n", SSLeay_version(SSLEAY_VERSION)); |
| 946 | #endif |
| 947 | #if defined(FOSSIL_HAVE_FUSEFS) |
| 948 | blob_appendf(pOut, "libfuse %s, loaded %s\n", fusefs_inc_version(), |
| @@ -1997,11 +2006,11 @@ | |
| 2006 | ** the name of that directory and the specific repository will be |
| 2007 | ** opened later by process_one_web_page() based on the content of |
| 2008 | ** the PATH_INFO variable. |
| 2009 | ** |
| 2010 | ** If the fCreate flag is set, then create the repository if it |
| 2011 | ** does not already exist. Always use "auto" hash-policy in this case. |
| 2012 | */ |
| 2013 | static void find_server_repository(int arg, int fCreate){ |
| 2014 | if( g.argc<=arg ){ |
| 2015 | db_must_be_within_tree(); |
| 2016 | }else{ |
| @@ -2014,10 +2023,12 @@ | |
| 2023 | if( isDir==0 && fCreate ){ |
| 2024 | const char *zPassword; |
| 2025 | db_create_repository(zRepo); |
| 2026 | db_open_repository(zRepo); |
| 2027 | db_begin_transaction(); |
| 2028 | g.eHashPolicy = HPOLICY_AUTO; |
| 2029 | db_set_int("hash-policy", HPOLICY_AUTO, 0); |
| 2030 | db_initial_setup(0, "now", g.zLogin); |
| 2031 | db_end_transaction(0); |
| 2032 | fossil_print("project-id: %s\n", db_get("project-code", 0)); |
| 2033 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 2034 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 2035 |
+36
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -52,10 +52,11 @@ | ||
| 52 | 52 | $(SRCDIR)/fshell.c \ |
| 53 | 53 | $(SRCDIR)/fusefs.c \ |
| 54 | 54 | $(SRCDIR)/glob.c \ |
| 55 | 55 | $(SRCDIR)/graph.c \ |
| 56 | 56 | $(SRCDIR)/gzip.c \ |
| 57 | + $(SRCDIR)/hname.c \ | |
| 57 | 58 | $(SRCDIR)/http.c \ |
| 58 | 59 | $(SRCDIR)/http_socket.c \ |
| 59 | 60 | $(SRCDIR)/http_ssl.c \ |
| 60 | 61 | $(SRCDIR)/http_transport.c \ |
| 61 | 62 | $(SRCDIR)/import.c \ |
| @@ -102,10 +103,12 @@ | ||
| 102 | 103 | $(SRCDIR)/rss.c \ |
| 103 | 104 | $(SRCDIR)/schema.c \ |
| 104 | 105 | $(SRCDIR)/search.c \ |
| 105 | 106 | $(SRCDIR)/setup.c \ |
| 106 | 107 | $(SRCDIR)/sha1.c \ |
| 108 | + $(SRCDIR)/sha1hard.c \ | |
| 109 | + $(SRCDIR)/sha3.c \ | |
| 107 | 110 | $(SRCDIR)/shun.c \ |
| 108 | 111 | $(SRCDIR)/sitemap.c \ |
| 109 | 112 | $(SRCDIR)/skins.c \ |
| 110 | 113 | $(SRCDIR)/sqlcmd.c \ |
| 111 | 114 | $(SRCDIR)/stash.c \ |
| @@ -227,10 +230,11 @@ | ||
| 227 | 230 | $(OBJDIR)/fshell_.c \ |
| 228 | 231 | $(OBJDIR)/fusefs_.c \ |
| 229 | 232 | $(OBJDIR)/glob_.c \ |
| 230 | 233 | $(OBJDIR)/graph_.c \ |
| 231 | 234 | $(OBJDIR)/gzip_.c \ |
| 235 | + $(OBJDIR)/hname_.c \ | |
| 232 | 236 | $(OBJDIR)/http_.c \ |
| 233 | 237 | $(OBJDIR)/http_socket_.c \ |
| 234 | 238 | $(OBJDIR)/http_ssl_.c \ |
| 235 | 239 | $(OBJDIR)/http_transport_.c \ |
| 236 | 240 | $(OBJDIR)/import_.c \ |
| @@ -277,10 +281,12 @@ | ||
| 277 | 281 | $(OBJDIR)/rss_.c \ |
| 278 | 282 | $(OBJDIR)/schema_.c \ |
| 279 | 283 | $(OBJDIR)/search_.c \ |
| 280 | 284 | $(OBJDIR)/setup_.c \ |
| 281 | 285 | $(OBJDIR)/sha1_.c \ |
| 286 | + $(OBJDIR)/sha1hard_.c \ | |
| 287 | + $(OBJDIR)/sha3_.c \ | |
| 282 | 288 | $(OBJDIR)/shun_.c \ |
| 283 | 289 | $(OBJDIR)/sitemap_.c \ |
| 284 | 290 | $(OBJDIR)/skins_.c \ |
| 285 | 291 | $(OBJDIR)/sqlcmd_.c \ |
| 286 | 292 | $(OBJDIR)/stash_.c \ |
| @@ -351,10 +357,11 @@ | ||
| 351 | 357 | $(OBJDIR)/fshell.o \ |
| 352 | 358 | $(OBJDIR)/fusefs.o \ |
| 353 | 359 | $(OBJDIR)/glob.o \ |
| 354 | 360 | $(OBJDIR)/graph.o \ |
| 355 | 361 | $(OBJDIR)/gzip.o \ |
| 362 | + $(OBJDIR)/hname.o \ | |
| 356 | 363 | $(OBJDIR)/http.o \ |
| 357 | 364 | $(OBJDIR)/http_socket.o \ |
| 358 | 365 | $(OBJDIR)/http_ssl.o \ |
| 359 | 366 | $(OBJDIR)/http_transport.o \ |
| 360 | 367 | $(OBJDIR)/import.o \ |
| @@ -401,10 +408,12 @@ | ||
| 401 | 408 | $(OBJDIR)/rss.o \ |
| 402 | 409 | $(OBJDIR)/schema.o \ |
| 403 | 410 | $(OBJDIR)/search.o \ |
| 404 | 411 | $(OBJDIR)/setup.o \ |
| 405 | 412 | $(OBJDIR)/sha1.o \ |
| 413 | + $(OBJDIR)/sha1hard.o \ | |
| 414 | + $(OBJDIR)/sha3.o \ | |
| 406 | 415 | $(OBJDIR)/shun.o \ |
| 407 | 416 | $(OBJDIR)/sitemap.o \ |
| 408 | 417 | $(OBJDIR)/skins.o \ |
| 409 | 418 | $(OBJDIR)/sqlcmd.o \ |
| 410 | 419 | $(OBJDIR)/stash.o \ |
| @@ -636,10 +645,11 @@ | ||
| 636 | 645 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 637 | 646 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 638 | 647 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 639 | 648 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 640 | 649 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 650 | + $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ | |
| 641 | 651 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 642 | 652 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 643 | 653 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 644 | 654 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 645 | 655 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -686,10 +696,12 @@ | ||
| 686 | 696 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 687 | 697 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 688 | 698 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 689 | 699 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 690 | 700 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 701 | + $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ | |
| 702 | + $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ | |
| 691 | 703 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 692 | 704 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 693 | 705 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 694 | 706 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 695 | 707 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1037,10 +1049,18 @@ | ||
| 1037 | 1049 | |
| 1038 | 1050 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1039 | 1051 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1040 | 1052 | |
| 1041 | 1053 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1054 | + | |
| 1055 | +$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(OBJDIR)/translate | |
| 1056 | + $(OBJDIR)/translate $(SRCDIR)/hname.c >$@ | |
| 1057 | + | |
| 1058 | +$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h | |
| 1059 | + $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c | |
| 1060 | + | |
| 1061 | +$(OBJDIR)/hname.h: $(OBJDIR)/headers | |
| 1042 | 1062 | |
| 1043 | 1063 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(OBJDIR)/translate |
| 1044 | 1064 | $(OBJDIR)/translate $(SRCDIR)/http.c >$@ |
| 1045 | 1065 | |
| 1046 | 1066 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1437,10 +1457,26 @@ | ||
| 1437 | 1457 | |
| 1438 | 1458 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1439 | 1459 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1440 | 1460 | |
| 1441 | 1461 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1462 | + | |
| 1463 | +$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(OBJDIR)/translate | |
| 1464 | + $(OBJDIR)/translate $(SRCDIR)/sha1hard.c >$@ | |
| 1465 | + | |
| 1466 | +$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h | |
| 1467 | + $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c | |
| 1468 | + | |
| 1469 | +$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers | |
| 1470 | + | |
| 1471 | +$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(OBJDIR)/translate | |
| 1472 | + $(OBJDIR)/translate $(SRCDIR)/sha3.c >$@ | |
| 1473 | + | |
| 1474 | +$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h | |
| 1475 | + $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c | |
| 1476 | + | |
| 1477 | +$(OBJDIR)/sha3.h: $(OBJDIR)/headers | |
| 1442 | 1478 | |
| 1443 | 1479 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(OBJDIR)/translate |
| 1444 | 1480 | $(OBJDIR)/translate $(SRCDIR)/shun.c >$@ |
| 1445 | 1481 | |
| 1446 | 1482 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1447 | 1483 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -52,10 +52,11 @@ | |
| 52 | $(SRCDIR)/fshell.c \ |
| 53 | $(SRCDIR)/fusefs.c \ |
| 54 | $(SRCDIR)/glob.c \ |
| 55 | $(SRCDIR)/graph.c \ |
| 56 | $(SRCDIR)/gzip.c \ |
| 57 | $(SRCDIR)/http.c \ |
| 58 | $(SRCDIR)/http_socket.c \ |
| 59 | $(SRCDIR)/http_ssl.c \ |
| 60 | $(SRCDIR)/http_transport.c \ |
| 61 | $(SRCDIR)/import.c \ |
| @@ -102,10 +103,12 @@ | |
| 102 | $(SRCDIR)/rss.c \ |
| 103 | $(SRCDIR)/schema.c \ |
| 104 | $(SRCDIR)/search.c \ |
| 105 | $(SRCDIR)/setup.c \ |
| 106 | $(SRCDIR)/sha1.c \ |
| 107 | $(SRCDIR)/shun.c \ |
| 108 | $(SRCDIR)/sitemap.c \ |
| 109 | $(SRCDIR)/skins.c \ |
| 110 | $(SRCDIR)/sqlcmd.c \ |
| 111 | $(SRCDIR)/stash.c \ |
| @@ -227,10 +230,11 @@ | |
| 227 | $(OBJDIR)/fshell_.c \ |
| 228 | $(OBJDIR)/fusefs_.c \ |
| 229 | $(OBJDIR)/glob_.c \ |
| 230 | $(OBJDIR)/graph_.c \ |
| 231 | $(OBJDIR)/gzip_.c \ |
| 232 | $(OBJDIR)/http_.c \ |
| 233 | $(OBJDIR)/http_socket_.c \ |
| 234 | $(OBJDIR)/http_ssl_.c \ |
| 235 | $(OBJDIR)/http_transport_.c \ |
| 236 | $(OBJDIR)/import_.c \ |
| @@ -277,10 +281,12 @@ | |
| 277 | $(OBJDIR)/rss_.c \ |
| 278 | $(OBJDIR)/schema_.c \ |
| 279 | $(OBJDIR)/search_.c \ |
| 280 | $(OBJDIR)/setup_.c \ |
| 281 | $(OBJDIR)/sha1_.c \ |
| 282 | $(OBJDIR)/shun_.c \ |
| 283 | $(OBJDIR)/sitemap_.c \ |
| 284 | $(OBJDIR)/skins_.c \ |
| 285 | $(OBJDIR)/sqlcmd_.c \ |
| 286 | $(OBJDIR)/stash_.c \ |
| @@ -351,10 +357,11 @@ | |
| 351 | $(OBJDIR)/fshell.o \ |
| 352 | $(OBJDIR)/fusefs.o \ |
| 353 | $(OBJDIR)/glob.o \ |
| 354 | $(OBJDIR)/graph.o \ |
| 355 | $(OBJDIR)/gzip.o \ |
| 356 | $(OBJDIR)/http.o \ |
| 357 | $(OBJDIR)/http_socket.o \ |
| 358 | $(OBJDIR)/http_ssl.o \ |
| 359 | $(OBJDIR)/http_transport.o \ |
| 360 | $(OBJDIR)/import.o \ |
| @@ -401,10 +408,12 @@ | |
| 401 | $(OBJDIR)/rss.o \ |
| 402 | $(OBJDIR)/schema.o \ |
| 403 | $(OBJDIR)/search.o \ |
| 404 | $(OBJDIR)/setup.o \ |
| 405 | $(OBJDIR)/sha1.o \ |
| 406 | $(OBJDIR)/shun.o \ |
| 407 | $(OBJDIR)/sitemap.o \ |
| 408 | $(OBJDIR)/skins.o \ |
| 409 | $(OBJDIR)/sqlcmd.o \ |
| 410 | $(OBJDIR)/stash.o \ |
| @@ -636,10 +645,11 @@ | |
| 636 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 637 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 638 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 639 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 640 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 641 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 642 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 643 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 644 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 645 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -686,10 +696,12 @@ | |
| 686 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 687 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 688 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 689 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 690 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 691 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 692 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 693 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 694 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 695 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1037,10 +1049,18 @@ | |
| 1037 | |
| 1038 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1039 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1040 | |
| 1041 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1042 | |
| 1043 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(OBJDIR)/translate |
| 1044 | $(OBJDIR)/translate $(SRCDIR)/http.c >$@ |
| 1045 | |
| 1046 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1437,10 +1457,26 @@ | |
| 1437 | |
| 1438 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1439 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1440 | |
| 1441 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1442 | |
| 1443 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(OBJDIR)/translate |
| 1444 | $(OBJDIR)/translate $(SRCDIR)/shun.c >$@ |
| 1445 | |
| 1446 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1447 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -52,10 +52,11 @@ | |
| 52 | $(SRCDIR)/fshell.c \ |
| 53 | $(SRCDIR)/fusefs.c \ |
| 54 | $(SRCDIR)/glob.c \ |
| 55 | $(SRCDIR)/graph.c \ |
| 56 | $(SRCDIR)/gzip.c \ |
| 57 | $(SRCDIR)/hname.c \ |
| 58 | $(SRCDIR)/http.c \ |
| 59 | $(SRCDIR)/http_socket.c \ |
| 60 | $(SRCDIR)/http_ssl.c \ |
| 61 | $(SRCDIR)/http_transport.c \ |
| 62 | $(SRCDIR)/import.c \ |
| @@ -102,10 +103,12 @@ | |
| 103 | $(SRCDIR)/rss.c \ |
| 104 | $(SRCDIR)/schema.c \ |
| 105 | $(SRCDIR)/search.c \ |
| 106 | $(SRCDIR)/setup.c \ |
| 107 | $(SRCDIR)/sha1.c \ |
| 108 | $(SRCDIR)/sha1hard.c \ |
| 109 | $(SRCDIR)/sha3.c \ |
| 110 | $(SRCDIR)/shun.c \ |
| 111 | $(SRCDIR)/sitemap.c \ |
| 112 | $(SRCDIR)/skins.c \ |
| 113 | $(SRCDIR)/sqlcmd.c \ |
| 114 | $(SRCDIR)/stash.c \ |
| @@ -227,10 +230,11 @@ | |
| 230 | $(OBJDIR)/fshell_.c \ |
| 231 | $(OBJDIR)/fusefs_.c \ |
| 232 | $(OBJDIR)/glob_.c \ |
| 233 | $(OBJDIR)/graph_.c \ |
| 234 | $(OBJDIR)/gzip_.c \ |
| 235 | $(OBJDIR)/hname_.c \ |
| 236 | $(OBJDIR)/http_.c \ |
| 237 | $(OBJDIR)/http_socket_.c \ |
| 238 | $(OBJDIR)/http_ssl_.c \ |
| 239 | $(OBJDIR)/http_transport_.c \ |
| 240 | $(OBJDIR)/import_.c \ |
| @@ -277,10 +281,12 @@ | |
| 281 | $(OBJDIR)/rss_.c \ |
| 282 | $(OBJDIR)/schema_.c \ |
| 283 | $(OBJDIR)/search_.c \ |
| 284 | $(OBJDIR)/setup_.c \ |
| 285 | $(OBJDIR)/sha1_.c \ |
| 286 | $(OBJDIR)/sha1hard_.c \ |
| 287 | $(OBJDIR)/sha3_.c \ |
| 288 | $(OBJDIR)/shun_.c \ |
| 289 | $(OBJDIR)/sitemap_.c \ |
| 290 | $(OBJDIR)/skins_.c \ |
| 291 | $(OBJDIR)/sqlcmd_.c \ |
| 292 | $(OBJDIR)/stash_.c \ |
| @@ -351,10 +357,11 @@ | |
| 357 | $(OBJDIR)/fshell.o \ |
| 358 | $(OBJDIR)/fusefs.o \ |
| 359 | $(OBJDIR)/glob.o \ |
| 360 | $(OBJDIR)/graph.o \ |
| 361 | $(OBJDIR)/gzip.o \ |
| 362 | $(OBJDIR)/hname.o \ |
| 363 | $(OBJDIR)/http.o \ |
| 364 | $(OBJDIR)/http_socket.o \ |
| 365 | $(OBJDIR)/http_ssl.o \ |
| 366 | $(OBJDIR)/http_transport.o \ |
| 367 | $(OBJDIR)/import.o \ |
| @@ -401,10 +408,12 @@ | |
| 408 | $(OBJDIR)/rss.o \ |
| 409 | $(OBJDIR)/schema.o \ |
| 410 | $(OBJDIR)/search.o \ |
| 411 | $(OBJDIR)/setup.o \ |
| 412 | $(OBJDIR)/sha1.o \ |
| 413 | $(OBJDIR)/sha1hard.o \ |
| 414 | $(OBJDIR)/sha3.o \ |
| 415 | $(OBJDIR)/shun.o \ |
| 416 | $(OBJDIR)/sitemap.o \ |
| 417 | $(OBJDIR)/skins.o \ |
| 418 | $(OBJDIR)/sqlcmd.o \ |
| 419 | $(OBJDIR)/stash.o \ |
| @@ -636,10 +645,11 @@ | |
| 645 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 646 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 647 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 648 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 649 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 650 | $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ |
| 651 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 652 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 653 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 654 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 655 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -686,10 +696,12 @@ | |
| 696 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 697 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 698 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 699 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 700 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 701 | $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ |
| 702 | $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ |
| 703 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 704 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 705 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 706 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 707 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1037,10 +1049,18 @@ | |
| 1049 | |
| 1050 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1051 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1052 | |
| 1053 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1054 | |
| 1055 | $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(OBJDIR)/translate |
| 1056 | $(OBJDIR)/translate $(SRCDIR)/hname.c >$@ |
| 1057 | |
| 1058 | $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h |
| 1059 | $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c |
| 1060 | |
| 1061 | $(OBJDIR)/hname.h: $(OBJDIR)/headers |
| 1062 | |
| 1063 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(OBJDIR)/translate |
| 1064 | $(OBJDIR)/translate $(SRCDIR)/http.c >$@ |
| 1065 | |
| 1066 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1437,10 +1457,26 @@ | |
| 1457 | |
| 1458 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1459 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1460 | |
| 1461 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1462 | |
| 1463 | $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(OBJDIR)/translate |
| 1464 | $(OBJDIR)/translate $(SRCDIR)/sha1hard.c >$@ |
| 1465 | |
| 1466 | $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h |
| 1467 | $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c |
| 1468 | |
| 1469 | $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers |
| 1470 | |
| 1471 | $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(OBJDIR)/translate |
| 1472 | $(OBJDIR)/translate $(SRCDIR)/sha3.c >$@ |
| 1473 | |
| 1474 | $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h |
| 1475 | $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c |
| 1476 | |
| 1477 | $(OBJDIR)/sha3.h: $(OBJDIR)/headers |
| 1478 | |
| 1479 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(OBJDIR)/translate |
| 1480 | $(OBJDIR)/translate $(SRCDIR)/shun.c >$@ |
| 1481 | |
| 1482 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1483 |
+6
-1
| --- src/makeheaders.c | ||
| +++ src/makeheaders.c | ||
| @@ -1017,11 +1017,14 @@ | ||
| 1017 | 1017 | /* printf("%04d: Type=%d nIf=%d [%.*s]\n", |
| 1018 | 1018 | pToken->nLine,pToken->eType,nIf,pToken->nText, |
| 1019 | 1019 | pToken->eType!=TT_Space ? pToken->zText : "<space>"); */ |
| 1020 | 1020 | pToken->pComment = blockComment; |
| 1021 | 1021 | switch( pToken->eType ){ |
| 1022 | - case TT_Comment: | |
| 1022 | + case TT_Comment: /*0123456789 12345678 */ | |
| 1023 | + if( strncmp(pToken->zText, "/*MAKEHEADERS-STOP", 18)==0 ) return nErr; | |
| 1024 | + break; | |
| 1025 | + | |
| 1023 | 1026 | case TT_Space: |
| 1024 | 1027 | break; |
| 1025 | 1028 | |
| 1026 | 1029 | case TT_BlockComment: |
| 1027 | 1030 | if( doc_flag ){ |
| @@ -2181,10 +2184,12 @@ | ||
| 2181 | 2184 | if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){ |
| 2182 | 2185 | PushIfMacro(0,0,0,pToken->nLine,PS_Interface); |
| 2183 | 2186 | }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){ |
| 2184 | 2187 | PushIfMacro(0,0,0,pToken->nLine,PS_Export); |
| 2185 | 2188 | }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){ |
| 2189 | + PushIfMacro(0,0,0,pToken->nLine,PS_Local); | |
| 2190 | + }else if( nArg==15 && strncmp(zArg,"MAKEHEADERS_STOPLOCAL_INTERFACE",15)==0 ){ | |
| 2186 | 2191 | PushIfMacro(0,0,0,pToken->nLine,PS_Local); |
| 2187 | 2192 | }else{ |
| 2188 | 2193 | PushIfMacro(0,zArg,nArg,pToken->nLine,0); |
| 2189 | 2194 | } |
| 2190 | 2195 | }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ |
| 2191 | 2196 |
| --- src/makeheaders.c | |
| +++ src/makeheaders.c | |
| @@ -1017,11 +1017,14 @@ | |
| 1017 | /* printf("%04d: Type=%d nIf=%d [%.*s]\n", |
| 1018 | pToken->nLine,pToken->eType,nIf,pToken->nText, |
| 1019 | pToken->eType!=TT_Space ? pToken->zText : "<space>"); */ |
| 1020 | pToken->pComment = blockComment; |
| 1021 | switch( pToken->eType ){ |
| 1022 | case TT_Comment: |
| 1023 | case TT_Space: |
| 1024 | break; |
| 1025 | |
| 1026 | case TT_BlockComment: |
| 1027 | if( doc_flag ){ |
| @@ -2181,10 +2184,12 @@ | |
| 2181 | if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){ |
| 2182 | PushIfMacro(0,0,0,pToken->nLine,PS_Interface); |
| 2183 | }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){ |
| 2184 | PushIfMacro(0,0,0,pToken->nLine,PS_Export); |
| 2185 | }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){ |
| 2186 | PushIfMacro(0,0,0,pToken->nLine,PS_Local); |
| 2187 | }else{ |
| 2188 | PushIfMacro(0,zArg,nArg,pToken->nLine,0); |
| 2189 | } |
| 2190 | }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ |
| 2191 |
| --- src/makeheaders.c | |
| +++ src/makeheaders.c | |
| @@ -1017,11 +1017,14 @@ | |
| 1017 | /* printf("%04d: Type=%d nIf=%d [%.*s]\n", |
| 1018 | pToken->nLine,pToken->eType,nIf,pToken->nText, |
| 1019 | pToken->eType!=TT_Space ? pToken->zText : "<space>"); */ |
| 1020 | pToken->pComment = blockComment; |
| 1021 | switch( pToken->eType ){ |
| 1022 | case TT_Comment: /*0123456789 12345678 */ |
| 1023 | if( strncmp(pToken->zText, "/*MAKEHEADERS-STOP", 18)==0 ) return nErr; |
| 1024 | break; |
| 1025 | |
| 1026 | case TT_Space: |
| 1027 | break; |
| 1028 | |
| 1029 | case TT_BlockComment: |
| 1030 | if( doc_flag ){ |
| @@ -2181,10 +2184,12 @@ | |
| 2184 | if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){ |
| 2185 | PushIfMacro(0,0,0,pToken->nLine,PS_Interface); |
| 2186 | }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){ |
| 2187 | PushIfMacro(0,0,0,pToken->nLine,PS_Export); |
| 2188 | }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){ |
| 2189 | PushIfMacro(0,0,0,pToken->nLine,PS_Local); |
| 2190 | }else if( nArg==15 && strncmp(zArg,"MAKEHEADERS_STOPLOCAL_INTERFACE",15)==0 ){ |
| 2191 | PushIfMacro(0,0,0,pToken->nLine,PS_Local); |
| 2192 | }else{ |
| 2193 | PushIfMacro(0,zArg,nArg,pToken->nLine,0); |
| 2194 | } |
| 2195 | }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ |
| 2196 |
+3
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -58,10 +58,11 @@ | ||
| 58 | 58 | fshell |
| 59 | 59 | fusefs |
| 60 | 60 | glob |
| 61 | 61 | graph |
| 62 | 62 | gzip |
| 63 | + hname | |
| 63 | 64 | http |
| 64 | 65 | http_socket |
| 65 | 66 | http_transport |
| 66 | 67 | import |
| 67 | 68 | info |
| @@ -107,10 +108,12 @@ | ||
| 107 | 108 | rss |
| 108 | 109 | schema |
| 109 | 110 | search |
| 110 | 111 | setup |
| 111 | 112 | sha1 |
| 113 | + sha1hard | |
| 114 | + sha3 | |
| 112 | 115 | shun |
| 113 | 116 | sitemap |
| 114 | 117 | skins |
| 115 | 118 | sqlcmd |
| 116 | 119 | stash |
| 117 | 120 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -58,10 +58,11 @@ | |
| 58 | fshell |
| 59 | fusefs |
| 60 | glob |
| 61 | graph |
| 62 | gzip |
| 63 | http |
| 64 | http_socket |
| 65 | http_transport |
| 66 | import |
| 67 | info |
| @@ -107,10 +108,12 @@ | |
| 107 | rss |
| 108 | schema |
| 109 | search |
| 110 | setup |
| 111 | sha1 |
| 112 | shun |
| 113 | sitemap |
| 114 | skins |
| 115 | sqlcmd |
| 116 | stash |
| 117 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -58,10 +58,11 @@ | |
| 58 | fshell |
| 59 | fusefs |
| 60 | glob |
| 61 | graph |
| 62 | gzip |
| 63 | hname |
| 64 | http |
| 65 | http_socket |
| 66 | http_transport |
| 67 | import |
| 68 | info |
| @@ -107,10 +108,12 @@ | |
| 108 | rss |
| 109 | schema |
| 110 | search |
| 111 | setup |
| 112 | sha1 |
| 113 | sha1hard |
| 114 | sha3 |
| 115 | shun |
| 116 | sitemap |
| 117 | skins |
| 118 | sqlcmd |
| 119 | stash |
| 120 |
+3
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -58,10 +58,11 @@ | ||
| 58 | 58 | fshell |
| 59 | 59 | fusefs |
| 60 | 60 | glob |
| 61 | 61 | graph |
| 62 | 62 | gzip |
| 63 | + hname | |
| 63 | 64 | http |
| 64 | 65 | http_socket |
| 65 | 66 | http_transport |
| 66 | 67 | import |
| 67 | 68 | info |
| @@ -107,10 +108,12 @@ | ||
| 107 | 108 | rss |
| 108 | 109 | schema |
| 109 | 110 | search |
| 110 | 111 | setup |
| 111 | 112 | sha1 |
| 113 | + sha1hard | |
| 114 | + sha3 | |
| 112 | 115 | shun |
| 113 | 116 | sitemap |
| 114 | 117 | skins |
| 115 | 118 | sqlcmd |
| 116 | 119 | stash |
| 117 | 120 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -58,10 +58,11 @@ | |
| 58 | fshell |
| 59 | fusefs |
| 60 | glob |
| 61 | graph |
| 62 | gzip |
| 63 | http |
| 64 | http_socket |
| 65 | http_transport |
| 66 | import |
| 67 | info |
| @@ -107,10 +108,12 @@ | |
| 107 | rss |
| 108 | schema |
| 109 | search |
| 110 | setup |
| 111 | sha1 |
| 112 | shun |
| 113 | sitemap |
| 114 | skins |
| 115 | sqlcmd |
| 116 | stash |
| 117 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -58,10 +58,11 @@ | |
| 58 | fshell |
| 59 | fusefs |
| 60 | glob |
| 61 | graph |
| 62 | gzip |
| 63 | hname |
| 64 | http |
| 65 | http_socket |
| 66 | http_transport |
| 67 | import |
| 68 | info |
| @@ -107,10 +108,12 @@ | |
| 108 | rss |
| 109 | schema |
| 110 | search |
| 111 | setup |
| 112 | sha1 |
| 113 | sha1hard |
| 114 | sha3 |
| 115 | shun |
| 116 | sitemap |
| 117 | skins |
| 118 | sqlcmd |
| 119 | stash |
| 120 |
+80
-80
| --- src/manifest.c | ||
| +++ src/manifest.c | ||
| @@ -54,11 +54,11 @@ | ||
| 54 | 54 | /* |
| 55 | 55 | ** A single F-card within a manifest |
| 56 | 56 | */ |
| 57 | 57 | struct ManifestFile { |
| 58 | 58 | char *zName; /* Name of a file */ |
| 59 | - char *zUuid; /* UUID of the file */ | |
| 59 | + char *zUuid; /* Artifact hash for the file */ | |
| 60 | 60 | char *zPerm; /* File permissions */ |
| 61 | 61 | char *zPrior; /* Prior name if the name was changed */ |
| 62 | 62 | }; |
| 63 | 63 | |
| 64 | 64 | |
| @@ -77,35 +77,35 @@ | ||
| 77 | 77 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 78 | 78 | char *zWiki; /* Text of the wiki page. W card. */ |
| 79 | 79 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 80 | 80 | char *zMimetype; /* Mime type of wiki or comment text. N card. */ |
| 81 | 81 | double rEventDate; /* Date of an event. E card. */ |
| 82 | - char *zEventId; /* UUID for an event. E card. */ | |
| 82 | + char *zEventId; /* Artifact hash for an event. E card. */ | |
| 83 | 83 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 84 | 84 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 85 | - char *zAttachSrc; /* UUID of document being attached. A card. */ | |
| 85 | + char *zAttachSrc; /* Artifact hash for document being attached. A card. */ | |
| 86 | 86 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 87 | 87 | int nFile; /* Number of F cards */ |
| 88 | 88 | int nFileAlloc; /* Slots allocated in aFile[] */ |
| 89 | 89 | int iFile; /* Index of current file in iterator */ |
| 90 | 90 | ManifestFile *aFile; /* One entry for each F-card */ |
| 91 | 91 | int nParent; /* Number of parents. */ |
| 92 | 92 | int nParentAlloc; /* Slots allocated in azParent[] */ |
| 93 | - char **azParent; /* UUIDs of parents. One for each P card argument */ | |
| 93 | + char **azParent; /* Hashes of parents. One for each P card argument */ | |
| 94 | 94 | int nCherrypick; /* Number of entries in aCherrypick[] */ |
| 95 | 95 | struct { |
| 96 | - char *zCPTarget; /* UUID of cherry-picked version w/ +|- prefix */ | |
| 97 | - char *zCPBase; /* UUID of cherry-pick baseline. NULL for singletons */ | |
| 96 | + char *zCPTarget; /* Hash for cherry-picked version w/ +|- prefix */ | |
| 97 | + char *zCPBase; /* Hash for cherry-pick baseline. NULL for singletons */ | |
| 98 | 98 | } *aCherrypick; |
| 99 | 99 | int nCChild; /* Number of cluster children */ |
| 100 | 100 | int nCChildAlloc; /* Number of closts allocated in azCChild[] */ |
| 101 | - char **azCChild; /* UUIDs of referenced objects in a cluster. M cards */ | |
| 101 | + char **azCChild; /* Hashes of referenced objects in a cluster. M cards */ | |
| 102 | 102 | int nTag; /* Number of T Cards */ |
| 103 | 103 | int nTagAlloc; /* Slots allocated in aTag[] */ |
| 104 | 104 | struct TagType { |
| 105 | 105 | char *zName; /* Name of the tag */ |
| 106 | - char *zUuid; /* UUID that the tag is applied to */ | |
| 106 | + char *zUuid; /* Hash of artifact that the tag is applied to */ | |
| 107 | 107 | char *zValue; /* Value if the tag is really a property */ |
| 108 | 108 | } *aTag; /* One for each T card */ |
| 109 | 109 | int nField; /* Number of J cards */ |
| 110 | 110 | int nFieldAlloc; /* Slots allocated in aField[] */ |
| 111 | 111 | struct { |
| @@ -327,26 +327,27 @@ | ||
| 327 | 327 | ** takes over the input blob and will free it when the |
| 328 | 328 | ** Manifest object is freed. Zeros are inserted into the blob |
| 329 | 329 | ** as string terminators so that blob should not be used again. |
| 330 | 330 | ** |
| 331 | 331 | ** Return a pointer to an allocated Manifest object if the content |
| 332 | -** really is a control file of some kind. This object needs to be | |
| 333 | -** freed by a subsequent call to manifest_destroy(). Return NULL | |
| 334 | -** if there are syntax errors. | |
| 332 | +** really is a structural artifact of some kind. The returned Manifest | |
| 333 | +** object needs to be freed by a subsequent call to manifest_destroy(). | |
| 334 | +** Return NULL if there are syntax errors or if the input blob does | |
| 335 | +** not describe a valid structural artifact. | |
| 335 | 336 | ** |
| 336 | -** This routine is strict about the format of a control file. | |
| 337 | +** This routine is strict about the format of a structural artifacts. | |
| 337 | 338 | ** The format must match exactly or else it is rejected. This |
| 338 | -** rule minimizes the risk that a content file will be mistaken | |
| 339 | -** for a control file simply because they look the same. | |
| 339 | +** rule minimizes the risk that a content artifact will be mistaken | |
| 340 | +** for a structural artifact simply because they look the same. | |
| 340 | 341 | ** |
| 341 | 342 | ** The pContent is reset. If a pointer is returned, then pContent will |
| 342 | 343 | ** be reset when the Manifest object is cleared. If NULL is |
| 343 | 344 | ** returned then the Manifest object is cleared automatically |
| 344 | 345 | ** and pContent is reset before the return. |
| 345 | 346 | ** |
| 346 | -** The entire file can be PGP clear-signed. The signature is ignored. | |
| 347 | -** The file consists of zero or more cards, one card per line. | |
| 347 | +** The entire input blob can be PGP clear-signed. The signature is ignored. | |
| 348 | +** The artifact consists of zero or more cards, one card per line. | |
| 348 | 349 | ** (Except: the content of the W card can extend of multiple lines.) |
| 349 | 350 | ** Each card is divided into tokens by a single space character. |
| 350 | 351 | ** The first token is a single upper-case letter which is the card type. |
| 351 | 352 | ** The card type determines the other parameters to the card. |
| 352 | 353 | ** Cards must occur in lexicographical order. |
| @@ -361,11 +362,10 @@ | ||
| 361 | 362 | char *z; |
| 362 | 363 | int n; |
| 363 | 364 | char *zUuid; |
| 364 | 365 | int sz = 0; |
| 365 | 366 | int isRepeat, hasSelfRefTag = 0; |
| 366 | - Blob bUuid = BLOB_INITIALIZER; | |
| 367 | 367 | static Bag seen; |
| 368 | 368 | const char *zErr = 0; |
| 369 | 369 | |
| 370 | 370 | if( rid==0 ){ |
| 371 | 371 | isRepeat = 1; |
| @@ -374,11 +374,11 @@ | ||
| 374 | 374 | }else{ |
| 375 | 375 | isRepeat = 0; |
| 376 | 376 | bag_insert(&seen, rid); |
| 377 | 377 | } |
| 378 | 378 | |
| 379 | - /* Every control artifact ends with a '\n' character. Exit early | |
| 379 | + /* Every structural artifact ends with a '\n' character. Exit early | |
| 380 | 380 | ** if that is not the case for this artifact. |
| 381 | 381 | */ |
| 382 | 382 | if( !isRepeat ) g.parseCnt[0]++; |
| 383 | 383 | z = blob_materialize(pContent); |
| 384 | 384 | n = blob_size(pContent); |
| @@ -406,15 +406,10 @@ | ||
| 406 | 406 | blob_reset(pContent); |
| 407 | 407 | blob_appendf(pErr, "incorrect Z-card cksum"); |
| 408 | 408 | return 0; |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | - /* Store the UUID (before modifying the blob) only for error | |
| 412 | - ** reporting purposes. | |
| 413 | - */ | |
| 414 | - sha1sum_blob(pContent, &bUuid); | |
| 415 | - | |
| 416 | 411 | /* Allocate a Manifest object to hold the parsed control artifact. |
| 417 | 412 | */ |
| 418 | 413 | p = fossil_malloc( sizeof(*p) ); |
| 419 | 414 | memset(p, 0, sizeof(*p)); |
| 420 | 415 | memcpy(&p->content, pContent, sizeof(p->content)); |
| @@ -449,15 +444,15 @@ | ||
| 449 | 444 | defossilize(zName); |
| 450 | 445 | if( !file_is_simple_pathname(zName, 0) ){ |
| 451 | 446 | SYNTAX("invalid filename on A-card"); |
| 452 | 447 | } |
| 453 | 448 | defossilize(zTarget); |
| 454 | - if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) | |
| 449 | + if( !hname_validate(zTarget,nTarget) | |
| 455 | 450 | && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| 456 | 451 | SYNTAX("invalid target on A-card"); |
| 457 | 452 | } |
| 458 | - if( zSrc && (nSrc!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){ | |
| 453 | + if( zSrc && !hname_validate(zSrc,nSrc) ){ | |
| 459 | 454 | SYNTAX("invalid source on A-card"); |
| 460 | 455 | } |
| 461 | 456 | p->zAttachName = (char*)file_tail(zName); |
| 462 | 457 | p->zAttachSrc = zSrc; |
| 463 | 458 | p->zAttachTarget = zTarget; |
| @@ -465,18 +460,18 @@ | ||
| 465 | 460 | } |
| 466 | 461 | |
| 467 | 462 | /* |
| 468 | 463 | ** B <uuid> |
| 469 | 464 | ** |
| 470 | - ** A B-line gives the UUID for the baseline of a delta-manifest. | |
| 465 | + ** A B-line gives the artifact hash for the baseline of a delta-manifest. | |
| 471 | 466 | */ |
| 472 | 467 | case 'B': { |
| 473 | 468 | if( p->zBaseline ) SYNTAX("more than one B-card"); |
| 474 | 469 | p->zBaseline = next_token(&x, &sz); |
| 475 | - if( p->zBaseline==0 ) SYNTAX("missing UUID on B-card"); | |
| 476 | - if( sz!=UUID_SIZE || !validate16(p->zBaseline, UUID_SIZE) ){ | |
| 477 | - SYNTAX("invalid UUID on B-card"); | |
| 470 | + if( p->zBaseline==0 ) SYNTAX("missing hash on B-card"); | |
| 471 | + if( !hname_validate(p->zBaseline,sz) ){ | |
| 472 | + SYNTAX("invalid hash on B-card"); | |
| 478 | 473 | } |
| 479 | 474 | break; |
| 480 | 475 | } |
| 481 | 476 | |
| 482 | 477 | |
| @@ -522,12 +517,12 @@ | ||
| 522 | 517 | case 'E': { |
| 523 | 518 | if( p->rEventDate>0.0 ) SYNTAX("more than one E-card"); |
| 524 | 519 | p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0)); |
| 525 | 520 | if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card"); |
| 526 | 521 | p->zEventId = next_token(&x, &sz); |
| 527 | - if( sz!=UUID_SIZE || !validate16(p->zEventId, UUID_SIZE) ){ | |
| 528 | - SYNTAX("malformed UUID on E-card"); | |
| 522 | + if( !hname_validate(p->zEventId, sz) ){ | |
| 523 | + SYNTAX("malformed hash on E-card"); | |
| 529 | 524 | } |
| 530 | 525 | break; |
| 531 | 526 | } |
| 532 | 527 | |
| 533 | 528 | /* |
| @@ -545,12 +540,13 @@ | ||
| 545 | 540 | if( !file_is_simple_pathname(zName, 0) ){ |
| 546 | 541 | SYNTAX("F-card filename is not a simple path"); |
| 547 | 542 | } |
| 548 | 543 | zUuid = next_token(&x, &sz); |
| 549 | 544 | if( p->zBaseline==0 || zUuid!=0 ){ |
| 550 | - if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size"); | |
| 551 | - if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("F-card UUID invalid"); | |
| 545 | + if( !hname_validate(zUuid,sz) ){ | |
| 546 | + SYNTAX("F-card hash invalid"); | |
| 547 | + } | |
| 552 | 548 | } |
| 553 | 549 | zPerm = next_token(&x,0); |
| 554 | 550 | zPriorName = next_token(&x,0); |
| 555 | 551 | if( zPriorName ){ |
| 556 | 552 | defossilize(zPriorName); |
| @@ -636,20 +632,21 @@ | ||
| 636 | 632 | } |
| 637 | 633 | break; |
| 638 | 634 | } |
| 639 | 635 | |
| 640 | 636 | /* |
| 641 | - ** M <uuid> | |
| 637 | + ** M <hash> | |
| 642 | 638 | ** |
| 643 | - ** An M-line identifies another artifact by its UUID. M-lines | |
| 639 | + ** An M-line identifies another artifact by its hash. M-lines | |
| 644 | 640 | ** occur in clusters only. |
| 645 | 641 | */ |
| 646 | 642 | case 'M': { |
| 647 | 643 | zUuid = next_token(&x, &sz); |
| 648 | - if( zUuid==0 ) SYNTAX("missing UUID on M-card"); | |
| 649 | - if( sz!=UUID_SIZE ) SYNTAX("wrong size for UUID on M-card"); | |
| 650 | - if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("UUID invalid on M-card"); | |
| 644 | + if( zUuid==0 ) SYNTAX("missing hash on M-card"); | |
| 645 | + if( !hname_validate(zUuid,sz) ){ | |
| 646 | + SYNTAX("Invalid hash on M-card"); | |
| 647 | + } | |
| 651 | 648 | if( p->nCChild>=p->nCChildAlloc ){ |
| 652 | 649 | p->nCChildAlloc = p->nCChildAlloc*2 + 10; |
| 653 | 650 | p->azCChild = fossil_realloc(p->azCChild |
| 654 | 651 | , p->nCChildAlloc*sizeof(p->azCChild[0]) ); |
| 655 | 652 | } |
| @@ -683,12 +680,13 @@ | ||
| 683 | 680 | ** check-in historically has an empty P-card, so empty P-cards |
| 684 | 681 | ** must be accepted. |
| 685 | 682 | */ |
| 686 | 683 | case 'P': { |
| 687 | 684 | while( (zUuid = next_token(&x, &sz))!=0 ){ |
| 688 | - if( sz!=UUID_SIZE ) SYNTAX("wrong size UUID on P-card"); | |
| 689 | - if( !validate16(zUuid, UUID_SIZE) )SYNTAX("invalid UUID on P-card"); | |
| 685 | + if( !hname_validate(zUuid, sz) ){ | |
| 686 | + SYNTAX("invalid hash on P-card"); | |
| 687 | + } | |
| 690 | 688 | if( p->nParent>=p->nParentAlloc ){ |
| 691 | 689 | p->nParentAlloc = p->nParentAlloc*2 + 5; |
| 692 | 690 | p->azParent = fossil_realloc(p->azParent, |
| 693 | 691 | p->nParentAlloc*sizeof(char*)); |
| 694 | 692 | } |
| @@ -703,29 +701,25 @@ | ||
| 703 | 701 | ** |
| 704 | 702 | ** Specify one or a range of check-ins that are cherrypicked into |
| 705 | 703 | ** this check-in ("+") or backed out of this check-in ("-"). |
| 706 | 704 | */ |
| 707 | 705 | case 'Q': { |
| 708 | - if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing UUID on Q-card"); | |
| 709 | - if( sz!=UUID_SIZE+1 ) SYNTAX("wrong size UUID on Q-card"); | |
| 706 | + if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing hash on Q-card"); | |
| 710 | 707 | if( zUuid[0]!='+' && zUuid[0]!='-' ){ |
| 711 | 708 | SYNTAX("Q-card does not begin with '+' or '-'"); |
| 712 | 709 | } |
| 713 | - if( !validate16(&zUuid[1], UUID_SIZE) ){ | |
| 714 | - SYNTAX("invalid UUID on Q-card"); | |
| 710 | + if( !hname_validate(&zUuid[1], sz-1) ){ | |
| 711 | + SYNTAX("invalid hash on Q-card"); | |
| 715 | 712 | } |
| 716 | 713 | n = p->nCherrypick; |
| 717 | 714 | p->nCherrypick++; |
| 718 | 715 | p->aCherrypick = fossil_realloc(p->aCherrypick, |
| 719 | 716 | p->nCherrypick*sizeof(p->aCherrypick[0])); |
| 720 | 717 | p->aCherrypick[n].zCPTarget = zUuid; |
| 721 | 718 | p->aCherrypick[n].zCPBase = zUuid = next_token(&x, &sz); |
| 722 | - if( zUuid ){ | |
| 723 | - if( sz!=UUID_SIZE ) SYNTAX("wrong size second UUID in Q-card"); | |
| 724 | - if( !validate16(zUuid, UUID_SIZE) ){ | |
| 725 | - SYNTAX("invalid second UUID on Q-card"); | |
| 726 | - } | |
| 719 | + if( zUuid && !hname_validate(zUuid,sz) ){ | |
| 720 | + SYNTAX("invalid second hash on Q-card"); | |
| 727 | 721 | } |
| 728 | 722 | break; |
| 729 | 723 | } |
| 730 | 724 | |
| 731 | 725 | /* |
| @@ -760,32 +754,32 @@ | ||
| 760 | 754 | case 'T': { |
| 761 | 755 | char *zName, *zValue; |
| 762 | 756 | zName = next_token(&x, 0); |
| 763 | 757 | if( zName==0 ) SYNTAX("missing name on T-card"); |
| 764 | 758 | zUuid = next_token(&x, &sz); |
| 765 | - if( zUuid==0 ) SYNTAX("missing UUID on T-card"); | |
| 759 | + if( zUuid==0 ) SYNTAX("missing artifact hash on T-card"); | |
| 766 | 760 | zValue = next_token(&x, 0); |
| 767 | 761 | if( zValue ) defossilize(zValue); |
| 768 | - if( sz==UUID_SIZE && validate16(zUuid, UUID_SIZE) ){ | |
| 769 | - /* A valid uuid */ | |
| 762 | + if( hname_validate(zUuid, sz) ){ | |
| 763 | + /* A valid artifact hash */ | |
| 770 | 764 | if( p->zEventId ) SYNTAX("non-self-referential T-card in event"); |
| 771 | 765 | }else if( sz==1 && zUuid[0]=='*' ){ |
| 772 | 766 | zUuid = 0; |
| 773 | 767 | hasSelfRefTag = 1; |
| 774 | 768 | if( p->zEventId && zName[0]!='+' ){ |
| 775 | 769 | SYNTAX("propagating T-card in event"); |
| 776 | 770 | } |
| 777 | 771 | }else{ |
| 778 | - SYNTAX("malformed UUID on T-card"); | |
| 772 | + SYNTAX("malformed artifact hash on T-card"); | |
| 779 | 773 | } |
| 780 | 774 | defossilize(zName); |
| 781 | 775 | if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){ |
| 782 | 776 | SYNTAX("T-card name does not begin with '-', '+', or '*'"); |
| 783 | 777 | } |
| 784 | 778 | if( validate16(&zName[1], strlen(&zName[1])) ){ |
| 785 | - /* Do not allow tags whose names look like UUIDs */ | |
| 786 | - SYNTAX("T-card name looks like a UUID"); | |
| 779 | + /* Do not allow tags whose names look like a hash */ | |
| 780 | + SYNTAX("T-card name looks like a hexadecimal hash"); | |
| 787 | 781 | } |
| 788 | 782 | if( p->nTag>=p->nTagAlloc ){ |
| 789 | 783 | p->nTagAlloc = p->nTagAlloc*2 + 10; |
| 790 | 784 | p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) ); |
| 791 | 785 | } |
| @@ -951,17 +945,19 @@ | ||
| 951 | 945 | if( !seenZ ) SYNTAX("missing Z-card on control"); |
| 952 | 946 | p->type = CFTYPE_CONTROL; |
| 953 | 947 | } |
| 954 | 948 | md5sum_init(); |
| 955 | 949 | if( !isRepeat ) g.parseCnt[p->type]++; |
| 956 | - blob_reset(&bUuid); | |
| 957 | 950 | return p; |
| 958 | 951 | |
| 959 | 952 | manifest_syntax_error: |
| 960 | - if(bUuid.nUsed){ | |
| 961 | - blob_appendf(pErr, "manifest [%.40s] ", blob_str(&bUuid)); | |
| 962 | - blob_reset(&bUuid); | |
| 953 | + { | |
| 954 | + char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); | |
| 955 | + if( zUuid ){ | |
| 956 | + blob_appendf(pErr, "manifest [%s] ", zUuid); | |
| 957 | + fossil_free(zUuid); | |
| 958 | + } | |
| 963 | 959 | } |
| 964 | 960 | if( zErr ){ |
| 965 | 961 | blob_appendf(pErr, "line %d: %s", lineNo, zErr); |
| 966 | 962 | }else{ |
| 967 | 963 | blob_appendf(pErr, "unknown error on line %d", lineNo); |
| @@ -1193,13 +1189,13 @@ | ||
| 1193 | 1189 | ** then the mlink entry is only created if there is already an mlink |
| 1194 | 1190 | ** from primary parent for the same file. |
| 1195 | 1191 | */ |
| 1196 | 1192 | static void add_one_mlink( |
| 1197 | 1193 | int pmid, /* The parent manifest */ |
| 1198 | - const char *zFromUuid, /* UUID for content in parent */ | |
| 1194 | + const char *zFromUuid, /* Artifact hash for content in parent */ | |
| 1199 | 1195 | int mid, /* The record ID of the manifest */ |
| 1200 | - const char *zToUuid, /* UUID for content in child */ | |
| 1196 | + const char *zToUuid, /* artifact hash for content in child */ | |
| 1201 | 1197 | const char *zFilename, /* Filename */ |
| 1202 | 1198 | const char *zPrior, /* Previous filename. NULL if unchanged */ |
| 1203 | 1199 | int isPublic, /* True if mid is not a private manifest */ |
| 1204 | 1200 | int isPrimary, /* pmid is the primary parent of mid */ |
| 1205 | 1201 | int mperm /* 1: exec, 2: symlink */ |
| @@ -1545,22 +1541,22 @@ | ||
| 1545 | 1541 | } |
| 1546 | 1542 | } |
| 1547 | 1543 | |
| 1548 | 1544 | /* |
| 1549 | 1545 | ** For a check-in with RID "rid" that has nParent parent check-ins given |
| 1550 | -** by the UUIDs in azParent[], create all appropriate plink and mlink table | |
| 1546 | +** by the hashes in azParent[], create all appropriate plink and mlink table | |
| 1551 | 1547 | ** entries. |
| 1552 | 1548 | ** |
| 1553 | -** The primary parent is the first UUID on the azParent[] list. | |
| 1549 | +** The primary parent is the first hash on the azParent[] list. | |
| 1554 | 1550 | ** |
| 1555 | 1551 | ** Return the RID of the primary parent. |
| 1556 | 1552 | */ |
| 1557 | 1553 | static int manifest_add_checkin_linkages( |
| 1558 | 1554 | int rid, /* The RID of the check-in */ |
| 1559 | 1555 | Manifest *p, /* Manifest for this check-in */ |
| 1560 | 1556 | int nParent, /* Number of parents for this check-in */ |
| 1561 | - char **azParent /* UUIDs for each parent */ | |
| 1557 | + char **azParent /* hashes for each parent */ | |
| 1562 | 1558 | ){ |
| 1563 | 1559 | int i; |
| 1564 | 1560 | int parentid = 0; |
| 1565 | 1561 | char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */ |
| 1566 | 1562 | Stmt q; |
| @@ -1611,33 +1607,36 @@ | ||
| 1611 | 1607 | return parentid; |
| 1612 | 1608 | } |
| 1613 | 1609 | |
| 1614 | 1610 | /* |
| 1615 | 1611 | ** There exists a "parent" tag against checkin rid that has value zValue. |
| 1616 | -** If value is well-formed (meaning that it is a list of UUIDs), then use | |
| 1612 | +** If value is well-formed (meaning that it is a list of hashes), then use | |
| 1617 | 1613 | ** zValue to reparent check-in rid. |
| 1618 | 1614 | */ |
| 1619 | 1615 | void manifest_reparent_checkin(int rid, const char *zValue){ |
| 1620 | - int nParent; | |
| 1616 | + int nParent = 0; | |
| 1621 | 1617 | char *zCopy = 0; |
| 1622 | 1618 | char **azParent = 0; |
| 1623 | 1619 | Manifest *p = 0; |
| 1624 | - int i; | |
| 1620 | + int i, j; | |
| 1625 | 1621 | int n = (int)strlen(zValue); |
| 1626 | - nParent = (n+1)/(UUID_SIZE+1); | |
| 1627 | - if( nParent*(UUID_SIZE+1) - 1 !=n ) return; | |
| 1628 | - if( nParent<1 ) return; | |
| 1622 | + int mxParent = (n+1)/(HNAME_MIN+1); | |
| 1623 | + | |
| 1624 | + if( mxParent<1 ) return; | |
| 1629 | 1625 | zCopy = fossil_strdup(zValue); |
| 1630 | - azParent = fossil_malloc( sizeof(azParent[0])*nParent ); | |
| 1631 | - for(i=0; i<nParent; i++){ | |
| 1632 | - azParent[i] = &zCopy[i*(UUID_SIZE+1)]; | |
| 1633 | - if( i<nParent-1 && azParent[i][UUID_SIZE]!=' ' ) break; | |
| 1634 | - azParent[i][UUID_SIZE] = 0; | |
| 1635 | - if( !validate16(azParent[i],UUID_SIZE) ) break; | |
| 1636 | - } | |
| 1637 | - if( i==nParent | |
| 1638 | - && !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d", | |
| 1626 | + azParent = fossil_malloc( sizeof(azParent[0])*mxParent ); | |
| 1627 | + for(nParent=0, i=0; zCopy[i]; i++){ | |
| 1628 | + char *z = &zCopy[i]; | |
| 1629 | + azParent[nParent++] = z; | |
| 1630 | + if( nParent>mxParent ) goto reparent_abort; | |
| 1631 | + for(j=HNAME_MIN; z[j]>' '; j++){} | |
| 1632 | + if( !hname_validate(z, j) ) goto reparent_abort; | |
| 1633 | + if( z[j]==0 ) break; | |
| 1634 | + z[j] = 0; | |
| 1635 | + i += j; | |
| 1636 | + } | |
| 1637 | + if( !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d", | |
| 1639 | 1638 | rid, uuid_to_rid(azParent[0],0)) |
| 1640 | 1639 | ){ |
| 1641 | 1640 | p = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 1642 | 1641 | } |
| 1643 | 1642 | if( p!=0 ){ |
| @@ -1647,10 +1646,11 @@ | ||
| 1647 | 1646 | rid, rid |
| 1648 | 1647 | ); |
| 1649 | 1648 | manifest_add_checkin_linkages(rid,p,nParent,azParent); |
| 1650 | 1649 | } |
| 1651 | 1650 | manifest_destroy(p); |
| 1651 | +reparent_abort: | |
| 1652 | 1652 | fossil_free(azParent); |
| 1653 | 1653 | fossil_free(zCopy); |
| 1654 | 1654 | } |
| 1655 | 1655 | |
| 1656 | 1656 | /* |
| @@ -2280,11 +2280,11 @@ | ||
| 2280 | 2280 | int branchMove = 0; |
| 2281 | 2281 | blob_zero(&comment); |
| 2282 | 2282 | if( p->zComment ){ |
| 2283 | 2283 | blob_appendf(&comment, " %s.", p->zComment); |
| 2284 | 2284 | } |
| 2285 | - /* Next loop expects tags to be sorted on UUID, so sort it. */ | |
| 2285 | + /* Next loop expects tags to be sorted on hash, so sort it. */ | |
| 2286 | 2286 | qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare); |
| 2287 | 2287 | for(i=0; i<p->nTag; i++){ |
| 2288 | 2288 | zTagUuid = p->aTag[i].zUuid; |
| 2289 | 2289 | if( !zTagUuid ) continue; |
| 2290 | 2290 | if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){ |
| 2291 | 2291 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -54,11 +54,11 @@ | |
| 54 | /* |
| 55 | ** A single F-card within a manifest |
| 56 | */ |
| 57 | struct ManifestFile { |
| 58 | char *zName; /* Name of a file */ |
| 59 | char *zUuid; /* UUID of the file */ |
| 60 | char *zPerm; /* File permissions */ |
| 61 | char *zPrior; /* Prior name if the name was changed */ |
| 62 | }; |
| 63 | |
| 64 | |
| @@ -77,35 +77,35 @@ | |
| 77 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 78 | char *zWiki; /* Text of the wiki page. W card. */ |
| 79 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 80 | char *zMimetype; /* Mime type of wiki or comment text. N card. */ |
| 81 | double rEventDate; /* Date of an event. E card. */ |
| 82 | char *zEventId; /* UUID for an event. E card. */ |
| 83 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 84 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 85 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 86 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 87 | int nFile; /* Number of F cards */ |
| 88 | int nFileAlloc; /* Slots allocated in aFile[] */ |
| 89 | int iFile; /* Index of current file in iterator */ |
| 90 | ManifestFile *aFile; /* One entry for each F-card */ |
| 91 | int nParent; /* Number of parents. */ |
| 92 | int nParentAlloc; /* Slots allocated in azParent[] */ |
| 93 | char **azParent; /* UUIDs of parents. One for each P card argument */ |
| 94 | int nCherrypick; /* Number of entries in aCherrypick[] */ |
| 95 | struct { |
| 96 | char *zCPTarget; /* UUID of cherry-picked version w/ +|- prefix */ |
| 97 | char *zCPBase; /* UUID of cherry-pick baseline. NULL for singletons */ |
| 98 | } *aCherrypick; |
| 99 | int nCChild; /* Number of cluster children */ |
| 100 | int nCChildAlloc; /* Number of closts allocated in azCChild[] */ |
| 101 | char **azCChild; /* UUIDs of referenced objects in a cluster. M cards */ |
| 102 | int nTag; /* Number of T Cards */ |
| 103 | int nTagAlloc; /* Slots allocated in aTag[] */ |
| 104 | struct TagType { |
| 105 | char *zName; /* Name of the tag */ |
| 106 | char *zUuid; /* UUID that the tag is applied to */ |
| 107 | char *zValue; /* Value if the tag is really a property */ |
| 108 | } *aTag; /* One for each T card */ |
| 109 | int nField; /* Number of J cards */ |
| 110 | int nFieldAlloc; /* Slots allocated in aField[] */ |
| 111 | struct { |
| @@ -327,26 +327,27 @@ | |
| 327 | ** takes over the input blob and will free it when the |
| 328 | ** Manifest object is freed. Zeros are inserted into the blob |
| 329 | ** as string terminators so that blob should not be used again. |
| 330 | ** |
| 331 | ** Return a pointer to an allocated Manifest object if the content |
| 332 | ** really is a control file of some kind. This object needs to be |
| 333 | ** freed by a subsequent call to manifest_destroy(). Return NULL |
| 334 | ** if there are syntax errors. |
| 335 | ** |
| 336 | ** This routine is strict about the format of a control file. |
| 337 | ** The format must match exactly or else it is rejected. This |
| 338 | ** rule minimizes the risk that a content file will be mistaken |
| 339 | ** for a control file simply because they look the same. |
| 340 | ** |
| 341 | ** The pContent is reset. If a pointer is returned, then pContent will |
| 342 | ** be reset when the Manifest object is cleared. If NULL is |
| 343 | ** returned then the Manifest object is cleared automatically |
| 344 | ** and pContent is reset before the return. |
| 345 | ** |
| 346 | ** The entire file can be PGP clear-signed. The signature is ignored. |
| 347 | ** The file consists of zero or more cards, one card per line. |
| 348 | ** (Except: the content of the W card can extend of multiple lines.) |
| 349 | ** Each card is divided into tokens by a single space character. |
| 350 | ** The first token is a single upper-case letter which is the card type. |
| 351 | ** The card type determines the other parameters to the card. |
| 352 | ** Cards must occur in lexicographical order. |
| @@ -361,11 +362,10 @@ | |
| 361 | char *z; |
| 362 | int n; |
| 363 | char *zUuid; |
| 364 | int sz = 0; |
| 365 | int isRepeat, hasSelfRefTag = 0; |
| 366 | Blob bUuid = BLOB_INITIALIZER; |
| 367 | static Bag seen; |
| 368 | const char *zErr = 0; |
| 369 | |
| 370 | if( rid==0 ){ |
| 371 | isRepeat = 1; |
| @@ -374,11 +374,11 @@ | |
| 374 | }else{ |
| 375 | isRepeat = 0; |
| 376 | bag_insert(&seen, rid); |
| 377 | } |
| 378 | |
| 379 | /* Every control artifact ends with a '\n' character. Exit early |
| 380 | ** if that is not the case for this artifact. |
| 381 | */ |
| 382 | if( !isRepeat ) g.parseCnt[0]++; |
| 383 | z = blob_materialize(pContent); |
| 384 | n = blob_size(pContent); |
| @@ -406,15 +406,10 @@ | |
| 406 | blob_reset(pContent); |
| 407 | blob_appendf(pErr, "incorrect Z-card cksum"); |
| 408 | return 0; |
| 409 | } |
| 410 | |
| 411 | /* Store the UUID (before modifying the blob) only for error |
| 412 | ** reporting purposes. |
| 413 | */ |
| 414 | sha1sum_blob(pContent, &bUuid); |
| 415 | |
| 416 | /* Allocate a Manifest object to hold the parsed control artifact. |
| 417 | */ |
| 418 | p = fossil_malloc( sizeof(*p) ); |
| 419 | memset(p, 0, sizeof(*p)); |
| 420 | memcpy(&p->content, pContent, sizeof(p->content)); |
| @@ -449,15 +444,15 @@ | |
| 449 | defossilize(zName); |
| 450 | if( !file_is_simple_pathname(zName, 0) ){ |
| 451 | SYNTAX("invalid filename on A-card"); |
| 452 | } |
| 453 | defossilize(zTarget); |
| 454 | if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) |
| 455 | && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| 456 | SYNTAX("invalid target on A-card"); |
| 457 | } |
| 458 | if( zSrc && (nSrc!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){ |
| 459 | SYNTAX("invalid source on A-card"); |
| 460 | } |
| 461 | p->zAttachName = (char*)file_tail(zName); |
| 462 | p->zAttachSrc = zSrc; |
| 463 | p->zAttachTarget = zTarget; |
| @@ -465,18 +460,18 @@ | |
| 465 | } |
| 466 | |
| 467 | /* |
| 468 | ** B <uuid> |
| 469 | ** |
| 470 | ** A B-line gives the UUID for the baseline of a delta-manifest. |
| 471 | */ |
| 472 | case 'B': { |
| 473 | if( p->zBaseline ) SYNTAX("more than one B-card"); |
| 474 | p->zBaseline = next_token(&x, &sz); |
| 475 | if( p->zBaseline==0 ) SYNTAX("missing UUID on B-card"); |
| 476 | if( sz!=UUID_SIZE || !validate16(p->zBaseline, UUID_SIZE) ){ |
| 477 | SYNTAX("invalid UUID on B-card"); |
| 478 | } |
| 479 | break; |
| 480 | } |
| 481 | |
| 482 | |
| @@ -522,12 +517,12 @@ | |
| 522 | case 'E': { |
| 523 | if( p->rEventDate>0.0 ) SYNTAX("more than one E-card"); |
| 524 | p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0)); |
| 525 | if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card"); |
| 526 | p->zEventId = next_token(&x, &sz); |
| 527 | if( sz!=UUID_SIZE || !validate16(p->zEventId, UUID_SIZE) ){ |
| 528 | SYNTAX("malformed UUID on E-card"); |
| 529 | } |
| 530 | break; |
| 531 | } |
| 532 | |
| 533 | /* |
| @@ -545,12 +540,13 @@ | |
| 545 | if( !file_is_simple_pathname(zName, 0) ){ |
| 546 | SYNTAX("F-card filename is not a simple path"); |
| 547 | } |
| 548 | zUuid = next_token(&x, &sz); |
| 549 | if( p->zBaseline==0 || zUuid!=0 ){ |
| 550 | if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size"); |
| 551 | if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("F-card UUID invalid"); |
| 552 | } |
| 553 | zPerm = next_token(&x,0); |
| 554 | zPriorName = next_token(&x,0); |
| 555 | if( zPriorName ){ |
| 556 | defossilize(zPriorName); |
| @@ -636,20 +632,21 @@ | |
| 636 | } |
| 637 | break; |
| 638 | } |
| 639 | |
| 640 | /* |
| 641 | ** M <uuid> |
| 642 | ** |
| 643 | ** An M-line identifies another artifact by its UUID. M-lines |
| 644 | ** occur in clusters only. |
| 645 | */ |
| 646 | case 'M': { |
| 647 | zUuid = next_token(&x, &sz); |
| 648 | if( zUuid==0 ) SYNTAX("missing UUID on M-card"); |
| 649 | if( sz!=UUID_SIZE ) SYNTAX("wrong size for UUID on M-card"); |
| 650 | if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("UUID invalid on M-card"); |
| 651 | if( p->nCChild>=p->nCChildAlloc ){ |
| 652 | p->nCChildAlloc = p->nCChildAlloc*2 + 10; |
| 653 | p->azCChild = fossil_realloc(p->azCChild |
| 654 | , p->nCChildAlloc*sizeof(p->azCChild[0]) ); |
| 655 | } |
| @@ -683,12 +680,13 @@ | |
| 683 | ** check-in historically has an empty P-card, so empty P-cards |
| 684 | ** must be accepted. |
| 685 | */ |
| 686 | case 'P': { |
| 687 | while( (zUuid = next_token(&x, &sz))!=0 ){ |
| 688 | if( sz!=UUID_SIZE ) SYNTAX("wrong size UUID on P-card"); |
| 689 | if( !validate16(zUuid, UUID_SIZE) )SYNTAX("invalid UUID on P-card"); |
| 690 | if( p->nParent>=p->nParentAlloc ){ |
| 691 | p->nParentAlloc = p->nParentAlloc*2 + 5; |
| 692 | p->azParent = fossil_realloc(p->azParent, |
| 693 | p->nParentAlloc*sizeof(char*)); |
| 694 | } |
| @@ -703,29 +701,25 @@ | |
| 703 | ** |
| 704 | ** Specify one or a range of check-ins that are cherrypicked into |
| 705 | ** this check-in ("+") or backed out of this check-in ("-"). |
| 706 | */ |
| 707 | case 'Q': { |
| 708 | if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing UUID on Q-card"); |
| 709 | if( sz!=UUID_SIZE+1 ) SYNTAX("wrong size UUID on Q-card"); |
| 710 | if( zUuid[0]!='+' && zUuid[0]!='-' ){ |
| 711 | SYNTAX("Q-card does not begin with '+' or '-'"); |
| 712 | } |
| 713 | if( !validate16(&zUuid[1], UUID_SIZE) ){ |
| 714 | SYNTAX("invalid UUID on Q-card"); |
| 715 | } |
| 716 | n = p->nCherrypick; |
| 717 | p->nCherrypick++; |
| 718 | p->aCherrypick = fossil_realloc(p->aCherrypick, |
| 719 | p->nCherrypick*sizeof(p->aCherrypick[0])); |
| 720 | p->aCherrypick[n].zCPTarget = zUuid; |
| 721 | p->aCherrypick[n].zCPBase = zUuid = next_token(&x, &sz); |
| 722 | if( zUuid ){ |
| 723 | if( sz!=UUID_SIZE ) SYNTAX("wrong size second UUID in Q-card"); |
| 724 | if( !validate16(zUuid, UUID_SIZE) ){ |
| 725 | SYNTAX("invalid second UUID on Q-card"); |
| 726 | } |
| 727 | } |
| 728 | break; |
| 729 | } |
| 730 | |
| 731 | /* |
| @@ -760,32 +754,32 @@ | |
| 760 | case 'T': { |
| 761 | char *zName, *zValue; |
| 762 | zName = next_token(&x, 0); |
| 763 | if( zName==0 ) SYNTAX("missing name on T-card"); |
| 764 | zUuid = next_token(&x, &sz); |
| 765 | if( zUuid==0 ) SYNTAX("missing UUID on T-card"); |
| 766 | zValue = next_token(&x, 0); |
| 767 | if( zValue ) defossilize(zValue); |
| 768 | if( sz==UUID_SIZE && validate16(zUuid, UUID_SIZE) ){ |
| 769 | /* A valid uuid */ |
| 770 | if( p->zEventId ) SYNTAX("non-self-referential T-card in event"); |
| 771 | }else if( sz==1 && zUuid[0]=='*' ){ |
| 772 | zUuid = 0; |
| 773 | hasSelfRefTag = 1; |
| 774 | if( p->zEventId && zName[0]!='+' ){ |
| 775 | SYNTAX("propagating T-card in event"); |
| 776 | } |
| 777 | }else{ |
| 778 | SYNTAX("malformed UUID on T-card"); |
| 779 | } |
| 780 | defossilize(zName); |
| 781 | if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){ |
| 782 | SYNTAX("T-card name does not begin with '-', '+', or '*'"); |
| 783 | } |
| 784 | if( validate16(&zName[1], strlen(&zName[1])) ){ |
| 785 | /* Do not allow tags whose names look like UUIDs */ |
| 786 | SYNTAX("T-card name looks like a UUID"); |
| 787 | } |
| 788 | if( p->nTag>=p->nTagAlloc ){ |
| 789 | p->nTagAlloc = p->nTagAlloc*2 + 10; |
| 790 | p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) ); |
| 791 | } |
| @@ -951,17 +945,19 @@ | |
| 951 | if( !seenZ ) SYNTAX("missing Z-card on control"); |
| 952 | p->type = CFTYPE_CONTROL; |
| 953 | } |
| 954 | md5sum_init(); |
| 955 | if( !isRepeat ) g.parseCnt[p->type]++; |
| 956 | blob_reset(&bUuid); |
| 957 | return p; |
| 958 | |
| 959 | manifest_syntax_error: |
| 960 | if(bUuid.nUsed){ |
| 961 | blob_appendf(pErr, "manifest [%.40s] ", blob_str(&bUuid)); |
| 962 | blob_reset(&bUuid); |
| 963 | } |
| 964 | if( zErr ){ |
| 965 | blob_appendf(pErr, "line %d: %s", lineNo, zErr); |
| 966 | }else{ |
| 967 | blob_appendf(pErr, "unknown error on line %d", lineNo); |
| @@ -1193,13 +1189,13 @@ | |
| 1193 | ** then the mlink entry is only created if there is already an mlink |
| 1194 | ** from primary parent for the same file. |
| 1195 | */ |
| 1196 | static void add_one_mlink( |
| 1197 | int pmid, /* The parent manifest */ |
| 1198 | const char *zFromUuid, /* UUID for content in parent */ |
| 1199 | int mid, /* The record ID of the manifest */ |
| 1200 | const char *zToUuid, /* UUID for content in child */ |
| 1201 | const char *zFilename, /* Filename */ |
| 1202 | const char *zPrior, /* Previous filename. NULL if unchanged */ |
| 1203 | int isPublic, /* True if mid is not a private manifest */ |
| 1204 | int isPrimary, /* pmid is the primary parent of mid */ |
| 1205 | int mperm /* 1: exec, 2: symlink */ |
| @@ -1545,22 +1541,22 @@ | |
| 1545 | } |
| 1546 | } |
| 1547 | |
| 1548 | /* |
| 1549 | ** For a check-in with RID "rid" that has nParent parent check-ins given |
| 1550 | ** by the UUIDs in azParent[], create all appropriate plink and mlink table |
| 1551 | ** entries. |
| 1552 | ** |
| 1553 | ** The primary parent is the first UUID on the azParent[] list. |
| 1554 | ** |
| 1555 | ** Return the RID of the primary parent. |
| 1556 | */ |
| 1557 | static int manifest_add_checkin_linkages( |
| 1558 | int rid, /* The RID of the check-in */ |
| 1559 | Manifest *p, /* Manifest for this check-in */ |
| 1560 | int nParent, /* Number of parents for this check-in */ |
| 1561 | char **azParent /* UUIDs for each parent */ |
| 1562 | ){ |
| 1563 | int i; |
| 1564 | int parentid = 0; |
| 1565 | char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */ |
| 1566 | Stmt q; |
| @@ -1611,33 +1607,36 @@ | |
| 1611 | return parentid; |
| 1612 | } |
| 1613 | |
| 1614 | /* |
| 1615 | ** There exists a "parent" tag against checkin rid that has value zValue. |
| 1616 | ** If value is well-formed (meaning that it is a list of UUIDs), then use |
| 1617 | ** zValue to reparent check-in rid. |
| 1618 | */ |
| 1619 | void manifest_reparent_checkin(int rid, const char *zValue){ |
| 1620 | int nParent; |
| 1621 | char *zCopy = 0; |
| 1622 | char **azParent = 0; |
| 1623 | Manifest *p = 0; |
| 1624 | int i; |
| 1625 | int n = (int)strlen(zValue); |
| 1626 | nParent = (n+1)/(UUID_SIZE+1); |
| 1627 | if( nParent*(UUID_SIZE+1) - 1 !=n ) return; |
| 1628 | if( nParent<1 ) return; |
| 1629 | zCopy = fossil_strdup(zValue); |
| 1630 | azParent = fossil_malloc( sizeof(azParent[0])*nParent ); |
| 1631 | for(i=0; i<nParent; i++){ |
| 1632 | azParent[i] = &zCopy[i*(UUID_SIZE+1)]; |
| 1633 | if( i<nParent-1 && azParent[i][UUID_SIZE]!=' ' ) break; |
| 1634 | azParent[i][UUID_SIZE] = 0; |
| 1635 | if( !validate16(azParent[i],UUID_SIZE) ) break; |
| 1636 | } |
| 1637 | if( i==nParent |
| 1638 | && !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d", |
| 1639 | rid, uuid_to_rid(azParent[0],0)) |
| 1640 | ){ |
| 1641 | p = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 1642 | } |
| 1643 | if( p!=0 ){ |
| @@ -1647,10 +1646,11 @@ | |
| 1647 | rid, rid |
| 1648 | ); |
| 1649 | manifest_add_checkin_linkages(rid,p,nParent,azParent); |
| 1650 | } |
| 1651 | manifest_destroy(p); |
| 1652 | fossil_free(azParent); |
| 1653 | fossil_free(zCopy); |
| 1654 | } |
| 1655 | |
| 1656 | /* |
| @@ -2280,11 +2280,11 @@ | |
| 2280 | int branchMove = 0; |
| 2281 | blob_zero(&comment); |
| 2282 | if( p->zComment ){ |
| 2283 | blob_appendf(&comment, " %s.", p->zComment); |
| 2284 | } |
| 2285 | /* Next loop expects tags to be sorted on UUID, so sort it. */ |
| 2286 | qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare); |
| 2287 | for(i=0; i<p->nTag; i++){ |
| 2288 | zTagUuid = p->aTag[i].zUuid; |
| 2289 | if( !zTagUuid ) continue; |
| 2290 | if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){ |
| 2291 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -54,11 +54,11 @@ | |
| 54 | /* |
| 55 | ** A single F-card within a manifest |
| 56 | */ |
| 57 | struct ManifestFile { |
| 58 | char *zName; /* Name of a file */ |
| 59 | char *zUuid; /* Artifact hash for the file */ |
| 60 | char *zPerm; /* File permissions */ |
| 61 | char *zPrior; /* Prior name if the name was changed */ |
| 62 | }; |
| 63 | |
| 64 | |
| @@ -77,35 +77,35 @@ | |
| 77 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 78 | char *zWiki; /* Text of the wiki page. W card. */ |
| 79 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 80 | char *zMimetype; /* Mime type of wiki or comment text. N card. */ |
| 81 | double rEventDate; /* Date of an event. E card. */ |
| 82 | char *zEventId; /* Artifact hash for an event. E card. */ |
| 83 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 84 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 85 | char *zAttachSrc; /* Artifact hash for document being attached. A card. */ |
| 86 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 87 | int nFile; /* Number of F cards */ |
| 88 | int nFileAlloc; /* Slots allocated in aFile[] */ |
| 89 | int iFile; /* Index of current file in iterator */ |
| 90 | ManifestFile *aFile; /* One entry for each F-card */ |
| 91 | int nParent; /* Number of parents. */ |
| 92 | int nParentAlloc; /* Slots allocated in azParent[] */ |
| 93 | char **azParent; /* Hashes of parents. One for each P card argument */ |
| 94 | int nCherrypick; /* Number of entries in aCherrypick[] */ |
| 95 | struct { |
| 96 | char *zCPTarget; /* Hash for cherry-picked version w/ +|- prefix */ |
| 97 | char *zCPBase; /* Hash for cherry-pick baseline. NULL for singletons */ |
| 98 | } *aCherrypick; |
| 99 | int nCChild; /* Number of cluster children */ |
| 100 | int nCChildAlloc; /* Number of closts allocated in azCChild[] */ |
| 101 | char **azCChild; /* Hashes of referenced objects in a cluster. M cards */ |
| 102 | int nTag; /* Number of T Cards */ |
| 103 | int nTagAlloc; /* Slots allocated in aTag[] */ |
| 104 | struct TagType { |
| 105 | char *zName; /* Name of the tag */ |
| 106 | char *zUuid; /* Hash of artifact that the tag is applied to */ |
| 107 | char *zValue; /* Value if the tag is really a property */ |
| 108 | } *aTag; /* One for each T card */ |
| 109 | int nField; /* Number of J cards */ |
| 110 | int nFieldAlloc; /* Slots allocated in aField[] */ |
| 111 | struct { |
| @@ -327,26 +327,27 @@ | |
| 327 | ** takes over the input blob and will free it when the |
| 328 | ** Manifest object is freed. Zeros are inserted into the blob |
| 329 | ** as string terminators so that blob should not be used again. |
| 330 | ** |
| 331 | ** Return a pointer to an allocated Manifest object if the content |
| 332 | ** really is a structural artifact of some kind. The returned Manifest |
| 333 | ** object needs to be freed by a subsequent call to manifest_destroy(). |
| 334 | ** Return NULL if there are syntax errors or if the input blob does |
| 335 | ** not describe a valid structural artifact. |
| 336 | ** |
| 337 | ** This routine is strict about the format of a structural artifacts. |
| 338 | ** The format must match exactly or else it is rejected. This |
| 339 | ** rule minimizes the risk that a content artifact will be mistaken |
| 340 | ** for a structural artifact simply because they look the same. |
| 341 | ** |
| 342 | ** The pContent is reset. If a pointer is returned, then pContent will |
| 343 | ** be reset when the Manifest object is cleared. If NULL is |
| 344 | ** returned then the Manifest object is cleared automatically |
| 345 | ** and pContent is reset before the return. |
| 346 | ** |
| 347 | ** The entire input blob can be PGP clear-signed. The signature is ignored. |
| 348 | ** The artifact consists of zero or more cards, one card per line. |
| 349 | ** (Except: the content of the W card can extend of multiple lines.) |
| 350 | ** Each card is divided into tokens by a single space character. |
| 351 | ** The first token is a single upper-case letter which is the card type. |
| 352 | ** The card type determines the other parameters to the card. |
| 353 | ** Cards must occur in lexicographical order. |
| @@ -361,11 +362,10 @@ | |
| 362 | char *z; |
| 363 | int n; |
| 364 | char *zUuid; |
| 365 | int sz = 0; |
| 366 | int isRepeat, hasSelfRefTag = 0; |
| 367 | static Bag seen; |
| 368 | const char *zErr = 0; |
| 369 | |
| 370 | if( rid==0 ){ |
| 371 | isRepeat = 1; |
| @@ -374,11 +374,11 @@ | |
| 374 | }else{ |
| 375 | isRepeat = 0; |
| 376 | bag_insert(&seen, rid); |
| 377 | } |
| 378 | |
| 379 | /* Every structural artifact ends with a '\n' character. Exit early |
| 380 | ** if that is not the case for this artifact. |
| 381 | */ |
| 382 | if( !isRepeat ) g.parseCnt[0]++; |
| 383 | z = blob_materialize(pContent); |
| 384 | n = blob_size(pContent); |
| @@ -406,15 +406,10 @@ | |
| 406 | blob_reset(pContent); |
| 407 | blob_appendf(pErr, "incorrect Z-card cksum"); |
| 408 | return 0; |
| 409 | } |
| 410 | |
| 411 | /* Allocate a Manifest object to hold the parsed control artifact. |
| 412 | */ |
| 413 | p = fossil_malloc( sizeof(*p) ); |
| 414 | memset(p, 0, sizeof(*p)); |
| 415 | memcpy(&p->content, pContent, sizeof(p->content)); |
| @@ -449,15 +444,15 @@ | |
| 444 | defossilize(zName); |
| 445 | if( !file_is_simple_pathname(zName, 0) ){ |
| 446 | SYNTAX("invalid filename on A-card"); |
| 447 | } |
| 448 | defossilize(zTarget); |
| 449 | if( !hname_validate(zTarget,nTarget) |
| 450 | && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| 451 | SYNTAX("invalid target on A-card"); |
| 452 | } |
| 453 | if( zSrc && !hname_validate(zSrc,nSrc) ){ |
| 454 | SYNTAX("invalid source on A-card"); |
| 455 | } |
| 456 | p->zAttachName = (char*)file_tail(zName); |
| 457 | p->zAttachSrc = zSrc; |
| 458 | p->zAttachTarget = zTarget; |
| @@ -465,18 +460,18 @@ | |
| 460 | } |
| 461 | |
| 462 | /* |
| 463 | ** B <uuid> |
| 464 | ** |
| 465 | ** A B-line gives the artifact hash for the baseline of a delta-manifest. |
| 466 | */ |
| 467 | case 'B': { |
| 468 | if( p->zBaseline ) SYNTAX("more than one B-card"); |
| 469 | p->zBaseline = next_token(&x, &sz); |
| 470 | if( p->zBaseline==0 ) SYNTAX("missing hash on B-card"); |
| 471 | if( !hname_validate(p->zBaseline,sz) ){ |
| 472 | SYNTAX("invalid hash on B-card"); |
| 473 | } |
| 474 | break; |
| 475 | } |
| 476 | |
| 477 | |
| @@ -522,12 +517,12 @@ | |
| 517 | case 'E': { |
| 518 | if( p->rEventDate>0.0 ) SYNTAX("more than one E-card"); |
| 519 | p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0)); |
| 520 | if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card"); |
| 521 | p->zEventId = next_token(&x, &sz); |
| 522 | if( !hname_validate(p->zEventId, sz) ){ |
| 523 | SYNTAX("malformed hash on E-card"); |
| 524 | } |
| 525 | break; |
| 526 | } |
| 527 | |
| 528 | /* |
| @@ -545,12 +540,13 @@ | |
| 540 | if( !file_is_simple_pathname(zName, 0) ){ |
| 541 | SYNTAX("F-card filename is not a simple path"); |
| 542 | } |
| 543 | zUuid = next_token(&x, &sz); |
| 544 | if( p->zBaseline==0 || zUuid!=0 ){ |
| 545 | if( !hname_validate(zUuid,sz) ){ |
| 546 | SYNTAX("F-card hash invalid"); |
| 547 | } |
| 548 | } |
| 549 | zPerm = next_token(&x,0); |
| 550 | zPriorName = next_token(&x,0); |
| 551 | if( zPriorName ){ |
| 552 | defossilize(zPriorName); |
| @@ -636,20 +632,21 @@ | |
| 632 | } |
| 633 | break; |
| 634 | } |
| 635 | |
| 636 | /* |
| 637 | ** M <hash> |
| 638 | ** |
| 639 | ** An M-line identifies another artifact by its hash. M-lines |
| 640 | ** occur in clusters only. |
| 641 | */ |
| 642 | case 'M': { |
| 643 | zUuid = next_token(&x, &sz); |
| 644 | if( zUuid==0 ) SYNTAX("missing hash on M-card"); |
| 645 | if( !hname_validate(zUuid,sz) ){ |
| 646 | SYNTAX("Invalid hash on M-card"); |
| 647 | } |
| 648 | if( p->nCChild>=p->nCChildAlloc ){ |
| 649 | p->nCChildAlloc = p->nCChildAlloc*2 + 10; |
| 650 | p->azCChild = fossil_realloc(p->azCChild |
| 651 | , p->nCChildAlloc*sizeof(p->azCChild[0]) ); |
| 652 | } |
| @@ -683,12 +680,13 @@ | |
| 680 | ** check-in historically has an empty P-card, so empty P-cards |
| 681 | ** must be accepted. |
| 682 | */ |
| 683 | case 'P': { |
| 684 | while( (zUuid = next_token(&x, &sz))!=0 ){ |
| 685 | if( !hname_validate(zUuid, sz) ){ |
| 686 | SYNTAX("invalid hash on P-card"); |
| 687 | } |
| 688 | if( p->nParent>=p->nParentAlloc ){ |
| 689 | p->nParentAlloc = p->nParentAlloc*2 + 5; |
| 690 | p->azParent = fossil_realloc(p->azParent, |
| 691 | p->nParentAlloc*sizeof(char*)); |
| 692 | } |
| @@ -703,29 +701,25 @@ | |
| 701 | ** |
| 702 | ** Specify one or a range of check-ins that are cherrypicked into |
| 703 | ** this check-in ("+") or backed out of this check-in ("-"). |
| 704 | */ |
| 705 | case 'Q': { |
| 706 | if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing hash on Q-card"); |
| 707 | if( zUuid[0]!='+' && zUuid[0]!='-' ){ |
| 708 | SYNTAX("Q-card does not begin with '+' or '-'"); |
| 709 | } |
| 710 | if( !hname_validate(&zUuid[1], sz-1) ){ |
| 711 | SYNTAX("invalid hash on Q-card"); |
| 712 | } |
| 713 | n = p->nCherrypick; |
| 714 | p->nCherrypick++; |
| 715 | p->aCherrypick = fossil_realloc(p->aCherrypick, |
| 716 | p->nCherrypick*sizeof(p->aCherrypick[0])); |
| 717 | p->aCherrypick[n].zCPTarget = zUuid; |
| 718 | p->aCherrypick[n].zCPBase = zUuid = next_token(&x, &sz); |
| 719 | if( zUuid && !hname_validate(zUuid,sz) ){ |
| 720 | SYNTAX("invalid second hash on Q-card"); |
| 721 | } |
| 722 | break; |
| 723 | } |
| 724 | |
| 725 | /* |
| @@ -760,32 +754,32 @@ | |
| 754 | case 'T': { |
| 755 | char *zName, *zValue; |
| 756 | zName = next_token(&x, 0); |
| 757 | if( zName==0 ) SYNTAX("missing name on T-card"); |
| 758 | zUuid = next_token(&x, &sz); |
| 759 | if( zUuid==0 ) SYNTAX("missing artifact hash on T-card"); |
| 760 | zValue = next_token(&x, 0); |
| 761 | if( zValue ) defossilize(zValue); |
| 762 | if( hname_validate(zUuid, sz) ){ |
| 763 | /* A valid artifact hash */ |
| 764 | if( p->zEventId ) SYNTAX("non-self-referential T-card in event"); |
| 765 | }else if( sz==1 && zUuid[0]=='*' ){ |
| 766 | zUuid = 0; |
| 767 | hasSelfRefTag = 1; |
| 768 | if( p->zEventId && zName[0]!='+' ){ |
| 769 | SYNTAX("propagating T-card in event"); |
| 770 | } |
| 771 | }else{ |
| 772 | SYNTAX("malformed artifact hash on T-card"); |
| 773 | } |
| 774 | defossilize(zName); |
| 775 | if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){ |
| 776 | SYNTAX("T-card name does not begin with '-', '+', or '*'"); |
| 777 | } |
| 778 | if( validate16(&zName[1], strlen(&zName[1])) ){ |
| 779 | /* Do not allow tags whose names look like a hash */ |
| 780 | SYNTAX("T-card name looks like a hexadecimal hash"); |
| 781 | } |
| 782 | if( p->nTag>=p->nTagAlloc ){ |
| 783 | p->nTagAlloc = p->nTagAlloc*2 + 10; |
| 784 | p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) ); |
| 785 | } |
| @@ -951,17 +945,19 @@ | |
| 945 | if( !seenZ ) SYNTAX("missing Z-card on control"); |
| 946 | p->type = CFTYPE_CONTROL; |
| 947 | } |
| 948 | md5sum_init(); |
| 949 | if( !isRepeat ) g.parseCnt[p->type]++; |
| 950 | return p; |
| 951 | |
| 952 | manifest_syntax_error: |
| 953 | { |
| 954 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 955 | if( zUuid ){ |
| 956 | blob_appendf(pErr, "manifest [%s] ", zUuid); |
| 957 | fossil_free(zUuid); |
| 958 | } |
| 959 | } |
| 960 | if( zErr ){ |
| 961 | blob_appendf(pErr, "line %d: %s", lineNo, zErr); |
| 962 | }else{ |
| 963 | blob_appendf(pErr, "unknown error on line %d", lineNo); |
| @@ -1193,13 +1189,13 @@ | |
| 1189 | ** then the mlink entry is only created if there is already an mlink |
| 1190 | ** from primary parent for the same file. |
| 1191 | */ |
| 1192 | static void add_one_mlink( |
| 1193 | int pmid, /* The parent manifest */ |
| 1194 | const char *zFromUuid, /* Artifact hash for content in parent */ |
| 1195 | int mid, /* The record ID of the manifest */ |
| 1196 | const char *zToUuid, /* artifact hash for content in child */ |
| 1197 | const char *zFilename, /* Filename */ |
| 1198 | const char *zPrior, /* Previous filename. NULL if unchanged */ |
| 1199 | int isPublic, /* True if mid is not a private manifest */ |
| 1200 | int isPrimary, /* pmid is the primary parent of mid */ |
| 1201 | int mperm /* 1: exec, 2: symlink */ |
| @@ -1545,22 +1541,22 @@ | |
| 1541 | } |
| 1542 | } |
| 1543 | |
| 1544 | /* |
| 1545 | ** For a check-in with RID "rid" that has nParent parent check-ins given |
| 1546 | ** by the hashes in azParent[], create all appropriate plink and mlink table |
| 1547 | ** entries. |
| 1548 | ** |
| 1549 | ** The primary parent is the first hash on the azParent[] list. |
| 1550 | ** |
| 1551 | ** Return the RID of the primary parent. |
| 1552 | */ |
| 1553 | static int manifest_add_checkin_linkages( |
| 1554 | int rid, /* The RID of the check-in */ |
| 1555 | Manifest *p, /* Manifest for this check-in */ |
| 1556 | int nParent, /* Number of parents for this check-in */ |
| 1557 | char **azParent /* hashes for each parent */ |
| 1558 | ){ |
| 1559 | int i; |
| 1560 | int parentid = 0; |
| 1561 | char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */ |
| 1562 | Stmt q; |
| @@ -1611,33 +1607,36 @@ | |
| 1607 | return parentid; |
| 1608 | } |
| 1609 | |
| 1610 | /* |
| 1611 | ** There exists a "parent" tag against checkin rid that has value zValue. |
| 1612 | ** If value is well-formed (meaning that it is a list of hashes), then use |
| 1613 | ** zValue to reparent check-in rid. |
| 1614 | */ |
| 1615 | void manifest_reparent_checkin(int rid, const char *zValue){ |
| 1616 | int nParent = 0; |
| 1617 | char *zCopy = 0; |
| 1618 | char **azParent = 0; |
| 1619 | Manifest *p = 0; |
| 1620 | int i, j; |
| 1621 | int n = (int)strlen(zValue); |
| 1622 | int mxParent = (n+1)/(HNAME_MIN+1); |
| 1623 | |
| 1624 | if( mxParent<1 ) return; |
| 1625 | zCopy = fossil_strdup(zValue); |
| 1626 | azParent = fossil_malloc( sizeof(azParent[0])*mxParent ); |
| 1627 | for(nParent=0, i=0; zCopy[i]; i++){ |
| 1628 | char *z = &zCopy[i]; |
| 1629 | azParent[nParent++] = z; |
| 1630 | if( nParent>mxParent ) goto reparent_abort; |
| 1631 | for(j=HNAME_MIN; z[j]>' '; j++){} |
| 1632 | if( !hname_validate(z, j) ) goto reparent_abort; |
| 1633 | if( z[j]==0 ) break; |
| 1634 | z[j] = 0; |
| 1635 | i += j; |
| 1636 | } |
| 1637 | if( !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d", |
| 1638 | rid, uuid_to_rid(azParent[0],0)) |
| 1639 | ){ |
| 1640 | p = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 1641 | } |
| 1642 | if( p!=0 ){ |
| @@ -1647,10 +1646,11 @@ | |
| 1646 | rid, rid |
| 1647 | ); |
| 1648 | manifest_add_checkin_linkages(rid,p,nParent,azParent); |
| 1649 | } |
| 1650 | manifest_destroy(p); |
| 1651 | reparent_abort: |
| 1652 | fossil_free(azParent); |
| 1653 | fossil_free(zCopy); |
| 1654 | } |
| 1655 | |
| 1656 | /* |
| @@ -2280,11 +2280,11 @@ | |
| 2280 | int branchMove = 0; |
| 2281 | blob_zero(&comment); |
| 2282 | if( p->zComment ){ |
| 2283 | blob_appendf(&comment, " %s.", p->zComment); |
| 2284 | } |
| 2285 | /* Next loop expects tags to be sorted on hash, so sort it. */ |
| 2286 | qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare); |
| 2287 | for(i=0; i<p->nTag; i++){ |
| 2288 | zTagUuid = p->aTag[i].zUuid; |
| 2289 | if( !zTagUuid ) continue; |
| 2290 | if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){ |
| 2291 |
+15
-1
| --- src/md5.c | ||
| +++ src/md5.c | ||
| @@ -22,10 +22,20 @@ | ||
| 22 | 22 | #include <string.h> |
| 23 | 23 | #include <stdio.h> |
| 24 | 24 | #include <sqlite3.h> |
| 25 | 25 | #include "md5.h" |
| 26 | 26 | |
| 27 | +#ifdef FOSSIL_ENABLE_SSL | |
| 28 | + | |
| 29 | +# include <openssl/md5.h> | |
| 30 | +# define MD5Context MD5_CTX | |
| 31 | +# define MD5Init MD5_Init | |
| 32 | +# define MD5Update MD5_Update | |
| 33 | +# define MD5Final MD5_Final | |
| 34 | + | |
| 35 | +#else | |
| 36 | + | |
| 27 | 37 | /* |
| 28 | 38 | * If compiled on a machine that doesn't have a 32-bit integer, |
| 29 | 39 | * you just set "uint32" to the appropriate datatype for an |
| 30 | 40 | * unsigned 32-bit integer. For example: |
| 31 | 41 | * |
| @@ -42,11 +52,14 @@ | ||
| 42 | 52 | uint32 bits[2]; |
| 43 | 53 | unsigned char in[64]; |
| 44 | 54 | }; |
| 45 | 55 | typedef struct Context MD5Context; |
| 46 | 56 | |
| 47 | -#if defined(__i386__) || defined(__x86_64__) || defined(_WIN32) | |
| 57 | +#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ | |
| 58 | + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ | |
| 59 | + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ | |
| 60 | + defined(__arm__) || defined(_WIN32) | |
| 48 | 61 | # define byteReverse(A,B) |
| 49 | 62 | #else |
| 50 | 63 | /* |
| 51 | 64 | * Convert an array of integers to little-endian. |
| 52 | 65 | * Note: this code is a no-op on little-endian machines. |
| @@ -266,10 +279,11 @@ | ||
| 266 | 279 | MD5Transform(ctx->buf, (uint32 *)ctx->in); |
| 267 | 280 | byteReverse((unsigned char *)ctx->buf, 4); |
| 268 | 281 | memcpy(digest, ctx->buf, 16); |
| 269 | 282 | memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ |
| 270 | 283 | } |
| 284 | +#endif | |
| 271 | 285 | |
| 272 | 286 | /* |
| 273 | 287 | ** Convert a digest into base-16. digest should be declared as |
| 274 | 288 | ** "unsigned char digest[16]" in the calling function. The MD5 |
| 275 | 289 | ** digest is stored in the first 16 bytes. zBuf should |
| 276 | 290 |
| --- src/md5.c | |
| +++ src/md5.c | |
| @@ -22,10 +22,20 @@ | |
| 22 | #include <string.h> |
| 23 | #include <stdio.h> |
| 24 | #include <sqlite3.h> |
| 25 | #include "md5.h" |
| 26 | |
| 27 | /* |
| 28 | * If compiled on a machine that doesn't have a 32-bit integer, |
| 29 | * you just set "uint32" to the appropriate datatype for an |
| 30 | * unsigned 32-bit integer. For example: |
| 31 | * |
| @@ -42,11 +52,14 @@ | |
| 42 | uint32 bits[2]; |
| 43 | unsigned char in[64]; |
| 44 | }; |
| 45 | typedef struct Context MD5Context; |
| 46 | |
| 47 | #if defined(__i386__) || defined(__x86_64__) || defined(_WIN32) |
| 48 | # define byteReverse(A,B) |
| 49 | #else |
| 50 | /* |
| 51 | * Convert an array of integers to little-endian. |
| 52 | * Note: this code is a no-op on little-endian machines. |
| @@ -266,10 +279,11 @@ | |
| 266 | MD5Transform(ctx->buf, (uint32 *)ctx->in); |
| 267 | byteReverse((unsigned char *)ctx->buf, 4); |
| 268 | memcpy(digest, ctx->buf, 16); |
| 269 | memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ |
| 270 | } |
| 271 | |
| 272 | /* |
| 273 | ** Convert a digest into base-16. digest should be declared as |
| 274 | ** "unsigned char digest[16]" in the calling function. The MD5 |
| 275 | ** digest is stored in the first 16 bytes. zBuf should |
| 276 |
| --- src/md5.c | |
| +++ src/md5.c | |
| @@ -22,10 +22,20 @@ | |
| 22 | #include <string.h> |
| 23 | #include <stdio.h> |
| 24 | #include <sqlite3.h> |
| 25 | #include "md5.h" |
| 26 | |
| 27 | #ifdef FOSSIL_ENABLE_SSL |
| 28 | |
| 29 | # include <openssl/md5.h> |
| 30 | # define MD5Context MD5_CTX |
| 31 | # define MD5Init MD5_Init |
| 32 | # define MD5Update MD5_Update |
| 33 | # define MD5Final MD5_Final |
| 34 | |
| 35 | #else |
| 36 | |
| 37 | /* |
| 38 | * If compiled on a machine that doesn't have a 32-bit integer, |
| 39 | * you just set "uint32" to the appropriate datatype for an |
| 40 | * unsigned 32-bit integer. For example: |
| 41 | * |
| @@ -42,11 +52,14 @@ | |
| 52 | uint32 bits[2]; |
| 53 | unsigned char in[64]; |
| 54 | }; |
| 55 | typedef struct Context MD5Context; |
| 56 | |
| 57 | #if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ |
| 58 | defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ |
| 59 | defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ |
| 60 | defined(__arm__) || defined(_WIN32) |
| 61 | # define byteReverse(A,B) |
| 62 | #else |
| 63 | /* |
| 64 | * Convert an array of integers to little-endian. |
| 65 | * Note: this code is a no-op on little-endian machines. |
| @@ -266,10 +279,11 @@ | |
| 279 | MD5Transform(ctx->buf, (uint32 *)ctx->in); |
| 280 | byteReverse((unsigned char *)ctx->buf, 4); |
| 281 | memcpy(digest, ctx->buf, 16); |
| 282 | memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ |
| 283 | } |
| 284 | #endif |
| 285 | |
| 286 | /* |
| 287 | ** Convert a digest into base-16. digest should be declared as |
| 288 | ** "unsigned char digest[16]" in the calling function. The MD5 |
| 289 | ** digest is stored in the first 16 bytes. zBuf should |
| 290 |
+6
-5
| --- src/mkversion.c | ||
| +++ src/mkversion.c | ||
| @@ -12,11 +12,12 @@ | ||
| 12 | 12 | #include <stdlib.h> |
| 13 | 13 | |
| 14 | 14 | int main(int argc, char *argv[]){ |
| 15 | 15 | FILE *m,*u,*v; |
| 16 | 16 | char *z; |
| 17 | - int i, x, d; | |
| 17 | + int i, j, x, d; | |
| 18 | + int vn[3]; | |
| 18 | 19 | char b[1000]; |
| 19 | 20 | char vx[1000]; |
| 20 | 21 | memset(b,0,sizeof(b)); |
| 21 | 22 | memset(vx,0,sizeof(vx)); |
| 22 | 23 | u = fopen(argv[1],"r"); |
| @@ -45,25 +46,25 @@ | ||
| 45 | 46 | fclose(v); |
| 46 | 47 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 47 | 48 | *z = 0; |
| 48 | 49 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 49 | 50 | x=0; |
| 50 | - i=0; | |
| 51 | + i=j=0; | |
| 51 | 52 | z=b; |
| 53 | + vn[0] = vn[1] = vn[2] = 0; | |
| 52 | 54 | while(1){ |
| 53 | 55 | if( z[0]>='0' && z[0]<='9' ){ |
| 54 | 56 | x = x*10 + z[0] - '0'; |
| 55 | 57 | }else{ |
| 56 | - sprintf(&vx[i],"%02d",x); | |
| 57 | - i += 2; | |
| 58 | + if( j<3 ) vn[j++] = x; | |
| 58 | 59 | x = 0; |
| 59 | 60 | if( z[0]==0 ) break; |
| 60 | 61 | } |
| 61 | 62 | z++; |
| 62 | 63 | } |
| 63 | 64 | for(z=vx; z[0]=='0'; z++){} |
| 64 | - printf("#define RELEASE_VERSION_NUMBER %s\n", z); | |
| 65 | + printf("#define RELEASE_VERSION_NUMBER %d%02d%02d\n", vn[0], vn[1], vn[2]); | |
| 65 | 66 | memset(vx,0,sizeof(vx)); |
| 66 | 67 | strcpy(vx,b); |
| 67 | 68 | d = 0; |
| 68 | 69 | for(z=vx; z[0]; z++){ |
| 69 | 70 | if( z[0]=='-' ){ |
| 70 | 71 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -12,11 +12,12 @@ | |
| 12 | #include <stdlib.h> |
| 13 | |
| 14 | int main(int argc, char *argv[]){ |
| 15 | FILE *m,*u,*v; |
| 16 | char *z; |
| 17 | int i, x, d; |
| 18 | char b[1000]; |
| 19 | char vx[1000]; |
| 20 | memset(b,0,sizeof(b)); |
| 21 | memset(vx,0,sizeof(vx)); |
| 22 | u = fopen(argv[1],"r"); |
| @@ -45,25 +46,25 @@ | |
| 45 | fclose(v); |
| 46 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 47 | *z = 0; |
| 48 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 49 | x=0; |
| 50 | i=0; |
| 51 | z=b; |
| 52 | while(1){ |
| 53 | if( z[0]>='0' && z[0]<='9' ){ |
| 54 | x = x*10 + z[0] - '0'; |
| 55 | }else{ |
| 56 | sprintf(&vx[i],"%02d",x); |
| 57 | i += 2; |
| 58 | x = 0; |
| 59 | if( z[0]==0 ) break; |
| 60 | } |
| 61 | z++; |
| 62 | } |
| 63 | for(z=vx; z[0]=='0'; z++){} |
| 64 | printf("#define RELEASE_VERSION_NUMBER %s\n", z); |
| 65 | memset(vx,0,sizeof(vx)); |
| 66 | strcpy(vx,b); |
| 67 | d = 0; |
| 68 | for(z=vx; z[0]; z++){ |
| 69 | if( z[0]=='-' ){ |
| 70 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -12,11 +12,12 @@ | |
| 12 | #include <stdlib.h> |
| 13 | |
| 14 | int main(int argc, char *argv[]){ |
| 15 | FILE *m,*u,*v; |
| 16 | char *z; |
| 17 | int i, j, x, d; |
| 18 | int vn[3]; |
| 19 | char b[1000]; |
| 20 | char vx[1000]; |
| 21 | memset(b,0,sizeof(b)); |
| 22 | memset(vx,0,sizeof(vx)); |
| 23 | u = fopen(argv[1],"r"); |
| @@ -45,25 +46,25 @@ | |
| 46 | fclose(v); |
| 47 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 48 | *z = 0; |
| 49 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 50 | x=0; |
| 51 | i=j=0; |
| 52 | z=b; |
| 53 | vn[0] = vn[1] = vn[2] = 0; |
| 54 | while(1){ |
| 55 | if( z[0]>='0' && z[0]<='9' ){ |
| 56 | x = x*10 + z[0] - '0'; |
| 57 | }else{ |
| 58 | if( j<3 ) vn[j++] = x; |
| 59 | x = 0; |
| 60 | if( z[0]==0 ) break; |
| 61 | } |
| 62 | z++; |
| 63 | } |
| 64 | for(z=vx; z[0]=='0'; z++){} |
| 65 | printf("#define RELEASE_VERSION_NUMBER %d%02d%02d\n", vn[0], vn[1], vn[2]); |
| 66 | memset(vx,0,sizeof(vx)); |
| 67 | strcpy(vx,b); |
| 68 | d = 0; |
| 69 | for(z=vx; z[0]; z++){ |
| 70 | if( z[0]=='-' ){ |
| 71 |
+24
-28
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | 3 | ** |
| 4 | 4 | ** This program is free software; you can redistribute it and/or |
| 5 | 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | - | |
| 7 | +** | |
| 8 | 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | 9 | ** but without any warranty; without even the implied warranty of |
| 10 | 10 | ** merchantability or fitness for a particular purpose. |
| 11 | 11 | ** |
| 12 | 12 | ** Author contact information: |
| @@ -13,15 +13,11 @@ | ||
| 13 | 13 | ** [email protected] |
| 14 | 14 | ** http://www.hwaci.com/drh/ |
| 15 | 15 | ** |
| 16 | 16 | ******************************************************************************* |
| 17 | 17 | ** |
| 18 | -** This file contains code used to convert user-supplied object names into | |
| 19 | -** canonical UUIDs. | |
| 20 | -** | |
| 21 | -** A user-supplied object name is any unique prefix of a valid UUID but | |
| 22 | -** not necessarily in canonical form. | |
| 18 | +** This file contains code used to resolved user-supplied object names. | |
| 23 | 19 | */ |
| 24 | 20 | #include "config.h" |
| 25 | 21 | #include "name.h" |
| 26 | 22 | #include <assert.h> |
| 27 | 23 | |
| @@ -80,12 +76,12 @@ | ||
| 80 | 76 | } |
| 81 | 77 | |
| 82 | 78 | /* |
| 83 | 79 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 84 | 80 | ** |
| 85 | -** * SHA1 hash | |
| 86 | -** * SHA1 hash prefix of at least 4 characters | |
| 81 | +** * artifact hash | |
| 82 | +** * 4-character or larger prefix of a artifact | |
| 87 | 83 | ** * Symbolic Name |
| 88 | 84 | ** * "tag:" + symbolic name |
| 89 | 85 | ** * Date or date-time |
| 90 | 86 | ** * "date:" + Date or date-time |
| 91 | 87 | ** * symbolic-name ":" date-time |
| @@ -105,11 +101,11 @@ | ||
| 105 | 101 | ** If zType is "br" then find the first check-in of the named branch |
| 106 | 102 | ** rather than the last. |
| 107 | 103 | ** zType is "ci" in most use cases since we are usually searching for |
| 108 | 104 | ** a check-in. |
| 109 | 105 | ** |
| 110 | -** Note that the input zTag for types "t" and "e" is the SHA1 hash of | |
| 106 | +** Note that the input zTag for types "t" and "e" is the artifact hash of | |
| 111 | 107 | ** the ticket-change or event-change artifact, not the randomly generated |
| 112 | 108 | ** hexadecimal identifier assigned to tickets and events. Those identifiers |
| 113 | 109 | ** live in a separate namespace. |
| 114 | 110 | */ |
| 115 | 111 | int symbolic_name_to_rid(const char *zTag, const char *zType){ |
| @@ -232,14 +228,14 @@ | ||
| 232 | 228 | zTagBase, zDate, zType |
| 233 | 229 | ); |
| 234 | 230 | return rid; |
| 235 | 231 | } |
| 236 | 232 | |
| 237 | - /* SHA1 hash or prefix */ | |
| 238 | - if( nTag>=4 && nTag<=UUID_SIZE && validate16(zTag, nTag) ){ | |
| 233 | + /* artifact hash or prefix */ | |
| 234 | + if( nTag>=4 && nTag<=HNAME_MAX && validate16(zTag, nTag) ){ | |
| 239 | 235 | Stmt q; |
| 240 | - char zUuid[UUID_SIZE+1]; | |
| 236 | + char zUuid[HNAME_MAX+1]; | |
| 241 | 237 | memcpy(zUuid, zTag, nTag+1); |
| 242 | 238 | canonical16(zUuid, nTag); |
| 243 | 239 | rid = 0; |
| 244 | 240 | if( zType[0]=='*' ){ |
| 245 | 241 | db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid); |
| @@ -354,11 +350,11 @@ | ||
| 354 | 350 | */ |
| 355 | 351 | int name_collisions(const char *zName){ |
| 356 | 352 | int c = 0; /* count of collisions for zName */ |
| 357 | 353 | int nLen; /* length of zName */ |
| 358 | 354 | nLen = strlen(zName); |
| 359 | - if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ | |
| 355 | + if( nLen>=4 && nLen<=HNAME_MAX && validate16(zName, nLen) ){ | |
| 360 | 356 | c = db_int(0, |
| 361 | 357 | "SELECT" |
| 362 | 358 | " (SELECT count(*) FROM ticket" |
| 363 | 359 | " WHERE tkt_uuid GLOB '%q*') +" |
| 364 | 360 | " (SELECT count(*) FROM tag" |
| @@ -396,11 +392,11 @@ | ||
| 396 | 392 | |
| 397 | 393 | /* |
| 398 | 394 | ** Convert a name to a rid. If the name can be any of the various forms |
| 399 | 395 | ** accepted: |
| 400 | 396 | ** |
| 401 | -** * SHA1 hash or prefix thereof | |
| 397 | +** * artifact hash or prefix thereof | |
| 402 | 398 | ** * symbolic name |
| 403 | 399 | ** * date |
| 404 | 400 | ** * label:date |
| 405 | 401 | ** * prev, previous |
| 406 | 402 | ** * next |
| @@ -425,13 +421,13 @@ | ||
| 425 | 421 | return name_to_typed_rid(zName, "*"); |
| 426 | 422 | } |
| 427 | 423 | |
| 428 | 424 | /* |
| 429 | 425 | ** WEBPAGE: ambiguous |
| 430 | -** URL: /ambiguous?name=UUID&src=WEBPAGE | |
| 426 | +** URL: /ambiguous?name=NAME&src=WEBPAGE | |
| 431 | 427 | ** |
| 432 | -** The UUID given by the name parameter is ambiguous. Display a page | |
| 428 | +** The NAME given by the name parameter is ambiguous. Display a page | |
| 433 | 429 | ** that shows all possible choices and let the user select between them. |
| 434 | 430 | */ |
| 435 | 431 | void ambiguous_page(void){ |
| 436 | 432 | Stmt q; |
| 437 | 433 | const char *zName = P("name"); |
| @@ -668,11 +664,11 @@ | ||
| 668 | 664 | /* |
| 669 | 665 | ** COMMAND: whatis* |
| 670 | 666 | ** |
| 671 | 667 | ** Usage: %fossil whatis NAME |
| 672 | 668 | ** |
| 673 | -** Resolve the symbol NAME into its canonical 40-character SHA1-hash | |
| 669 | +** Resolve the symbol NAME into its canonical artifact hash | |
| 674 | 670 | ** artifact name and provide a description of what role that artifact |
| 675 | 671 | ** plays. |
| 676 | 672 | ** |
| 677 | 673 | ** Options: |
| 678 | 674 | ** |
| @@ -744,11 +740,11 @@ | ||
| 744 | 740 | /* |
| 745 | 741 | ** COMMAND: test-ambiguous |
| 746 | 742 | ** |
| 747 | 743 | ** Usage: %fossil test-ambiguous [--minsize N] |
| 748 | 744 | ** |
| 749 | -** Show a list of ambiguous SHA1-hash abbreviations of N characters or | |
| 745 | +** Show a list of ambiguous artifact hash abbreviations of N characters or | |
| 750 | 746 | ** more where N defaults to 4. Change N to a different value using |
| 751 | 747 | ** the "--minsize N" command-line option. |
| 752 | 748 | */ |
| 753 | 749 | void test_ambiguous_cmd(void){ |
| 754 | 750 | Stmt q, ins; |
| @@ -794,11 +790,11 @@ | ||
| 794 | 790 | ** Schema for the description table |
| 795 | 791 | */ |
| 796 | 792 | static const char zDescTab[] = |
| 797 | 793 | @ CREATE TEMP TABLE IF NOT EXISTS description( |
| 798 | 794 | @ rid INTEGER PRIMARY KEY, -- RID of the object |
| 799 | -@ uuid TEXT, -- SHA1 hash of the object | |
| 795 | +@ uuid TEXT, -- hash of the object | |
| 800 | 796 | @ ctime DATETIME, -- Time of creation |
| 801 | 797 | @ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts |
| 802 | 798 | @ type TEXT, -- file, checkin, wiki, ticket, etc. |
| 803 | 799 | @ summary TEXT, -- Summary comment for the object |
| 804 | 800 | @ detail TEXT -- File name, check-in comment, etc |
| @@ -1084,11 +1080,11 @@ | ||
| 1084 | 1080 | " WHERE description.rid=blob.rid" |
| 1085 | 1081 | " ORDER BY length(content) DESC" |
| 1086 | 1082 | ); |
| 1087 | 1083 | @ <table cellpadding="2" cellspacing="0" border="1" id="bigblobtab"> |
| 1088 | 1084 | @ <thead><tr><th align="right">Size<th align="right">RID |
| 1089 | - @ <th align="right">Delta From<th>SHA1<th>Description<th>Date</tr></thead> | |
| 1085 | + @ <th align="right">Delta From<th>Hash<th>Description<th>Date</tr></thead> | |
| 1090 | 1086 | @ <tbody> |
| 1091 | 1087 | while( db_step(&q)==SQLITE_ROW ){ |
| 1092 | 1088 | int rid = db_column_int(&q,0); |
| 1093 | 1089 | const char *zUuid = db_column_text(&q, 1); |
| 1094 | 1090 | const char *zDesc = db_column_text(&q, 2); |
| @@ -1147,33 +1143,33 @@ | ||
| 1147 | 1143 | |
| 1148 | 1144 | /* Maximum number of collision examples to remember */ |
| 1149 | 1145 | #define MAX_COLLIDE 25 |
| 1150 | 1146 | |
| 1151 | 1147 | /* |
| 1152 | -** Generate a report on the number of collisions in SHA1 hashes | |
| 1148 | +** Generate a report on the number of collisions in artifact hashes | |
| 1153 | 1149 | ** generated by the SQL given in the argument. |
| 1154 | 1150 | */ |
| 1155 | 1151 | static void collision_report(const char *zSql){ |
| 1156 | 1152 | int i, j, kk; |
| 1157 | 1153 | int nHash = 0; |
| 1158 | 1154 | Stmt q; |
| 1159 | - char zPrev[UUID_SIZE+1]; | |
| 1155 | + char zPrev[HNAME_MAX+1]; | |
| 1160 | 1156 | struct { |
| 1161 | 1157 | int cnt; |
| 1162 | 1158 | char *azHit[MAX_COLLIDE]; |
| 1163 | - char z[UUID_SIZE+1]; | |
| 1164 | - } aCollide[UUID_SIZE+1]; | |
| 1159 | + char z[HNAME_MAX+1]; | |
| 1160 | + } aCollide[HNAME_MAX+1]; | |
| 1165 | 1161 | memset(aCollide, 0, sizeof(aCollide)); |
| 1166 | 1162 | memset(zPrev, 0, sizeof(zPrev)); |
| 1167 | 1163 | db_prepare(&q,"%s",zSql/*safe-for-%s*/); |
| 1168 | 1164 | while( db_step(&q)==SQLITE_ROW ){ |
| 1169 | 1165 | const char *zUuid = db_column_text(&q,0); |
| 1170 | 1166 | int n = db_column_bytes(&q,0); |
| 1171 | 1167 | int i; |
| 1172 | 1168 | nHash++; |
| 1173 | 1169 | for(i=0; zPrev[i] && zPrev[i]==zUuid[i]; i++){} |
| 1174 | - if( i>0 && i<=UUID_SIZE ){ | |
| 1170 | + if( i>0 && i<=HNAME_MAX ){ | |
| 1175 | 1171 | if( i>=4 && aCollide[i].cnt<MAX_COLLIDE ){ |
| 1176 | 1172 | aCollide[i].azHit[aCollide[i].cnt] = mprintf("%.*s", i, zPrev); |
| 1177 | 1173 | } |
| 1178 | 1174 | aCollide[i].cnt++; |
| 1179 | 1175 | if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1); |
| @@ -1182,18 +1178,18 @@ | ||
| 1182 | 1178 | } |
| 1183 | 1179 | db_finalize(&q); |
| 1184 | 1180 | @ <table border=1><thead> |
| 1185 | 1181 | @ <tr><th>Length<th>Instances<th>First Instance</tr> |
| 1186 | 1182 | @ </thead><tbody> |
| 1187 | - for(i=1; i<=UUID_SIZE; i++){ | |
| 1183 | + for(i=1; i<=HNAME_MAX; i++){ | |
| 1188 | 1184 | if( aCollide[i].cnt==0 ) continue; |
| 1189 | 1185 | @ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr> |
| 1190 | 1186 | } |
| 1191 | 1187 | @ </tbody></table> |
| 1192 | 1188 | @ <p>Total number of hashes: %d(nHash)</p> |
| 1193 | 1189 | kk = 0; |
| 1194 | - for(i=UUID_SIZE; i>=4; i--){ | |
| 1190 | + for(i=HNAME_MAX; i>=4; i--){ | |
| 1195 | 1191 | if( aCollide[i].cnt==0 ) continue; |
| 1196 | 1192 | if( aCollide[i].cnt>200 ) break; |
| 1197 | 1193 | kk += aCollide[i].cnt; |
| 1198 | 1194 | if( aCollide[i].cnt<25 ){ |
| 1199 | 1195 | @ <p>Collisions of length %d(i): |
| @@ -1219,11 +1215,11 @@ | ||
| 1219 | 1215 | ** Show the number of hash collisions for hash prefixes of various lengths. |
| 1220 | 1216 | */ |
| 1221 | 1217 | void hash_collisions_webpage(void){ |
| 1222 | 1218 | login_check_credentials(); |
| 1223 | 1219 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1224 | - style_header("SHA1 Prefix Collisions"); | |
| 1220 | + style_header("Hash Prefix Collisions"); | |
| 1225 | 1221 | style_submenu_element("Activity Reports", "reports"); |
| 1226 | 1222 | style_submenu_element("Stats", "stat"); |
| 1227 | 1223 | @ <h1>Hash Prefix Collisions on Check-ins</h1> |
| 1228 | 1224 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1229 | 1225 | " FROM event WHERE event.type='ci'" |
| 1230 | 1226 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| @@ -13,15 +13,11 @@ | |
| 13 | ** [email protected] |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code used to convert user-supplied object names into |
| 19 | ** canonical UUIDs. |
| 20 | ** |
| 21 | ** A user-supplied object name is any unique prefix of a valid UUID but |
| 22 | ** not necessarily in canonical form. |
| 23 | */ |
| 24 | #include "config.h" |
| 25 | #include "name.h" |
| 26 | #include <assert.h> |
| 27 | |
| @@ -80,12 +76,12 @@ | |
| 80 | } |
| 81 | |
| 82 | /* |
| 83 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 84 | ** |
| 85 | ** * SHA1 hash |
| 86 | ** * SHA1 hash prefix of at least 4 characters |
| 87 | ** * Symbolic Name |
| 88 | ** * "tag:" + symbolic name |
| 89 | ** * Date or date-time |
| 90 | ** * "date:" + Date or date-time |
| 91 | ** * symbolic-name ":" date-time |
| @@ -105,11 +101,11 @@ | |
| 105 | ** If zType is "br" then find the first check-in of the named branch |
| 106 | ** rather than the last. |
| 107 | ** zType is "ci" in most use cases since we are usually searching for |
| 108 | ** a check-in. |
| 109 | ** |
| 110 | ** Note that the input zTag for types "t" and "e" is the SHA1 hash of |
| 111 | ** the ticket-change or event-change artifact, not the randomly generated |
| 112 | ** hexadecimal identifier assigned to tickets and events. Those identifiers |
| 113 | ** live in a separate namespace. |
| 114 | */ |
| 115 | int symbolic_name_to_rid(const char *zTag, const char *zType){ |
| @@ -232,14 +228,14 @@ | |
| 232 | zTagBase, zDate, zType |
| 233 | ); |
| 234 | return rid; |
| 235 | } |
| 236 | |
| 237 | /* SHA1 hash or prefix */ |
| 238 | if( nTag>=4 && nTag<=UUID_SIZE && validate16(zTag, nTag) ){ |
| 239 | Stmt q; |
| 240 | char zUuid[UUID_SIZE+1]; |
| 241 | memcpy(zUuid, zTag, nTag+1); |
| 242 | canonical16(zUuid, nTag); |
| 243 | rid = 0; |
| 244 | if( zType[0]=='*' ){ |
| 245 | db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid); |
| @@ -354,11 +350,11 @@ | |
| 354 | */ |
| 355 | int name_collisions(const char *zName){ |
| 356 | int c = 0; /* count of collisions for zName */ |
| 357 | int nLen; /* length of zName */ |
| 358 | nLen = strlen(zName); |
| 359 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 360 | c = db_int(0, |
| 361 | "SELECT" |
| 362 | " (SELECT count(*) FROM ticket" |
| 363 | " WHERE tkt_uuid GLOB '%q*') +" |
| 364 | " (SELECT count(*) FROM tag" |
| @@ -396,11 +392,11 @@ | |
| 396 | |
| 397 | /* |
| 398 | ** Convert a name to a rid. If the name can be any of the various forms |
| 399 | ** accepted: |
| 400 | ** |
| 401 | ** * SHA1 hash or prefix thereof |
| 402 | ** * symbolic name |
| 403 | ** * date |
| 404 | ** * label:date |
| 405 | ** * prev, previous |
| 406 | ** * next |
| @@ -425,13 +421,13 @@ | |
| 425 | return name_to_typed_rid(zName, "*"); |
| 426 | } |
| 427 | |
| 428 | /* |
| 429 | ** WEBPAGE: ambiguous |
| 430 | ** URL: /ambiguous?name=UUID&src=WEBPAGE |
| 431 | ** |
| 432 | ** The UUID given by the name parameter is ambiguous. Display a page |
| 433 | ** that shows all possible choices and let the user select between them. |
| 434 | */ |
| 435 | void ambiguous_page(void){ |
| 436 | Stmt q; |
| 437 | const char *zName = P("name"); |
| @@ -668,11 +664,11 @@ | |
| 668 | /* |
| 669 | ** COMMAND: whatis* |
| 670 | ** |
| 671 | ** Usage: %fossil whatis NAME |
| 672 | ** |
| 673 | ** Resolve the symbol NAME into its canonical 40-character SHA1-hash |
| 674 | ** artifact name and provide a description of what role that artifact |
| 675 | ** plays. |
| 676 | ** |
| 677 | ** Options: |
| 678 | ** |
| @@ -744,11 +740,11 @@ | |
| 744 | /* |
| 745 | ** COMMAND: test-ambiguous |
| 746 | ** |
| 747 | ** Usage: %fossil test-ambiguous [--minsize N] |
| 748 | ** |
| 749 | ** Show a list of ambiguous SHA1-hash abbreviations of N characters or |
| 750 | ** more where N defaults to 4. Change N to a different value using |
| 751 | ** the "--minsize N" command-line option. |
| 752 | */ |
| 753 | void test_ambiguous_cmd(void){ |
| 754 | Stmt q, ins; |
| @@ -794,11 +790,11 @@ | |
| 794 | ** Schema for the description table |
| 795 | */ |
| 796 | static const char zDescTab[] = |
| 797 | @ CREATE TEMP TABLE IF NOT EXISTS description( |
| 798 | @ rid INTEGER PRIMARY KEY, -- RID of the object |
| 799 | @ uuid TEXT, -- SHA1 hash of the object |
| 800 | @ ctime DATETIME, -- Time of creation |
| 801 | @ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts |
| 802 | @ type TEXT, -- file, checkin, wiki, ticket, etc. |
| 803 | @ summary TEXT, -- Summary comment for the object |
| 804 | @ detail TEXT -- File name, check-in comment, etc |
| @@ -1084,11 +1080,11 @@ | |
| 1084 | " WHERE description.rid=blob.rid" |
| 1085 | " ORDER BY length(content) DESC" |
| 1086 | ); |
| 1087 | @ <table cellpadding="2" cellspacing="0" border="1" id="bigblobtab"> |
| 1088 | @ <thead><tr><th align="right">Size<th align="right">RID |
| 1089 | @ <th align="right">Delta From<th>SHA1<th>Description<th>Date</tr></thead> |
| 1090 | @ <tbody> |
| 1091 | while( db_step(&q)==SQLITE_ROW ){ |
| 1092 | int rid = db_column_int(&q,0); |
| 1093 | const char *zUuid = db_column_text(&q, 1); |
| 1094 | const char *zDesc = db_column_text(&q, 2); |
| @@ -1147,33 +1143,33 @@ | |
| 1147 | |
| 1148 | /* Maximum number of collision examples to remember */ |
| 1149 | #define MAX_COLLIDE 25 |
| 1150 | |
| 1151 | /* |
| 1152 | ** Generate a report on the number of collisions in SHA1 hashes |
| 1153 | ** generated by the SQL given in the argument. |
| 1154 | */ |
| 1155 | static void collision_report(const char *zSql){ |
| 1156 | int i, j, kk; |
| 1157 | int nHash = 0; |
| 1158 | Stmt q; |
| 1159 | char zPrev[UUID_SIZE+1]; |
| 1160 | struct { |
| 1161 | int cnt; |
| 1162 | char *azHit[MAX_COLLIDE]; |
| 1163 | char z[UUID_SIZE+1]; |
| 1164 | } aCollide[UUID_SIZE+1]; |
| 1165 | memset(aCollide, 0, sizeof(aCollide)); |
| 1166 | memset(zPrev, 0, sizeof(zPrev)); |
| 1167 | db_prepare(&q,"%s",zSql/*safe-for-%s*/); |
| 1168 | while( db_step(&q)==SQLITE_ROW ){ |
| 1169 | const char *zUuid = db_column_text(&q,0); |
| 1170 | int n = db_column_bytes(&q,0); |
| 1171 | int i; |
| 1172 | nHash++; |
| 1173 | for(i=0; zPrev[i] && zPrev[i]==zUuid[i]; i++){} |
| 1174 | if( i>0 && i<=UUID_SIZE ){ |
| 1175 | if( i>=4 && aCollide[i].cnt<MAX_COLLIDE ){ |
| 1176 | aCollide[i].azHit[aCollide[i].cnt] = mprintf("%.*s", i, zPrev); |
| 1177 | } |
| 1178 | aCollide[i].cnt++; |
| 1179 | if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1); |
| @@ -1182,18 +1178,18 @@ | |
| 1182 | } |
| 1183 | db_finalize(&q); |
| 1184 | @ <table border=1><thead> |
| 1185 | @ <tr><th>Length<th>Instances<th>First Instance</tr> |
| 1186 | @ </thead><tbody> |
| 1187 | for(i=1; i<=UUID_SIZE; i++){ |
| 1188 | if( aCollide[i].cnt==0 ) continue; |
| 1189 | @ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr> |
| 1190 | } |
| 1191 | @ </tbody></table> |
| 1192 | @ <p>Total number of hashes: %d(nHash)</p> |
| 1193 | kk = 0; |
| 1194 | for(i=UUID_SIZE; i>=4; i--){ |
| 1195 | if( aCollide[i].cnt==0 ) continue; |
| 1196 | if( aCollide[i].cnt>200 ) break; |
| 1197 | kk += aCollide[i].cnt; |
| 1198 | if( aCollide[i].cnt<25 ){ |
| 1199 | @ <p>Collisions of length %d(i): |
| @@ -1219,11 +1215,11 @@ | |
| 1219 | ** Show the number of hash collisions for hash prefixes of various lengths. |
| 1220 | */ |
| 1221 | void hash_collisions_webpage(void){ |
| 1222 | login_check_credentials(); |
| 1223 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1224 | style_header("SHA1 Prefix Collisions"); |
| 1225 | style_submenu_element("Activity Reports", "reports"); |
| 1226 | style_submenu_element("Stats", "stat"); |
| 1227 | @ <h1>Hash Prefix Collisions on Check-ins</h1> |
| 1228 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1229 | " FROM event WHERE event.type='ci'" |
| 1230 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -2,11 +2,11 @@ | |
| 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | ** |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| @@ -13,15 +13,11 @@ | |
| 13 | ** [email protected] |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code used to resolved user-supplied object names. |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include "name.h" |
| 22 | #include <assert.h> |
| 23 | |
| @@ -80,12 +76,12 @@ | |
| 76 | } |
| 77 | |
| 78 | /* |
| 79 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 80 | ** |
| 81 | ** * artifact hash |
| 82 | ** * 4-character or larger prefix of a artifact |
| 83 | ** * Symbolic Name |
| 84 | ** * "tag:" + symbolic name |
| 85 | ** * Date or date-time |
| 86 | ** * "date:" + Date or date-time |
| 87 | ** * symbolic-name ":" date-time |
| @@ -105,11 +101,11 @@ | |
| 101 | ** If zType is "br" then find the first check-in of the named branch |
| 102 | ** rather than the last. |
| 103 | ** zType is "ci" in most use cases since we are usually searching for |
| 104 | ** a check-in. |
| 105 | ** |
| 106 | ** Note that the input zTag for types "t" and "e" is the artifact hash of |
| 107 | ** the ticket-change or event-change artifact, not the randomly generated |
| 108 | ** hexadecimal identifier assigned to tickets and events. Those identifiers |
| 109 | ** live in a separate namespace. |
| 110 | */ |
| 111 | int symbolic_name_to_rid(const char *zTag, const char *zType){ |
| @@ -232,14 +228,14 @@ | |
| 228 | zTagBase, zDate, zType |
| 229 | ); |
| 230 | return rid; |
| 231 | } |
| 232 | |
| 233 | /* artifact hash or prefix */ |
| 234 | if( nTag>=4 && nTag<=HNAME_MAX && validate16(zTag, nTag) ){ |
| 235 | Stmt q; |
| 236 | char zUuid[HNAME_MAX+1]; |
| 237 | memcpy(zUuid, zTag, nTag+1); |
| 238 | canonical16(zUuid, nTag); |
| 239 | rid = 0; |
| 240 | if( zType[0]=='*' ){ |
| 241 | db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid); |
| @@ -354,11 +350,11 @@ | |
| 350 | */ |
| 351 | int name_collisions(const char *zName){ |
| 352 | int c = 0; /* count of collisions for zName */ |
| 353 | int nLen; /* length of zName */ |
| 354 | nLen = strlen(zName); |
| 355 | if( nLen>=4 && nLen<=HNAME_MAX && validate16(zName, nLen) ){ |
| 356 | c = db_int(0, |
| 357 | "SELECT" |
| 358 | " (SELECT count(*) FROM ticket" |
| 359 | " WHERE tkt_uuid GLOB '%q*') +" |
| 360 | " (SELECT count(*) FROM tag" |
| @@ -396,11 +392,11 @@ | |
| 392 | |
| 393 | /* |
| 394 | ** Convert a name to a rid. If the name can be any of the various forms |
| 395 | ** accepted: |
| 396 | ** |
| 397 | ** * artifact hash or prefix thereof |
| 398 | ** * symbolic name |
| 399 | ** * date |
| 400 | ** * label:date |
| 401 | ** * prev, previous |
| 402 | ** * next |
| @@ -425,13 +421,13 @@ | |
| 421 | return name_to_typed_rid(zName, "*"); |
| 422 | } |
| 423 | |
| 424 | /* |
| 425 | ** WEBPAGE: ambiguous |
| 426 | ** URL: /ambiguous?name=NAME&src=WEBPAGE |
| 427 | ** |
| 428 | ** The NAME given by the name parameter is ambiguous. Display a page |
| 429 | ** that shows all possible choices and let the user select between them. |
| 430 | */ |
| 431 | void ambiguous_page(void){ |
| 432 | Stmt q; |
| 433 | const char *zName = P("name"); |
| @@ -668,11 +664,11 @@ | |
| 664 | /* |
| 665 | ** COMMAND: whatis* |
| 666 | ** |
| 667 | ** Usage: %fossil whatis NAME |
| 668 | ** |
| 669 | ** Resolve the symbol NAME into its canonical artifact hash |
| 670 | ** artifact name and provide a description of what role that artifact |
| 671 | ** plays. |
| 672 | ** |
| 673 | ** Options: |
| 674 | ** |
| @@ -744,11 +740,11 @@ | |
| 740 | /* |
| 741 | ** COMMAND: test-ambiguous |
| 742 | ** |
| 743 | ** Usage: %fossil test-ambiguous [--minsize N] |
| 744 | ** |
| 745 | ** Show a list of ambiguous artifact hash abbreviations of N characters or |
| 746 | ** more where N defaults to 4. Change N to a different value using |
| 747 | ** the "--minsize N" command-line option. |
| 748 | */ |
| 749 | void test_ambiguous_cmd(void){ |
| 750 | Stmt q, ins; |
| @@ -794,11 +790,11 @@ | |
| 790 | ** Schema for the description table |
| 791 | */ |
| 792 | static const char zDescTab[] = |
| 793 | @ CREATE TEMP TABLE IF NOT EXISTS description( |
| 794 | @ rid INTEGER PRIMARY KEY, -- RID of the object |
| 795 | @ uuid TEXT, -- hash of the object |
| 796 | @ ctime DATETIME, -- Time of creation |
| 797 | @ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts |
| 798 | @ type TEXT, -- file, checkin, wiki, ticket, etc. |
| 799 | @ summary TEXT, -- Summary comment for the object |
| 800 | @ detail TEXT -- File name, check-in comment, etc |
| @@ -1084,11 +1080,11 @@ | |
| 1080 | " WHERE description.rid=blob.rid" |
| 1081 | " ORDER BY length(content) DESC" |
| 1082 | ); |
| 1083 | @ <table cellpadding="2" cellspacing="0" border="1" id="bigblobtab"> |
| 1084 | @ <thead><tr><th align="right">Size<th align="right">RID |
| 1085 | @ <th align="right">Delta From<th>Hash<th>Description<th>Date</tr></thead> |
| 1086 | @ <tbody> |
| 1087 | while( db_step(&q)==SQLITE_ROW ){ |
| 1088 | int rid = db_column_int(&q,0); |
| 1089 | const char *zUuid = db_column_text(&q, 1); |
| 1090 | const char *zDesc = db_column_text(&q, 2); |
| @@ -1147,33 +1143,33 @@ | |
| 1143 | |
| 1144 | /* Maximum number of collision examples to remember */ |
| 1145 | #define MAX_COLLIDE 25 |
| 1146 | |
| 1147 | /* |
| 1148 | ** Generate a report on the number of collisions in artifact hashes |
| 1149 | ** generated by the SQL given in the argument. |
| 1150 | */ |
| 1151 | static void collision_report(const char *zSql){ |
| 1152 | int i, j, kk; |
| 1153 | int nHash = 0; |
| 1154 | Stmt q; |
| 1155 | char zPrev[HNAME_MAX+1]; |
| 1156 | struct { |
| 1157 | int cnt; |
| 1158 | char *azHit[MAX_COLLIDE]; |
| 1159 | char z[HNAME_MAX+1]; |
| 1160 | } aCollide[HNAME_MAX+1]; |
| 1161 | memset(aCollide, 0, sizeof(aCollide)); |
| 1162 | memset(zPrev, 0, sizeof(zPrev)); |
| 1163 | db_prepare(&q,"%s",zSql/*safe-for-%s*/); |
| 1164 | while( db_step(&q)==SQLITE_ROW ){ |
| 1165 | const char *zUuid = db_column_text(&q,0); |
| 1166 | int n = db_column_bytes(&q,0); |
| 1167 | int i; |
| 1168 | nHash++; |
| 1169 | for(i=0; zPrev[i] && zPrev[i]==zUuid[i]; i++){} |
| 1170 | if( i>0 && i<=HNAME_MAX ){ |
| 1171 | if( i>=4 && aCollide[i].cnt<MAX_COLLIDE ){ |
| 1172 | aCollide[i].azHit[aCollide[i].cnt] = mprintf("%.*s", i, zPrev); |
| 1173 | } |
| 1174 | aCollide[i].cnt++; |
| 1175 | if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1); |
| @@ -1182,18 +1178,18 @@ | |
| 1178 | } |
| 1179 | db_finalize(&q); |
| 1180 | @ <table border=1><thead> |
| 1181 | @ <tr><th>Length<th>Instances<th>First Instance</tr> |
| 1182 | @ </thead><tbody> |
| 1183 | for(i=1; i<=HNAME_MAX; i++){ |
| 1184 | if( aCollide[i].cnt==0 ) continue; |
| 1185 | @ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr> |
| 1186 | } |
| 1187 | @ </tbody></table> |
| 1188 | @ <p>Total number of hashes: %d(nHash)</p> |
| 1189 | kk = 0; |
| 1190 | for(i=HNAME_MAX; i>=4; i--){ |
| 1191 | if( aCollide[i].cnt==0 ) continue; |
| 1192 | if( aCollide[i].cnt>200 ) break; |
| 1193 | kk += aCollide[i].cnt; |
| 1194 | if( aCollide[i].cnt<25 ){ |
| 1195 | @ <p>Collisions of length %d(i): |
| @@ -1219,11 +1215,11 @@ | |
| 1215 | ** Show the number of hash collisions for hash prefixes of various lengths. |
| 1216 | */ |
| 1217 | void hash_collisions_webpage(void){ |
| 1218 | login_check_credentials(); |
| 1219 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1220 | style_header("Hash Prefix Collisions"); |
| 1221 | style_submenu_element("Activity Reports", "reports"); |
| 1222 | style_submenu_element("Stats", "stat"); |
| 1223 | @ <h1>Hash Prefix Collisions on Check-ins</h1> |
| 1224 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1225 | " FROM event WHERE event.type='ci'" |
| 1226 |
+2
-2
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -24,11 +24,11 @@ | ||
| 24 | 24 | # include <io.h> |
| 25 | 25 | # include <fcntl.h> |
| 26 | 26 | #endif |
| 27 | 27 | #include <time.h> |
| 28 | 28 | |
| 29 | -/* Two custom conversions are used to show a prefix of SHA1 hashes: | |
| 29 | +/* Two custom conversions are used to show a prefix of artifact hashes: | |
| 30 | 30 | ** |
| 31 | 31 | ** %!S Prefix of a length appropriate for URLs |
| 32 | 32 | ** %S Prefix of a length appropriate for human display |
| 33 | 33 | ** |
| 34 | 34 | ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS |
| @@ -44,11 +44,11 @@ | ||
| 44 | 44 | #ifndef FOSSIL_HASH_DIGITS_URL |
| 45 | 45 | # define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */ |
| 46 | 46 | #endif |
| 47 | 47 | |
| 48 | 48 | /* |
| 49 | -** Return the number of SHA1 hash digits to display. The number is for | |
| 49 | +** Return the number of artifact hash digits to display. The number is for | |
| 50 | 50 | ** human output if the bForUrl is false and is destined for a URL if |
| 51 | 51 | ** bForUrl is false. |
| 52 | 52 | */ |
| 53 | 53 | static int hashDigits(int bForUrl){ |
| 54 | 54 | static int nDigitHuman = 0; |
| 55 | 55 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -24,11 +24,11 @@ | |
| 24 | # include <io.h> |
| 25 | # include <fcntl.h> |
| 26 | #endif |
| 27 | #include <time.h> |
| 28 | |
| 29 | /* Two custom conversions are used to show a prefix of SHA1 hashes: |
| 30 | ** |
| 31 | ** %!S Prefix of a length appropriate for URLs |
| 32 | ** %S Prefix of a length appropriate for human display |
| 33 | ** |
| 34 | ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS |
| @@ -44,11 +44,11 @@ | |
| 44 | #ifndef FOSSIL_HASH_DIGITS_URL |
| 45 | # define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */ |
| 46 | #endif |
| 47 | |
| 48 | /* |
| 49 | ** Return the number of SHA1 hash digits to display. The number is for |
| 50 | ** human output if the bForUrl is false and is destined for a URL if |
| 51 | ** bForUrl is false. |
| 52 | */ |
| 53 | static int hashDigits(int bForUrl){ |
| 54 | static int nDigitHuman = 0; |
| 55 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -24,11 +24,11 @@ | |
| 24 | # include <io.h> |
| 25 | # include <fcntl.h> |
| 26 | #endif |
| 27 | #include <time.h> |
| 28 | |
| 29 | /* Two custom conversions are used to show a prefix of artifact hashes: |
| 30 | ** |
| 31 | ** %!S Prefix of a length appropriate for URLs |
| 32 | ** %S Prefix of a length appropriate for human display |
| 33 | ** |
| 34 | ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS |
| @@ -44,11 +44,11 @@ | |
| 44 | #ifndef FOSSIL_HASH_DIGITS_URL |
| 45 | # define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */ |
| 46 | #endif |
| 47 | |
| 48 | /* |
| 49 | ** Return the number of artifact hash digits to display. The number is for |
| 50 | ** human output if the bForUrl is false and is destined for a URL if |
| 51 | ** bForUrl is false. |
| 52 | */ |
| 53 | static int hashDigits(int bForUrl){ |
| 54 | static int nDigitHuman = 0; |
| 55 |
+7
-13
| --- src/purge.c | ||
| +++ src/purge.c | ||
| @@ -43,11 +43,11 @@ | ||
| 43 | 43 | @ ); |
| 44 | 44 | @ CREATE TABLE IF NOT EXISTS "%w".purgeitem( |
| 45 | 45 | @ piid INTEGER PRIMARY KEY, -- ID for the purge item |
| 46 | 46 | @ peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event |
| 47 | 47 | @ orid INTEGER, -- Original RID before purged |
| 48 | -@ uuid TEXT NOT NULL, -- SHA1 hash of the purged artifact | |
| 48 | +@ uuid TEXT NOT NULL, -- hash of the purged artifact | |
| 49 | 49 | @ srcid INTEGER, -- Basis purgeitem for delta compression |
| 50 | 50 | @ isPrivate BOOLEAN, -- True if artifact was originally private |
| 51 | 51 | @ sz INT NOT NULL, -- Uncompressed size of the purged artifact |
| 52 | 52 | @ desc TEXT, -- Brief description of this artifact |
| 53 | 53 | @ data BLOB -- Compressed artifact content |
| @@ -347,11 +347,11 @@ | ||
| 347 | 347 | int piid, /* ID of the item to extract */ |
| 348 | 348 | Blob *pOut /* Write the content into this blob */ |
| 349 | 349 | ){ |
| 350 | 350 | Stmt q; |
| 351 | 351 | int srcid; |
| 352 | - Blob h1, h2, x; | |
| 352 | + Blob h1, x; | |
| 353 | 353 | static Bag busy; |
| 354 | 354 | |
| 355 | 355 | db_prepare(&q, "SELECT uuid, srcid, data FROM purgeitem" |
| 356 | 356 | " WHERE piid=%d", piid); |
| 357 | 357 | if( db_step(&q)!=SQLITE_ROW ){ |
| @@ -376,17 +376,14 @@ | ||
| 376 | 376 | blob_reset(&baseline); |
| 377 | 377 | } |
| 378 | 378 | bag_remove(&busy, piid); |
| 379 | 379 | blob_zero(&h1); |
| 380 | 380 | db_column_blob(&q, 0, &h1); |
| 381 | - sha1sum_blob(pOut, &h2); | |
| 382 | - if( blob_compare(&h1, &h2)!=0 ){ | |
| 383 | - fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", | |
| 384 | - blob_str(&h1), blob_str(&h2)); | |
| 381 | + if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){ | |
| 382 | + fossil_fatal("incorrect artifact hash on %b", &h1); | |
| 385 | 383 | } |
| 386 | 384 | blob_reset(&h1); |
| 387 | - blob_reset(&h2); | |
| 388 | 385 | db_finalize(&q); |
| 389 | 386 | return 0; |
| 390 | 387 | } |
| 391 | 388 | |
| 392 | 389 | /* |
| @@ -411,11 +408,11 @@ | ||
| 411 | 408 | " WHERE ix.srcid=%d" |
| 412 | 409 | " AND ix.piid=purgeitem.piid;", |
| 413 | 410 | iSrc |
| 414 | 411 | ); |
| 415 | 412 | while( db_step(&q)==SQLITE_ROW ){ |
| 416 | - Blob h1, h2, c1, c2; | |
| 413 | + Blob h1, c1, c2; | |
| 417 | 414 | int isPriv, rid; |
| 418 | 415 | blob_zero(&h1); |
| 419 | 416 | db_column_blob(&q, 0, &h1); |
| 420 | 417 | blob_zero(&c1); |
| 421 | 418 | db_column_blob(&q, 1, &c1); |
| @@ -425,16 +422,13 @@ | ||
| 425 | 422 | blob_delta_apply(pBasis, &c1, &c2); |
| 426 | 423 | blob_reset(&c1); |
| 427 | 424 | }else{ |
| 428 | 425 | c2 = c1; |
| 429 | 426 | } |
| 430 | - sha1sum_blob(&c2, &h2); | |
| 431 | - if( blob_compare(&h1, &h2)!=0 ){ | |
| 432 | - fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", | |
| 433 | - blob_str(&h1), blob_str(&h2)); | |
| 427 | + if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){ | |
| 428 | + fossil_fatal("incorrect hash on %b", &h1); | |
| 434 | 429 | } |
| 435 | - blob_reset(&h2); | |
| 436 | 430 | isPriv = db_column_int(&q, 2); |
| 437 | 431 | rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv); |
| 438 | 432 | if( rid==0 ){ |
| 439 | 433 | fossil_fatal("%s", g.zErrMsg); |
| 440 | 434 | }else{ |
| 441 | 435 |
| --- src/purge.c | |
| +++ src/purge.c | |
| @@ -43,11 +43,11 @@ | |
| 43 | @ ); |
| 44 | @ CREATE TABLE IF NOT EXISTS "%w".purgeitem( |
| 45 | @ piid INTEGER PRIMARY KEY, -- ID for the purge item |
| 46 | @ peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event |
| 47 | @ orid INTEGER, -- Original RID before purged |
| 48 | @ uuid TEXT NOT NULL, -- SHA1 hash of the purged artifact |
| 49 | @ srcid INTEGER, -- Basis purgeitem for delta compression |
| 50 | @ isPrivate BOOLEAN, -- True if artifact was originally private |
| 51 | @ sz INT NOT NULL, -- Uncompressed size of the purged artifact |
| 52 | @ desc TEXT, -- Brief description of this artifact |
| 53 | @ data BLOB -- Compressed artifact content |
| @@ -347,11 +347,11 @@ | |
| 347 | int piid, /* ID of the item to extract */ |
| 348 | Blob *pOut /* Write the content into this blob */ |
| 349 | ){ |
| 350 | Stmt q; |
| 351 | int srcid; |
| 352 | Blob h1, h2, x; |
| 353 | static Bag busy; |
| 354 | |
| 355 | db_prepare(&q, "SELECT uuid, srcid, data FROM purgeitem" |
| 356 | " WHERE piid=%d", piid); |
| 357 | if( db_step(&q)!=SQLITE_ROW ){ |
| @@ -376,17 +376,14 @@ | |
| 376 | blob_reset(&baseline); |
| 377 | } |
| 378 | bag_remove(&busy, piid); |
| 379 | blob_zero(&h1); |
| 380 | db_column_blob(&q, 0, &h1); |
| 381 | sha1sum_blob(pOut, &h2); |
| 382 | if( blob_compare(&h1, &h2)!=0 ){ |
| 383 | fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", |
| 384 | blob_str(&h1), blob_str(&h2)); |
| 385 | } |
| 386 | blob_reset(&h1); |
| 387 | blob_reset(&h2); |
| 388 | db_finalize(&q); |
| 389 | return 0; |
| 390 | } |
| 391 | |
| 392 | /* |
| @@ -411,11 +408,11 @@ | |
| 411 | " WHERE ix.srcid=%d" |
| 412 | " AND ix.piid=purgeitem.piid;", |
| 413 | iSrc |
| 414 | ); |
| 415 | while( db_step(&q)==SQLITE_ROW ){ |
| 416 | Blob h1, h2, c1, c2; |
| 417 | int isPriv, rid; |
| 418 | blob_zero(&h1); |
| 419 | db_column_blob(&q, 0, &h1); |
| 420 | blob_zero(&c1); |
| 421 | db_column_blob(&q, 1, &c1); |
| @@ -425,16 +422,13 @@ | |
| 425 | blob_delta_apply(pBasis, &c1, &c2); |
| 426 | blob_reset(&c1); |
| 427 | }else{ |
| 428 | c2 = c1; |
| 429 | } |
| 430 | sha1sum_blob(&c2, &h2); |
| 431 | if( blob_compare(&h1, &h2)!=0 ){ |
| 432 | fossil_fatal("SHA1 hash mismatch - wanted %s, got %s", |
| 433 | blob_str(&h1), blob_str(&h2)); |
| 434 | } |
| 435 | blob_reset(&h2); |
| 436 | isPriv = db_column_int(&q, 2); |
| 437 | rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv); |
| 438 | if( rid==0 ){ |
| 439 | fossil_fatal("%s", g.zErrMsg); |
| 440 | }else{ |
| 441 |
| --- src/purge.c | |
| +++ src/purge.c | |
| @@ -43,11 +43,11 @@ | |
| 43 | @ ); |
| 44 | @ CREATE TABLE IF NOT EXISTS "%w".purgeitem( |
| 45 | @ piid INTEGER PRIMARY KEY, -- ID for the purge item |
| 46 | @ peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event |
| 47 | @ orid INTEGER, -- Original RID before purged |
| 48 | @ uuid TEXT NOT NULL, -- hash of the purged artifact |
| 49 | @ srcid INTEGER, -- Basis purgeitem for delta compression |
| 50 | @ isPrivate BOOLEAN, -- True if artifact was originally private |
| 51 | @ sz INT NOT NULL, -- Uncompressed size of the purged artifact |
| 52 | @ desc TEXT, -- Brief description of this artifact |
| 53 | @ data BLOB -- Compressed artifact content |
| @@ -347,11 +347,11 @@ | |
| 347 | int piid, /* ID of the item to extract */ |
| 348 | Blob *pOut /* Write the content into this blob */ |
| 349 | ){ |
| 350 | Stmt q; |
| 351 | int srcid; |
| 352 | Blob h1, x; |
| 353 | static Bag busy; |
| 354 | |
| 355 | db_prepare(&q, "SELECT uuid, srcid, data FROM purgeitem" |
| 356 | " WHERE piid=%d", piid); |
| 357 | if( db_step(&q)!=SQLITE_ROW ){ |
| @@ -376,17 +376,14 @@ | |
| 376 | blob_reset(&baseline); |
| 377 | } |
| 378 | bag_remove(&busy, piid); |
| 379 | blob_zero(&h1); |
| 380 | db_column_blob(&q, 0, &h1); |
| 381 | if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){ |
| 382 | fossil_fatal("incorrect artifact hash on %b", &h1); |
| 383 | } |
| 384 | blob_reset(&h1); |
| 385 | db_finalize(&q); |
| 386 | return 0; |
| 387 | } |
| 388 | |
| 389 | /* |
| @@ -411,11 +408,11 @@ | |
| 408 | " WHERE ix.srcid=%d" |
| 409 | " AND ix.piid=purgeitem.piid;", |
| 410 | iSrc |
| 411 | ); |
| 412 | while( db_step(&q)==SQLITE_ROW ){ |
| 413 | Blob h1, c1, c2; |
| 414 | int isPriv, rid; |
| 415 | blob_zero(&h1); |
| 416 | db_column_blob(&q, 0, &h1); |
| 417 | blob_zero(&c1); |
| 418 | db_column_blob(&q, 1, &c1); |
| @@ -425,16 +422,13 @@ | |
| 422 | blob_delta_apply(pBasis, &c1, &c2); |
| 423 | blob_reset(&c1); |
| 424 | }else{ |
| 425 | c2 = c1; |
| 426 | } |
| 427 | if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){ |
| 428 | fossil_fatal("incorrect hash on %b", &h1); |
| 429 | } |
| 430 | isPriv = db_column_int(&q, 2); |
| 431 | rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv); |
| 432 | if( rid==0 ){ |
| 433 | fossil_fatal("%s", g.zErrMsg); |
| 434 | }else{ |
| 435 |
+106
-94
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -21,76 +21,41 @@ | ||
| 21 | 21 | #include "rebuild.h" |
| 22 | 22 | #include <assert.h> |
| 23 | 23 | #include <errno.h> |
| 24 | 24 | |
| 25 | 25 | /* |
| 26 | -** Make changes to the stable part of the schema (the part that is not | |
| 27 | -** simply deleted and reconstructed on a rebuild) to bring the schema | |
| 28 | -** up to the latest. | |
| 26 | +** Update the schema as necessary | |
| 29 | 27 | */ |
| 30 | -static const char zSchemaUpdates1[] = | |
| 31 | -@ -- Index on the delta table | |
| 32 | -@ -- | |
| 33 | -@ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid); | |
| 34 | -@ | |
| 35 | -@ -- Artifacts that should not be processed are identified in the | |
| 36 | -@ -- "shun" table. Artifacts that are control-file forgeries or | |
| 37 | -@ -- spam or artifacts whose contents violate administrative policy | |
| 38 | -@ -- can be shunned in order to prevent them from contaminating | |
| 39 | -@ -- the repository. | |
| 40 | -@ -- | |
| 41 | -@ -- Shunned artifacts do not exist in the blob table. Hence they | |
| 42 | -@ -- have not artifact ID (rid) and we thus must store their full | |
| 43 | -@ -- UUID. | |
| 44 | -@ -- | |
| 45 | -@ CREATE TABLE IF NOT EXISTS shun( | |
| 46 | -@ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form | |
| 47 | -@ mtime INTEGER, -- When added. Seconds since 1970 | |
| 48 | -@ scom TEXT -- Optional text explaining why the shun occurred | |
| 49 | -@ ); | |
| 50 | -@ | |
| 51 | -@ -- Artifacts that should not be pushed are stored in the "private" | |
| 52 | -@ -- table. | |
| 53 | -@ -- | |
| 54 | -@ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY); | |
| 55 | -@ | |
| 56 | -@ -- Some ticket content (such as the originators email address or contact | |
| 57 | -@ -- information) needs to be obscured to protect privacy. This is achieved | |
| 58 | -@ -- by storing an SHA1 hash of the content. For display, the hash is | |
| 59 | -@ -- mapped back into the original text using this table. | |
| 60 | -@ -- | |
| 61 | -@ -- This table contains sensitive information and should not be shared | |
| 62 | -@ -- with unauthorized users. | |
| 63 | -@ -- | |
| 64 | -@ CREATE TABLE IF NOT EXISTS concealed( | |
| 65 | -@ hash TEXT PRIMARY KEY, -- The SHA1 hash of content | |
| 66 | -@ mtime INTEGER, -- Time created. Seconds since 1970 | |
| 67 | -@ content TEXT -- Content intended to be concealed | |
| 68 | -@ ); | |
| 69 | -; | |
| 70 | -static const char zSchemaUpdates2[] = | |
| 71 | -@ -- An entry in this table describes a database query that generates a | |
| 72 | -@ -- table of tickets. | |
| 73 | -@ -- | |
| 74 | -@ CREATE TABLE IF NOT EXISTS reportfmt( | |
| 75 | -@ rn INTEGER PRIMARY KEY, -- Report number | |
| 76 | -@ owner TEXT, -- Owner of this report format (not used) | |
| 77 | -@ title TEXT UNIQUE, -- Title of this report | |
| 78 | -@ mtime INTEGER, -- Time last modified. Seconds since 1970 | |
| 79 | -@ cols TEXT, -- A color-key specification | |
| 80 | -@ sqlcode TEXT -- An SQL SELECT statement for this report | |
| 81 | -@ ); | |
| 82 | -; | |
| 83 | - | |
| 84 | 28 | static void rebuild_update_schema(void){ |
| 85 | - int rc; | |
| 86 | - db_multi_exec("%s", zSchemaUpdates1 /*safe-for-%s*/); | |
| 87 | - db_multi_exec("%s", zSchemaUpdates2 /*safe-for-%s*/); | |
| 29 | + /* Verify that the PLINK table has a new column added by the | |
| 30 | + ** 2014-11-28 schema change. Create it if necessary. This code | |
| 31 | + ** can be removed in the future, once all users have upgraded to the | |
| 32 | + ** 2014-11-28 or later schema. | |
| 33 | + */ | |
| 34 | + if( !db_table_has_column("repository","plink","baseid") ){ | |
| 35 | + db_multi_exec( | |
| 36 | + "ALTER TABLE repository.plink ADD COLUMN baseid;" | |
| 37 | + ); | |
| 38 | + } | |
| 39 | + | |
| 40 | + /* Verify that the MLINK table has the newer columns added by the | |
| 41 | + ** 2015-01-24 schema change. Create them if necessary. This code | |
| 42 | + ** can be removed in the future, once all users have upgraded to the | |
| 43 | + ** 2015-01-24 or later schema. | |
| 44 | + */ | |
| 45 | + if( !db_table_has_column("repository","mlink","isaux") ){ | |
| 46 | + db_begin_transaction(); | |
| 47 | + db_multi_exec( | |
| 48 | + "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;" | |
| 49 | + "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;" | |
| 50 | + ); | |
| 51 | + db_end_transaction(0); | |
| 52 | + } | |
| 88 | 53 | |
| 89 | - rc = db_exists("SELECT 1 FROM sqlite_master" | |
| 90 | - " WHERE name='user' AND sql GLOB '* mtime *'"); | |
| 91 | - if( rc==0 ){ | |
| 54 | + /* Add the user.mtime column if it is missing. (2011-04-27) | |
| 55 | + */ | |
| 56 | + if( !db_table_has_column("repository", "user", "mtime") ){ | |
| 92 | 57 | db_multi_exec( |
| 93 | 58 | "CREATE TEMP TABLE temp_user AS SELECT * FROM user;" |
| 94 | 59 | "DROP TABLE user;" |
| 95 | 60 | "CREATE TABLE user(\n" |
| 96 | 61 | " uid INTEGER PRIMARY KEY,\n" |
| @@ -109,54 +74,99 @@ | ||
| 109 | 74 | " ipaddr, cexpire, info, now(), photo FROM temp_user;" |
| 110 | 75 | "DROP TABLE temp_user;" |
| 111 | 76 | ); |
| 112 | 77 | } |
| 113 | 78 | |
| 114 | - rc = db_exists("SELECT 1 FROM sqlite_master" | |
| 115 | - " WHERE name='config' AND sql GLOB '* mtime *'"); | |
| 116 | - if( rc==0 ){ | |
| 79 | + /* Add the config.mtime column if it is missing. (2011-04-27) | |
| 80 | + */ | |
| 81 | + if( !db_table_has_column("repository", "config", "mtime") ){ | |
| 117 | 82 | db_multi_exec( |
| 118 | 83 | "ALTER TABLE config ADD COLUMN mtime INTEGER;" |
| 119 | 84 | "UPDATE config SET mtime=now();" |
| 120 | 85 | ); |
| 121 | 86 | } |
| 122 | 87 | |
| 123 | - rc = db_exists("SELECT 1 FROM sqlite_master" | |
| 124 | - " WHERE name='shun' AND sql GLOB '* mtime *'"); | |
| 125 | - if( rc==0 ){ | |
| 88 | + /* Add the shun.mtime and shun.scom columns if they are missing. | |
| 89 | + ** (2011-04-27) | |
| 90 | + */ | |
| 91 | + if( !db_table_has_column("repository", "shun", "mtime") ){ | |
| 126 | 92 | db_multi_exec( |
| 127 | 93 | "ALTER TABLE shun ADD COLUMN mtime INTEGER;" |
| 128 | 94 | "ALTER TABLE shun ADD COLUMN scom TEXT;" |
| 129 | 95 | "UPDATE shun SET mtime=now();" |
| 130 | 96 | ); |
| 131 | 97 | } |
| 132 | 98 | |
| 133 | - rc = db_exists("SELECT 1 FROM sqlite_master" | |
| 134 | - " WHERE name='reportfmt' AND sql GLOB '* mtime *'"); | |
| 135 | - if( rc==0 ){ | |
| 99 | + /* Add the reportfmt.mtime column if it is missing. (2011-04-27) | |
| 100 | + */ | |
| 101 | + if( !db_table_has_column("repository", "reportfmt", "mtime") ){ | |
| 102 | + static const char zCreateReportFmtTable[] = | |
| 103 | + @ -- An entry in this table describes a database query that generates a | |
| 104 | + @ -- table of tickets. | |
| 105 | + @ -- | |
| 106 | + @ CREATE TABLE IF NOT EXISTS reportfmt( | |
| 107 | + @ rn INTEGER PRIMARY KEY, -- Report number | |
| 108 | + @ owner TEXT, -- Owner of this report format (not used) | |
| 109 | + @ title TEXT UNIQUE, -- Title of this report | |
| 110 | + @ mtime INTEGER, -- Time last modified. Seconds since 1970 | |
| 111 | + @ cols TEXT, -- A color-key specification | |
| 112 | + @ sqlcode TEXT -- An SQL SELECT statement for this report | |
| 113 | + @ ); | |
| 114 | + ; | |
| 136 | 115 | db_multi_exec( |
| 137 | 116 | "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;" |
| 138 | 117 | "DROP TABLE reportfmt;" |
| 139 | 118 | ); |
| 140 | - db_multi_exec("%s", zSchemaUpdates2/*safe-for-%s*/); | |
| 119 | + db_multi_exec("%s", zCreateReportFmtTable/*safe-for-%s*/); | |
| 141 | 120 | db_multi_exec( |
| 142 | 121 | "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)" |
| 143 | 122 | " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;" |
| 144 | 123 | "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)" |
| 145 | 124 | " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()" |
| 146 | 125 | " FROM old_fmt;" |
| 147 | 126 | ); |
| 148 | 127 | } |
| 149 | 128 | |
| 150 | - rc = db_exists("SELECT 1 FROM sqlite_master" | |
| 151 | - " WHERE name='concealed' AND sql GLOB '* mtime *'"); | |
| 152 | - if( rc==0 ){ | |
| 129 | + /* Add the concealed.mtime column if it is missing. (2011-04-27) | |
| 130 | + */ | |
| 131 | + if( !db_table_has_column("repository", "concealed", "mtime") ){ | |
| 153 | 132 | db_multi_exec( |
| 154 | 133 | "ALTER TABLE concealed ADD COLUMN mtime INTEGER;" |
| 155 | 134 | "UPDATE concealed SET mtime=now();" |
| 156 | 135 | ); |
| 157 | 136 | } |
| 137 | + | |
| 138 | + /* Do the fossil-2.0 updates to the schema. (2017-02-28) | |
| 139 | + */ | |
| 140 | + rebuild_schema_update_2_0(); | |
| 141 | +} | |
| 142 | + | |
| 143 | +/* | |
| 144 | +** Update the repository schema for Fossil version 2.0. (2017-02-28) | |
| 145 | +** (1) Change the CHECK constraint on BLOB.UUID so that the length | |
| 146 | +** is greater than or equal to 40, not exactly equal to 40. | |
| 147 | +*/ | |
| 148 | +void rebuild_schema_update_2_0(void){ | |
| 149 | + char *z = db_text(0, "SELECT sql FROM repository.sqlite_master WHERE name='blob'"); | |
| 150 | + if( z ){ | |
| 151 | + /* Search for: length(uuid)==40 | |
| 152 | + ** 0123456789 12345 */ | |
| 153 | + int i; | |
| 154 | + for(i=10; z[i]; i++){ | |
| 155 | + if( z[i]=='=' && strncmp(&z[i-6],"(uuid)==40",10)==0 ){ | |
| 156 | + z[i] = '>'; | |
| 157 | + db_multi_exec( | |
| 158 | + "PRAGMA writable_schema=ON;" | |
| 159 | + "UPDATE repository.sqlite_master SET sql=%Q WHERE name LIKE 'blob';" | |
| 160 | + "PRAGMA writable_schema=OFF;", | |
| 161 | + z | |
| 162 | + ); | |
| 163 | + break; | |
| 164 | + } | |
| 165 | + } | |
| 166 | + fossil_free(z); | |
| 167 | + } | |
| 158 | 168 | } |
| 159 | 169 | |
| 160 | 170 | /* |
| 161 | 171 | ** Variables used to store state information about an on-going "rebuild" |
| 162 | 172 | ** or "deconstruct". |
| @@ -330,37 +340,39 @@ | ||
| 330 | 340 | ** extracted in a random order. This feature is used to test the |
| 331 | 341 | ** ability of fossil to accept records in any order and still |
| 332 | 342 | ** construct a sane repository. |
| 333 | 343 | */ |
| 334 | 344 | int rebuild_db(int randomize, int doOut, int doClustering){ |
| 335 | - Stmt s; | |
| 345 | + Stmt s, q; | |
| 336 | 346 | int errCnt = 0; |
| 337 | - char *zTable; | |
| 338 | 347 | int incrSize; |
| 348 | + Blob sql; | |
| 339 | 349 | |
| 340 | 350 | bag_init(&bagDone); |
| 341 | 351 | ttyOutput = doOut; |
| 342 | 352 | processCnt = 0; |
| 343 | 353 | if (ttyOutput && !g.fQuiet) { |
| 344 | 354 | percent_complete(0); |
| 345 | 355 | } |
| 346 | 356 | rebuild_update_schema(); |
| 347 | - for(;;){ | |
| 348 | - zTable = db_text(0, | |
| 349 | - "SELECT name FROM sqlite_master /*scan*/" | |
| 350 | - " WHERE type='table'" | |
| 351 | - " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user'," | |
| 352 | - "'config','shun','private','reportfmt'," | |
| 353 | - "'concealed','accesslog','modreq'," | |
| 354 | - "'purgeevent','purgeitem','unversioned')" | |
| 355 | - " AND name NOT GLOB 'sqlite_*'" | |
| 356 | - " AND name NOT GLOB 'fx_*'" | |
| 357 | - ); | |
| 358 | - if( zTable==0 ) break; | |
| 359 | - db_multi_exec("DROP TABLE %Q", zTable); | |
| 360 | - free(zTable); | |
| 361 | - } | |
| 357 | + blob_init(&sql, 0, 0); | |
| 358 | + db_prepare(&q, | |
| 359 | + "SELECT name FROM sqlite_master /*scan*/" | |
| 360 | + " WHERE type='table'" | |
| 361 | + " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias'," | |
| 362 | + "'config','shun','private','reportfmt'," | |
| 363 | + "'concealed','accesslog','modreq'," | |
| 364 | + "'purgeevent','purgeitem','unversioned')" | |
| 365 | + " AND name NOT GLOB 'sqlite_*'" | |
| 366 | + " AND name NOT GLOB 'fx_*'" | |
| 367 | + ); | |
| 368 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 369 | + blob_appendf(&sql, "DROP TABLE \"%w\";\n", db_column_text(&q,0)); | |
| 370 | + } | |
| 371 | + db_finalize(&q); | |
| 372 | + db_multi_exec("%s", blob_str(&sql)/*safe-for-%s*/); | |
| 373 | + blob_reset(&sql); | |
| 362 | 374 | db_multi_exec("%s", zRepositorySchema2/*safe-for-%s*/); |
| 363 | 375 | ticket_create_table(0); |
| 364 | 376 | shun_artifacts(); |
| 365 | 377 | |
| 366 | 378 | db_multi_exec( |
| @@ -994,11 +1006,11 @@ | ||
| 994 | 1006 | ** |
| 995 | 1007 | ** |
| 996 | 1008 | ** This command exports all artifacts of a given repository and |
| 997 | 1009 | ** writes all artifacts to the file system. The DESTINATION directory |
| 998 | 1010 | ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where |
| 999 | -** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters. | |
| 1011 | +** AABBBBBBBBB.. is the 40+ character artifact ID, AA the first 2 characters. | |
| 1000 | 1012 | ** If -L|--prefixlength is given, the length (default 2) of the directory |
| 1001 | 1013 | ** prefix can be set to 0,1,..,9 characters. |
| 1002 | 1014 | ** |
| 1003 | 1015 | ** Options: |
| 1004 | 1016 | ** -R|--repository REPOSITORY deconstruct given REPOSITORY |
| 1005 | 1017 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -21,76 +21,41 @@ | |
| 21 | #include "rebuild.h" |
| 22 | #include <assert.h> |
| 23 | #include <errno.h> |
| 24 | |
| 25 | /* |
| 26 | ** Make changes to the stable part of the schema (the part that is not |
| 27 | ** simply deleted and reconstructed on a rebuild) to bring the schema |
| 28 | ** up to the latest. |
| 29 | */ |
| 30 | static const char zSchemaUpdates1[] = |
| 31 | @ -- Index on the delta table |
| 32 | @ -- |
| 33 | @ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid); |
| 34 | @ |
| 35 | @ -- Artifacts that should not be processed are identified in the |
| 36 | @ -- "shun" table. Artifacts that are control-file forgeries or |
| 37 | @ -- spam or artifacts whose contents violate administrative policy |
| 38 | @ -- can be shunned in order to prevent them from contaminating |
| 39 | @ -- the repository. |
| 40 | @ -- |
| 41 | @ -- Shunned artifacts do not exist in the blob table. Hence they |
| 42 | @ -- have not artifact ID (rid) and we thus must store their full |
| 43 | @ -- UUID. |
| 44 | @ -- |
| 45 | @ CREATE TABLE IF NOT EXISTS shun( |
| 46 | @ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form |
| 47 | @ mtime INTEGER, -- When added. Seconds since 1970 |
| 48 | @ scom TEXT -- Optional text explaining why the shun occurred |
| 49 | @ ); |
| 50 | @ |
| 51 | @ -- Artifacts that should not be pushed are stored in the "private" |
| 52 | @ -- table. |
| 53 | @ -- |
| 54 | @ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY); |
| 55 | @ |
| 56 | @ -- Some ticket content (such as the originators email address or contact |
| 57 | @ -- information) needs to be obscured to protect privacy. This is achieved |
| 58 | @ -- by storing an SHA1 hash of the content. For display, the hash is |
| 59 | @ -- mapped back into the original text using this table. |
| 60 | @ -- |
| 61 | @ -- This table contains sensitive information and should not be shared |
| 62 | @ -- with unauthorized users. |
| 63 | @ -- |
| 64 | @ CREATE TABLE IF NOT EXISTS concealed( |
| 65 | @ hash TEXT PRIMARY KEY, -- The SHA1 hash of content |
| 66 | @ mtime INTEGER, -- Time created. Seconds since 1970 |
| 67 | @ content TEXT -- Content intended to be concealed |
| 68 | @ ); |
| 69 | ; |
| 70 | static const char zSchemaUpdates2[] = |
| 71 | @ -- An entry in this table describes a database query that generates a |
| 72 | @ -- table of tickets. |
| 73 | @ -- |
| 74 | @ CREATE TABLE IF NOT EXISTS reportfmt( |
| 75 | @ rn INTEGER PRIMARY KEY, -- Report number |
| 76 | @ owner TEXT, -- Owner of this report format (not used) |
| 77 | @ title TEXT UNIQUE, -- Title of this report |
| 78 | @ mtime INTEGER, -- Time last modified. Seconds since 1970 |
| 79 | @ cols TEXT, -- A color-key specification |
| 80 | @ sqlcode TEXT -- An SQL SELECT statement for this report |
| 81 | @ ); |
| 82 | ; |
| 83 | |
| 84 | static void rebuild_update_schema(void){ |
| 85 | int rc; |
| 86 | db_multi_exec("%s", zSchemaUpdates1 /*safe-for-%s*/); |
| 87 | db_multi_exec("%s", zSchemaUpdates2 /*safe-for-%s*/); |
| 88 | |
| 89 | rc = db_exists("SELECT 1 FROM sqlite_master" |
| 90 | " WHERE name='user' AND sql GLOB '* mtime *'"); |
| 91 | if( rc==0 ){ |
| 92 | db_multi_exec( |
| 93 | "CREATE TEMP TABLE temp_user AS SELECT * FROM user;" |
| 94 | "DROP TABLE user;" |
| 95 | "CREATE TABLE user(\n" |
| 96 | " uid INTEGER PRIMARY KEY,\n" |
| @@ -109,54 +74,99 @@ | |
| 109 | " ipaddr, cexpire, info, now(), photo FROM temp_user;" |
| 110 | "DROP TABLE temp_user;" |
| 111 | ); |
| 112 | } |
| 113 | |
| 114 | rc = db_exists("SELECT 1 FROM sqlite_master" |
| 115 | " WHERE name='config' AND sql GLOB '* mtime *'"); |
| 116 | if( rc==0 ){ |
| 117 | db_multi_exec( |
| 118 | "ALTER TABLE config ADD COLUMN mtime INTEGER;" |
| 119 | "UPDATE config SET mtime=now();" |
| 120 | ); |
| 121 | } |
| 122 | |
| 123 | rc = db_exists("SELECT 1 FROM sqlite_master" |
| 124 | " WHERE name='shun' AND sql GLOB '* mtime *'"); |
| 125 | if( rc==0 ){ |
| 126 | db_multi_exec( |
| 127 | "ALTER TABLE shun ADD COLUMN mtime INTEGER;" |
| 128 | "ALTER TABLE shun ADD COLUMN scom TEXT;" |
| 129 | "UPDATE shun SET mtime=now();" |
| 130 | ); |
| 131 | } |
| 132 | |
| 133 | rc = db_exists("SELECT 1 FROM sqlite_master" |
| 134 | " WHERE name='reportfmt' AND sql GLOB '* mtime *'"); |
| 135 | if( rc==0 ){ |
| 136 | db_multi_exec( |
| 137 | "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;" |
| 138 | "DROP TABLE reportfmt;" |
| 139 | ); |
| 140 | db_multi_exec("%s", zSchemaUpdates2/*safe-for-%s*/); |
| 141 | db_multi_exec( |
| 142 | "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)" |
| 143 | " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;" |
| 144 | "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)" |
| 145 | " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()" |
| 146 | " FROM old_fmt;" |
| 147 | ); |
| 148 | } |
| 149 | |
| 150 | rc = db_exists("SELECT 1 FROM sqlite_master" |
| 151 | " WHERE name='concealed' AND sql GLOB '* mtime *'"); |
| 152 | if( rc==0 ){ |
| 153 | db_multi_exec( |
| 154 | "ALTER TABLE concealed ADD COLUMN mtime INTEGER;" |
| 155 | "UPDATE concealed SET mtime=now();" |
| 156 | ); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | /* |
| 161 | ** Variables used to store state information about an on-going "rebuild" |
| 162 | ** or "deconstruct". |
| @@ -330,37 +340,39 @@ | |
| 330 | ** extracted in a random order. This feature is used to test the |
| 331 | ** ability of fossil to accept records in any order and still |
| 332 | ** construct a sane repository. |
| 333 | */ |
| 334 | int rebuild_db(int randomize, int doOut, int doClustering){ |
| 335 | Stmt s; |
| 336 | int errCnt = 0; |
| 337 | char *zTable; |
| 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, |
| 349 | "SELECT name FROM sqlite_master /*scan*/" |
| 350 | " WHERE type='table'" |
| 351 | " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user'," |
| 352 | "'config','shun','private','reportfmt'," |
| 353 | "'concealed','accesslog','modreq'," |
| 354 | "'purgeevent','purgeitem','unversioned')" |
| 355 | " AND name NOT GLOB 'sqlite_*'" |
| 356 | " AND name NOT GLOB 'fx_*'" |
| 357 | ); |
| 358 | if( zTable==0 ) break; |
| 359 | db_multi_exec("DROP TABLE %Q", zTable); |
| 360 | free(zTable); |
| 361 | } |
| 362 | db_multi_exec("%s", zRepositorySchema2/*safe-for-%s*/); |
| 363 | ticket_create_table(0); |
| 364 | shun_artifacts(); |
| 365 | |
| 366 | db_multi_exec( |
| @@ -994,11 +1006,11 @@ | |
| 994 | ** |
| 995 | ** |
| 996 | ** This command exports all artifacts of a given repository and |
| 997 | ** writes all artifacts to the file system. The DESTINATION directory |
| 998 | ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where |
| 999 | ** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters. |
| 1000 | ** If -L|--prefixlength is given, the length (default 2) of the directory |
| 1001 | ** prefix can be set to 0,1,..,9 characters. |
| 1002 | ** |
| 1003 | ** Options: |
| 1004 | ** -R|--repository REPOSITORY deconstruct given REPOSITORY |
| 1005 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -21,76 +21,41 @@ | |
| 21 | #include "rebuild.h" |
| 22 | #include <assert.h> |
| 23 | #include <errno.h> |
| 24 | |
| 25 | /* |
| 26 | ** Update the schema as necessary |
| 27 | */ |
| 28 | static void rebuild_update_schema(void){ |
| 29 | /* Verify that the PLINK table has a new column added by the |
| 30 | ** 2014-11-28 schema change. Create it if necessary. This code |
| 31 | ** can be removed in the future, once all users have upgraded to the |
| 32 | ** 2014-11-28 or later schema. |
| 33 | */ |
| 34 | if( !db_table_has_column("repository","plink","baseid") ){ |
| 35 | db_multi_exec( |
| 36 | "ALTER TABLE repository.plink ADD COLUMN baseid;" |
| 37 | ); |
| 38 | } |
| 39 | |
| 40 | /* Verify that the MLINK table has the newer columns added by the |
| 41 | ** 2015-01-24 schema change. Create them if necessary. This code |
| 42 | ** can be removed in the future, once all users have upgraded to the |
| 43 | ** 2015-01-24 or later schema. |
| 44 | */ |
| 45 | if( !db_table_has_column("repository","mlink","isaux") ){ |
| 46 | db_begin_transaction(); |
| 47 | db_multi_exec( |
| 48 | "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;" |
| 49 | "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;" |
| 50 | ); |
| 51 | db_end_transaction(0); |
| 52 | } |
| 53 | |
| 54 | /* Add the user.mtime column if it is missing. (2011-04-27) |
| 55 | */ |
| 56 | if( !db_table_has_column("repository", "user", "mtime") ){ |
| 57 | db_multi_exec( |
| 58 | "CREATE TEMP TABLE temp_user AS SELECT * FROM user;" |
| 59 | "DROP TABLE user;" |
| 60 | "CREATE TABLE user(\n" |
| 61 | " uid INTEGER PRIMARY KEY,\n" |
| @@ -109,54 +74,99 @@ | |
| 74 | " ipaddr, cexpire, info, now(), photo FROM temp_user;" |
| 75 | "DROP TABLE temp_user;" |
| 76 | ); |
| 77 | } |
| 78 | |
| 79 | /* Add the config.mtime column if it is missing. (2011-04-27) |
| 80 | */ |
| 81 | if( !db_table_has_column("repository", "config", "mtime") ){ |
| 82 | db_multi_exec( |
| 83 | "ALTER TABLE config ADD COLUMN mtime INTEGER;" |
| 84 | "UPDATE config SET mtime=now();" |
| 85 | ); |
| 86 | } |
| 87 | |
| 88 | /* Add the shun.mtime and shun.scom columns if they are missing. |
| 89 | ** (2011-04-27) |
| 90 | */ |
| 91 | if( !db_table_has_column("repository", "shun", "mtime") ){ |
| 92 | db_multi_exec( |
| 93 | "ALTER TABLE shun ADD COLUMN mtime INTEGER;" |
| 94 | "ALTER TABLE shun ADD COLUMN scom TEXT;" |
| 95 | "UPDATE shun SET mtime=now();" |
| 96 | ); |
| 97 | } |
| 98 | |
| 99 | /* Add the reportfmt.mtime column if it is missing. (2011-04-27) |
| 100 | */ |
| 101 | if( !db_table_has_column("repository", "reportfmt", "mtime") ){ |
| 102 | static const char zCreateReportFmtTable[] = |
| 103 | @ -- An entry in this table describes a database query that generates a |
| 104 | @ -- table of tickets. |
| 105 | @ -- |
| 106 | @ CREATE TABLE IF NOT EXISTS reportfmt( |
| 107 | @ rn INTEGER PRIMARY KEY, -- Report number |
| 108 | @ owner TEXT, -- Owner of this report format (not used) |
| 109 | @ title TEXT UNIQUE, -- Title of this report |
| 110 | @ mtime INTEGER, -- Time last modified. Seconds since 1970 |
| 111 | @ cols TEXT, -- A color-key specification |
| 112 | @ sqlcode TEXT -- An SQL SELECT statement for this report |
| 113 | @ ); |
| 114 | ; |
| 115 | db_multi_exec( |
| 116 | "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;" |
| 117 | "DROP TABLE reportfmt;" |
| 118 | ); |
| 119 | db_multi_exec("%s", zCreateReportFmtTable/*safe-for-%s*/); |
| 120 | db_multi_exec( |
| 121 | "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)" |
| 122 | " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;" |
| 123 | "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)" |
| 124 | " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()" |
| 125 | " FROM old_fmt;" |
| 126 | ); |
| 127 | } |
| 128 | |
| 129 | /* Add the concealed.mtime column if it is missing. (2011-04-27) |
| 130 | */ |
| 131 | if( !db_table_has_column("repository", "concealed", "mtime") ){ |
| 132 | db_multi_exec( |
| 133 | "ALTER TABLE concealed ADD COLUMN mtime INTEGER;" |
| 134 | "UPDATE concealed SET mtime=now();" |
| 135 | ); |
| 136 | } |
| 137 | |
| 138 | /* Do the fossil-2.0 updates to the schema. (2017-02-28) |
| 139 | */ |
| 140 | rebuild_schema_update_2_0(); |
| 141 | } |
| 142 | |
| 143 | /* |
| 144 | ** Update the repository schema for Fossil version 2.0. (2017-02-28) |
| 145 | ** (1) Change the CHECK constraint on BLOB.UUID so that the length |
| 146 | ** is greater than or equal to 40, not exactly equal to 40. |
| 147 | */ |
| 148 | void rebuild_schema_update_2_0(void){ |
| 149 | char *z = db_text(0, "SELECT sql FROM repository.sqlite_master WHERE name='blob'"); |
| 150 | if( z ){ |
| 151 | /* Search for: length(uuid)==40 |
| 152 | ** 0123456789 12345 */ |
| 153 | int i; |
| 154 | for(i=10; z[i]; i++){ |
| 155 | if( z[i]=='=' && strncmp(&z[i-6],"(uuid)==40",10)==0 ){ |
| 156 | z[i] = '>'; |
| 157 | db_multi_exec( |
| 158 | "PRAGMA writable_schema=ON;" |
| 159 | "UPDATE repository.sqlite_master SET sql=%Q WHERE name LIKE 'blob';" |
| 160 | "PRAGMA writable_schema=OFF;", |
| 161 | z |
| 162 | ); |
| 163 | break; |
| 164 | } |
| 165 | } |
| 166 | fossil_free(z); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | /* |
| 171 | ** Variables used to store state information about an on-going "rebuild" |
| 172 | ** or "deconstruct". |
| @@ -330,37 +340,39 @@ | |
| 340 | ** extracted in a random order. This feature is used to test the |
| 341 | ** ability of fossil to accept records in any order and still |
| 342 | ** construct a sane repository. |
| 343 | */ |
| 344 | int rebuild_db(int randomize, int doOut, int doClustering){ |
| 345 | Stmt s, q; |
| 346 | int errCnt = 0; |
| 347 | int incrSize; |
| 348 | Blob sql; |
| 349 | |
| 350 | bag_init(&bagDone); |
| 351 | ttyOutput = doOut; |
| 352 | processCnt = 0; |
| 353 | if (ttyOutput && !g.fQuiet) { |
| 354 | percent_complete(0); |
| 355 | } |
| 356 | rebuild_update_schema(); |
| 357 | blob_init(&sql, 0, 0); |
| 358 | db_prepare(&q, |
| 359 | "SELECT name FROM sqlite_master /*scan*/" |
| 360 | " WHERE type='table'" |
| 361 | " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias'," |
| 362 | "'config','shun','private','reportfmt'," |
| 363 | "'concealed','accesslog','modreq'," |
| 364 | "'purgeevent','purgeitem','unversioned')" |
| 365 | " AND name NOT GLOB 'sqlite_*'" |
| 366 | " AND name NOT GLOB 'fx_*'" |
| 367 | ); |
| 368 | while( db_step(&q)==SQLITE_ROW ){ |
| 369 | blob_appendf(&sql, "DROP TABLE \"%w\";\n", db_column_text(&q,0)); |
| 370 | } |
| 371 | db_finalize(&q); |
| 372 | db_multi_exec("%s", blob_str(&sql)/*safe-for-%s*/); |
| 373 | blob_reset(&sql); |
| 374 | db_multi_exec("%s", zRepositorySchema2/*safe-for-%s*/); |
| 375 | ticket_create_table(0); |
| 376 | shun_artifacts(); |
| 377 | |
| 378 | db_multi_exec( |
| @@ -994,11 +1006,11 @@ | |
| 1006 | ** |
| 1007 | ** |
| 1008 | ** This command exports all artifacts of a given repository and |
| 1009 | ** writes all artifacts to the file system. The DESTINATION directory |
| 1010 | ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where |
| 1011 | ** AABBBBBBBBB.. is the 40+ character artifact ID, AA the first 2 characters. |
| 1012 | ** If -L|--prefixlength is given, the length (default 2) of the directory |
| 1013 | ** prefix can be set to 0,1,..,9 characters. |
| 1014 | ** |
| 1015 | ** Options: |
| 1016 | ** -R|--repository REPOSITORY deconstruct given REPOSITORY |
| 1017 |
+2
-2
| --- src/schema.c | ||
| +++ src/schema.c | ||
| @@ -79,13 +79,13 @@ | ||
| 79 | 79 | @ -- |
| 80 | 80 | @ CREATE TABLE blob( |
| 81 | 81 | @ rid INTEGER PRIMARY KEY, -- Record ID |
| 82 | 82 | @ rcvid INTEGER, -- Origin of this record |
| 83 | 83 | @ size INTEGER, -- Size of content. -1 for a phantom. |
| 84 | -@ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content | |
| 84 | +@ uuid TEXT UNIQUE NOT NULL, -- hash of the content | |
| 85 | 85 | @ content BLOB, -- Compressed content of this record |
| 86 | -@ CHECK( length(uuid)==40 AND rid>0 ) | |
| 86 | +@ CHECK( length(uuid)>=40 AND rid>0 ) | |
| 87 | 87 | @ ); |
| 88 | 88 | @ CREATE TABLE delta( |
| 89 | 89 | @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed |
| 90 | 90 | @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression |
| 91 | 91 | @ ); |
| 92 | 92 |
| --- src/schema.c | |
| +++ src/schema.c | |
| @@ -79,13 +79,13 @@ | |
| 79 | @ -- |
| 80 | @ CREATE TABLE blob( |
| 81 | @ rid INTEGER PRIMARY KEY, -- Record ID |
| 82 | @ rcvid INTEGER, -- Origin of this record |
| 83 | @ size INTEGER, -- Size of content. -1 for a phantom. |
| 84 | @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content |
| 85 | @ content BLOB, -- Compressed content of this record |
| 86 | @ CHECK( length(uuid)==40 AND rid>0 ) |
| 87 | @ ); |
| 88 | @ CREATE TABLE delta( |
| 89 | @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed |
| 90 | @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression |
| 91 | @ ); |
| 92 |
| --- src/schema.c | |
| +++ src/schema.c | |
| @@ -79,13 +79,13 @@ | |
| 79 | @ -- |
| 80 | @ CREATE TABLE blob( |
| 81 | @ rid INTEGER PRIMARY KEY, -- Record ID |
| 82 | @ rcvid INTEGER, -- Origin of this record |
| 83 | @ size INTEGER, -- Size of content. -1 for a phantom. |
| 84 | @ uuid TEXT UNIQUE NOT NULL, -- hash of the content |
| 85 | @ content BLOB, -- Compressed content of this record |
| 86 | @ CHECK( length(uuid)>=40 AND rid>0 ) |
| 87 | @ ); |
| 88 | @ CREATE TABLE delta( |
| 89 | @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed |
| 90 | @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression |
| 91 | @ ); |
| 92 |
+8
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1108,10 +1108,18 @@ | ||
| 1108 | 1108 | "remote_user_ok", "remote_user_ok", 0, 0); |
| 1109 | 1109 | @ <p>When enabled, if the REMOTE_USER environment variable is set to the |
| 1110 | 1110 | @ login name of a valid user and no other login credentials are available, |
| 1111 | 1111 | @ then the REMOTE_USER is accepted as an authenticated user. |
| 1112 | 1112 | @ </p> |
| 1113 | + @ | |
| 1114 | + @ <hr /> | |
| 1115 | + onoff_attribute("Allow HTTP_AUTHENTICATION authentication", | |
| 1116 | + "http_authentication_ok", "http_authentication_ok", 0, 0); | |
| 1117 | + @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment | |
| 1118 | + @ variable or the "Authentication:" HTTP header to find the username and | |
| 1119 | + @ password. This is another way of supporting Basic Authenitication. | |
| 1120 | + @ </p> | |
| 1113 | 1121 | @ |
| 1114 | 1122 | @ <hr /> |
| 1115 | 1123 | entry_attribute("IP address terms used in login cookie", 3, |
| 1116 | 1124 | "ip-prefix-terms", "ipt", "2", 0); |
| 1117 | 1125 | @ <p>The number of octets of of the IP address used in the login cookie. |
| 1118 | 1126 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1108,10 +1108,18 @@ | |
| 1108 | "remote_user_ok", "remote_user_ok", 0, 0); |
| 1109 | @ <p>When enabled, if the REMOTE_USER environment variable is set to the |
| 1110 | @ login name of a valid user and no other login credentials are available, |
| 1111 | @ then the REMOTE_USER is accepted as an authenticated user. |
| 1112 | @ </p> |
| 1113 | @ |
| 1114 | @ <hr /> |
| 1115 | entry_attribute("IP address terms used in login cookie", 3, |
| 1116 | "ip-prefix-terms", "ipt", "2", 0); |
| 1117 | @ <p>The number of octets of of the IP address used in the login cookie. |
| 1118 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1108,10 +1108,18 @@ | |
| 1108 | "remote_user_ok", "remote_user_ok", 0, 0); |
| 1109 | @ <p>When enabled, if the REMOTE_USER environment variable is set to the |
| 1110 | @ login name of a valid user and no other login credentials are available, |
| 1111 | @ then the REMOTE_USER is accepted as an authenticated user. |
| 1112 | @ </p> |
| 1113 | @ |
| 1114 | @ <hr /> |
| 1115 | onoff_attribute("Allow HTTP_AUTHENTICATION authentication", |
| 1116 | "http_authentication_ok", "http_authentication_ok", 0, 0); |
| 1117 | @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment |
| 1118 | @ variable or the "Authentication:" HTTP header to find the username and |
| 1119 | @ password. This is another way of supporting Basic Authenitication. |
| 1120 | @ </p> |
| 1121 | @ |
| 1122 | @ <hr /> |
| 1123 | entry_attribute("IP address terms used in login cookie", 3, |
| 1124 | "ip-prefix-terms", "ipt", "2", 0); |
| 1125 | @ <p>The number of octets of of the IP address used in the login cookie. |
| 1126 |
+79
-11
| --- src/sha1.c | ||
| +++ src/sha1.c | ||
| @@ -1,22 +1,88 @@ | ||
| 1 | 1 | /* |
| 2 | +** Copyright (c) 2006 D. Richard Hipp | |
| 3 | +** | |
| 4 | +** This program is free software; you can redistribute it and/or | |
| 5 | +** modify it under the terms of the Simplified BSD License (also | |
| 6 | +** known as the "2-Clause License" or "FreeBSD License".) | |
| 7 | +** | |
| 8 | +** This program is distributed in the hope that it will be useful, | |
| 9 | +** but without any warranty; without even the implied warranty of | |
| 10 | +** merchantability or fitness for a particular purpose. | |
| 11 | +** | |
| 12 | +** Author contact information: | |
| 13 | +** [email protected] | |
| 14 | +** http://www.hwaci.com/drh/ | |
| 15 | +** | |
| 16 | +******************************************************************************* | |
| 17 | +** | |
| 2 | 18 | ** This implementation of SHA1. |
| 3 | 19 | */ |
| 4 | 20 | #include "config.h" |
| 5 | 21 | #include <sys/types.h> |
| 22 | +#include <stdint.h> | |
| 6 | 23 | #include "sha1.h" |
| 7 | 24 | |
| 8 | -#ifdef FOSSIL_ENABLE_SSL | |
| 25 | + | |
| 26 | +/* | |
| 27 | +** SHA1 Implementation #1 is the hardened SHA1 implementation by | |
| 28 | +** Marc Stevens. Code obtained from GitHub | |
| 29 | +** | |
| 30 | +** https://github.com/cr-marcstevens/sha1collisiondetection | |
| 31 | +** | |
| 32 | +** Downloaded on 2017-03-01 then repackaged to work with Fossil | |
| 33 | +** and makeheaders. | |
| 34 | +*/ | |
| 35 | +#if FOSSIL_HARDENED_SHA1 | |
| 36 | + | |
| 37 | +#if INTERFACE | |
| 38 | +typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*); | |
| 39 | +struct SHA1_CTX { | |
| 40 | + uint64_t total; | |
| 41 | + uint32_t ihv[5]; | |
| 42 | + unsigned char buffer[64]; | |
| 43 | + int bigendian; | |
| 44 | + int found_collision; | |
| 45 | + int safe_hash; | |
| 46 | + int detect_coll; | |
| 47 | + int ubc_check; | |
| 48 | + int reduced_round_coll; | |
| 49 | + collision_block_callback callback; | |
| 50 | + | |
| 51 | + uint32_t ihv1[5]; | |
| 52 | + uint32_t ihv2[5]; | |
| 53 | + uint32_t m1[80]; | |
| 54 | + uint32_t m2[80]; | |
| 55 | + uint32_t states[80][5]; | |
| 56 | +}; | |
| 57 | +#endif | |
| 58 | +void SHA1DCInit(SHA1_CTX*); | |
| 59 | +void SHA1DCUpdate(SHA1_CTX*, const unsigned char*, unsigned); | |
| 60 | +int SHA1DCFinal(unsigned char[20], SHA1_CTX*); | |
| 61 | + | |
| 62 | +#define SHA1Context SHA1_CTX | |
| 63 | +#define SHA1Init SHA1DCInit | |
| 64 | +#define SHA1Update SHA1DCUpdate | |
| 65 | +#define SHA1Final SHA1DCFinal | |
| 66 | + | |
| 67 | +/* | |
| 68 | +** SHA1 Implementation #2: use the SHA1 algorithm built into SSL | |
| 69 | +*/ | |
| 70 | +#elif defined(FOSSIL_ENABLE_SSL) | |
| 9 | 71 | |
| 10 | 72 | # include <openssl/sha.h> |
| 11 | 73 | # define SHA1Context SHA_CTX |
| 12 | 74 | # define SHA1Init SHA1_Init |
| 13 | 75 | # define SHA1Update SHA1_Update |
| 14 | -# define SHA1Final(a,b) SHA1_Final(b,a) | |
| 76 | +# define SHA1Final SHA1_Final | |
| 15 | 77 | |
| 78 | +/* | |
| 79 | +** SHA1 Implementation #3: If none of the previous two SHA1 | |
| 80 | +** algorithms work, there is this built-in. This built-in was the | |
| 81 | +** original implementation used by Fossil. | |
| 82 | +*/ | |
| 16 | 83 | #else |
| 17 | - | |
| 18 | 84 | /* |
| 19 | 85 | ** The SHA1 implementation below is adapted from: |
| 20 | 86 | ** |
| 21 | 87 | ** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ |
| 22 | 88 | ** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ |
| @@ -53,10 +119,13 @@ | ||
| 53 | 119 | /* Generic C equivalent */ |
| 54 | 120 | #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) |
| 55 | 121 | #define rol(x,k) SHA_ROT(x,k,32-(k)) |
| 56 | 122 | #define ror(x,k) SHA_ROT(x,32-(k),k) |
| 57 | 123 | #endif |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 58 | 127 | |
| 59 | 128 | |
| 60 | 129 | #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ |
| 61 | 130 | |(rol(block[i],8)&0x00FF00FF)) |
| 62 | 131 | #define blk0be(i) block[i] |
| @@ -188,11 +257,11 @@ | ||
| 188 | 257 | |
| 189 | 258 | |
| 190 | 259 | /* |
| 191 | 260 | * Add padding and return the message digest. |
| 192 | 261 | */ |
| 193 | -static void SHA1Final(SHA1Context *context, unsigned char digest[20]){ | |
| 262 | +static void SHA1Final(unsigned char *digest, SHA1Context *context){ | |
| 194 | 263 | unsigned int i; |
| 195 | 264 | unsigned char finalcount[8]; |
| 196 | 265 | |
| 197 | 266 | for (i = 0; i < 8; i++) { |
| 198 | 267 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] |
| @@ -207,12 +276,11 @@ | ||
| 207 | 276 | for (i = 0; i < 20; i++) |
| 208 | 277 | digest[i] = (unsigned char) |
| 209 | 278 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); |
| 210 | 279 | } |
| 211 | 280 | } |
| 212 | -#endif | |
| 213 | - | |
| 281 | +#endif /* Built-in SHA1 implemenation */ | |
| 214 | 282 | |
| 215 | 283 | /* |
| 216 | 284 | ** Convert a digest into base-16. digest should be declared as |
| 217 | 285 | ** "unsigned char digest[20]" in the calling function. The SHA1 |
| 218 | 286 | ** digest is stored in the first 20 bytes. zBuf should |
| @@ -268,11 +336,11 @@ | ||
| 268 | 336 | */ |
| 269 | 337 | char *sha1sum_finish(Blob *pOut){ |
| 270 | 338 | unsigned char zResult[20]; |
| 271 | 339 | static char zOut[41]; |
| 272 | 340 | sha1sum_step_text(0,0); |
| 273 | - SHA1Final(&incrCtx, zResult); | |
| 341 | + SHA1Final(zResult, &incrCtx); | |
| 274 | 342 | incrInit = 0; |
| 275 | 343 | DigestToBase16(zResult, zOut); |
| 276 | 344 | if( pOut ){ |
| 277 | 345 | blob_zero(pOut); |
| 278 | 346 | blob_append(pOut, zOut, 40); |
| @@ -316,11 +384,11 @@ | ||
| 316 | 384 | SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n); |
| 317 | 385 | } |
| 318 | 386 | fclose(in); |
| 319 | 387 | blob_zero(pCksum); |
| 320 | 388 | blob_resize(pCksum, 40); |
| 321 | - SHA1Final(&ctx, zResult); | |
| 389 | + SHA1Final(zResult, &ctx); | |
| 322 | 390 | DigestToBase16(zResult, blob_buffer(pCksum)); |
| 323 | 391 | return 0; |
| 324 | 392 | } |
| 325 | 393 | |
| 326 | 394 | /* |
| @@ -340,11 +408,11 @@ | ||
| 340 | 408 | blob_reset(pCksum); |
| 341 | 409 | }else{ |
| 342 | 410 | blob_zero(pCksum); |
| 343 | 411 | } |
| 344 | 412 | blob_resize(pCksum, 40); |
| 345 | - SHA1Final(&ctx, zResult); | |
| 413 | + SHA1Final(zResult, &ctx); | |
| 346 | 414 | DigestToBase16(zResult, blob_buffer(pCksum)); |
| 347 | 415 | return 0; |
| 348 | 416 | } |
| 349 | 417 | |
| 350 | 418 | /* |
| @@ -356,11 +424,11 @@ | ||
| 356 | 424 | unsigned char zResult[20]; |
| 357 | 425 | char zDigest[41]; |
| 358 | 426 | |
| 359 | 427 | SHA1Init(&ctx); |
| 360 | 428 | SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn)); |
| 361 | - SHA1Final(&ctx, zResult); | |
| 429 | + SHA1Final(zResult, &ctx); | |
| 362 | 430 | DigestToBase16(zResult, zDigest); |
| 363 | 431 | return mprintf("%s", zDigest); |
| 364 | 432 | } |
| 365 | 433 | |
| 366 | 434 | /* |
| @@ -407,11 +475,11 @@ | ||
| 407 | 475 | SHA1Update(&ctx, (unsigned char*)zProjCode, strlen(zProjCode)); |
| 408 | 476 | SHA1Update(&ctx, (unsigned char*)"/", 1); |
| 409 | 477 | SHA1Update(&ctx, (unsigned char*)zLogin, strlen(zLogin)); |
| 410 | 478 | SHA1Update(&ctx, (unsigned char*)"/", 1); |
| 411 | 479 | SHA1Update(&ctx, (unsigned const char*)zPw, strlen(zPw)); |
| 412 | - SHA1Final(&ctx, zResult); | |
| 480 | + SHA1Final(zResult, &ctx); | |
| 413 | 481 | DigestToBase16(zResult, zDigest); |
| 414 | 482 | return mprintf("%s", zDigest); |
| 415 | 483 | } |
| 416 | 484 | |
| 417 | 485 | /* |
| 418 | 486 | |
| 419 | 487 | ADDED src/sha1hard.c |
| 420 | 488 | ADDED src/sha3.c |
| --- src/sha1.c | |
| +++ src/sha1.c | |
| @@ -1,22 +1,88 @@ | |
| 1 | /* |
| 2 | ** This implementation of SHA1. |
| 3 | */ |
| 4 | #include "config.h" |
| 5 | #include <sys/types.h> |
| 6 | #include "sha1.h" |
| 7 | |
| 8 | #ifdef FOSSIL_ENABLE_SSL |
| 9 | |
| 10 | # include <openssl/sha.h> |
| 11 | # define SHA1Context SHA_CTX |
| 12 | # define SHA1Init SHA1_Init |
| 13 | # define SHA1Update SHA1_Update |
| 14 | # define SHA1Final(a,b) SHA1_Final(b,a) |
| 15 | |
| 16 | #else |
| 17 | |
| 18 | /* |
| 19 | ** The SHA1 implementation below is adapted from: |
| 20 | ** |
| 21 | ** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ |
| 22 | ** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ |
| @@ -53,10 +119,13 @@ | |
| 53 | /* Generic C equivalent */ |
| 54 | #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) |
| 55 | #define rol(x,k) SHA_ROT(x,k,32-(k)) |
| 56 | #define ror(x,k) SHA_ROT(x,32-(k),k) |
| 57 | #endif |
| 58 | |
| 59 | |
| 60 | #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ |
| 61 | |(rol(block[i],8)&0x00FF00FF)) |
| 62 | #define blk0be(i) block[i] |
| @@ -188,11 +257,11 @@ | |
| 188 | |
| 189 | |
| 190 | /* |
| 191 | * Add padding and return the message digest. |
| 192 | */ |
| 193 | static void SHA1Final(SHA1Context *context, unsigned char digest[20]){ |
| 194 | unsigned int i; |
| 195 | unsigned char finalcount[8]; |
| 196 | |
| 197 | for (i = 0; i < 8; i++) { |
| 198 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] |
| @@ -207,12 +276,11 @@ | |
| 207 | for (i = 0; i < 20; i++) |
| 208 | digest[i] = (unsigned char) |
| 209 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); |
| 210 | } |
| 211 | } |
| 212 | #endif |
| 213 | |
| 214 | |
| 215 | /* |
| 216 | ** Convert a digest into base-16. digest should be declared as |
| 217 | ** "unsigned char digest[20]" in the calling function. The SHA1 |
| 218 | ** digest is stored in the first 20 bytes. zBuf should |
| @@ -268,11 +336,11 @@ | |
| 268 | */ |
| 269 | char *sha1sum_finish(Blob *pOut){ |
| 270 | unsigned char zResult[20]; |
| 271 | static char zOut[41]; |
| 272 | sha1sum_step_text(0,0); |
| 273 | SHA1Final(&incrCtx, zResult); |
| 274 | incrInit = 0; |
| 275 | DigestToBase16(zResult, zOut); |
| 276 | if( pOut ){ |
| 277 | blob_zero(pOut); |
| 278 | blob_append(pOut, zOut, 40); |
| @@ -316,11 +384,11 @@ | |
| 316 | SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n); |
| 317 | } |
| 318 | fclose(in); |
| 319 | blob_zero(pCksum); |
| 320 | blob_resize(pCksum, 40); |
| 321 | SHA1Final(&ctx, zResult); |
| 322 | DigestToBase16(zResult, blob_buffer(pCksum)); |
| 323 | return 0; |
| 324 | } |
| 325 | |
| 326 | /* |
| @@ -340,11 +408,11 @@ | |
| 340 | blob_reset(pCksum); |
| 341 | }else{ |
| 342 | blob_zero(pCksum); |
| 343 | } |
| 344 | blob_resize(pCksum, 40); |
| 345 | SHA1Final(&ctx, zResult); |
| 346 | DigestToBase16(zResult, blob_buffer(pCksum)); |
| 347 | return 0; |
| 348 | } |
| 349 | |
| 350 | /* |
| @@ -356,11 +424,11 @@ | |
| 356 | unsigned char zResult[20]; |
| 357 | char zDigest[41]; |
| 358 | |
| 359 | SHA1Init(&ctx); |
| 360 | SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn)); |
| 361 | SHA1Final(&ctx, zResult); |
| 362 | DigestToBase16(zResult, zDigest); |
| 363 | return mprintf("%s", zDigest); |
| 364 | } |
| 365 | |
| 366 | /* |
| @@ -407,11 +475,11 @@ | |
| 407 | SHA1Update(&ctx, (unsigned char*)zProjCode, strlen(zProjCode)); |
| 408 | SHA1Update(&ctx, (unsigned char*)"/", 1); |
| 409 | SHA1Update(&ctx, (unsigned char*)zLogin, strlen(zLogin)); |
| 410 | SHA1Update(&ctx, (unsigned char*)"/", 1); |
| 411 | SHA1Update(&ctx, (unsigned const char*)zPw, strlen(zPw)); |
| 412 | SHA1Final(&ctx, zResult); |
| 413 | DigestToBase16(zResult, zDigest); |
| 414 | return mprintf("%s", zDigest); |
| 415 | } |
| 416 | |
| 417 | /* |
| 418 | |
| 419 | DDED src/sha1hard.c |
| 420 | DDED src/sha3.c |
| --- src/sha1.c | |
| +++ src/sha1.c | |
| @@ -1,22 +1,88 @@ | |
| 1 | /* |
| 2 | ** Copyright (c) 2006 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | ** |
| 8 | ** This program is distributed in the hope that it will be useful, |
| 9 | ** but without any warranty; without even the implied warranty of |
| 10 | ** merchantability or fitness for a particular purpose. |
| 11 | ** |
| 12 | ** Author contact information: |
| 13 | ** [email protected] |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This implementation of SHA1. |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include <sys/types.h> |
| 22 | #include <stdint.h> |
| 23 | #include "sha1.h" |
| 24 | |
| 25 | |
| 26 | /* |
| 27 | ** SHA1 Implementation #1 is the hardened SHA1 implementation by |
| 28 | ** Marc Stevens. Code obtained from GitHub |
| 29 | ** |
| 30 | ** https://github.com/cr-marcstevens/sha1collisiondetection |
| 31 | ** |
| 32 | ** Downloaded on 2017-03-01 then repackaged to work with Fossil |
| 33 | ** and makeheaders. |
| 34 | */ |
| 35 | #if FOSSIL_HARDENED_SHA1 |
| 36 | |
| 37 | #if INTERFACE |
| 38 | typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*); |
| 39 | struct SHA1_CTX { |
| 40 | uint64_t total; |
| 41 | uint32_t ihv[5]; |
| 42 | unsigned char buffer[64]; |
| 43 | int bigendian; |
| 44 | int found_collision; |
| 45 | int safe_hash; |
| 46 | int detect_coll; |
| 47 | int ubc_check; |
| 48 | int reduced_round_coll; |
| 49 | collision_block_callback callback; |
| 50 | |
| 51 | uint32_t ihv1[5]; |
| 52 | uint32_t ihv2[5]; |
| 53 | uint32_t m1[80]; |
| 54 | uint32_t m2[80]; |
| 55 | uint32_t states[80][5]; |
| 56 | }; |
| 57 | #endif |
| 58 | void SHA1DCInit(SHA1_CTX*); |
| 59 | void SHA1DCUpdate(SHA1_CTX*, const unsigned char*, unsigned); |
| 60 | int SHA1DCFinal(unsigned char[20], SHA1_CTX*); |
| 61 | |
| 62 | #define SHA1Context SHA1_CTX |
| 63 | #define SHA1Init SHA1DCInit |
| 64 | #define SHA1Update SHA1DCUpdate |
| 65 | #define SHA1Final SHA1DCFinal |
| 66 | |
| 67 | /* |
| 68 | ** SHA1 Implementation #2: use the SHA1 algorithm built into SSL |
| 69 | */ |
| 70 | #elif defined(FOSSIL_ENABLE_SSL) |
| 71 | |
| 72 | # include <openssl/sha.h> |
| 73 | # define SHA1Context SHA_CTX |
| 74 | # define SHA1Init SHA1_Init |
| 75 | # define SHA1Update SHA1_Update |
| 76 | # define SHA1Final SHA1_Final |
| 77 | |
| 78 | /* |
| 79 | ** SHA1 Implementation #3: If none of the previous two SHA1 |
| 80 | ** algorithms work, there is this built-in. This built-in was the |
| 81 | ** original implementation used by Fossil. |
| 82 | */ |
| 83 | #else |
| 84 | /* |
| 85 | ** The SHA1 implementation below is adapted from: |
| 86 | ** |
| 87 | ** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ |
| 88 | ** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ |
| @@ -53,10 +119,13 @@ | |
| 119 | /* Generic C equivalent */ |
| 120 | #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) |
| 121 | #define rol(x,k) SHA_ROT(x,k,32-(k)) |
| 122 | #define ror(x,k) SHA_ROT(x,32-(k),k) |
| 123 | #endif |
| 124 | |
| 125 | |
| 126 | |
| 127 | |
| 128 | |
| 129 | #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ |
| 130 | |(rol(block[i],8)&0x00FF00FF)) |
| 131 | #define blk0be(i) block[i] |
| @@ -188,11 +257,11 @@ | |
| 257 | |
| 258 | |
| 259 | /* |
| 260 | * Add padding and return the message digest. |
| 261 | */ |
| 262 | static void SHA1Final(unsigned char *digest, SHA1Context *context){ |
| 263 | unsigned int i; |
| 264 | unsigned char finalcount[8]; |
| 265 | |
| 266 | for (i = 0; i < 8; i++) { |
| 267 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] |
| @@ -207,12 +276,11 @@ | |
| 276 | for (i = 0; i < 20; i++) |
| 277 | digest[i] = (unsigned char) |
| 278 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); |
| 279 | } |
| 280 | } |
| 281 | #endif /* Built-in SHA1 implemenation */ |
| 282 | |
| 283 | /* |
| 284 | ** Convert a digest into base-16. digest should be declared as |
| 285 | ** "unsigned char digest[20]" in the calling function. The SHA1 |
| 286 | ** digest is stored in the first 20 bytes. zBuf should |
| @@ -268,11 +336,11 @@ | |
| 336 | */ |
| 337 | char *sha1sum_finish(Blob *pOut){ |
| 338 | unsigned char zResult[20]; |
| 339 | static char zOut[41]; |
| 340 | sha1sum_step_text(0,0); |
| 341 | SHA1Final(zResult, &incrCtx); |
| 342 | incrInit = 0; |
| 343 | DigestToBase16(zResult, zOut); |
| 344 | if( pOut ){ |
| 345 | blob_zero(pOut); |
| 346 | blob_append(pOut, zOut, 40); |
| @@ -316,11 +384,11 @@ | |
| 384 | SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n); |
| 385 | } |
| 386 | fclose(in); |
| 387 | blob_zero(pCksum); |
| 388 | blob_resize(pCksum, 40); |
| 389 | SHA1Final(zResult, &ctx); |
| 390 | DigestToBase16(zResult, blob_buffer(pCksum)); |
| 391 | return 0; |
| 392 | } |
| 393 | |
| 394 | /* |
| @@ -340,11 +408,11 @@ | |
| 408 | blob_reset(pCksum); |
| 409 | }else{ |
| 410 | blob_zero(pCksum); |
| 411 | } |
| 412 | blob_resize(pCksum, 40); |
| 413 | SHA1Final(zResult, &ctx); |
| 414 | DigestToBase16(zResult, blob_buffer(pCksum)); |
| 415 | return 0; |
| 416 | } |
| 417 | |
| 418 | /* |
| @@ -356,11 +424,11 @@ | |
| 424 | unsigned char zResult[20]; |
| 425 | char zDigest[41]; |
| 426 | |
| 427 | SHA1Init(&ctx); |
| 428 | SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn)); |
| 429 | SHA1Final(zResult, &ctx); |
| 430 | DigestToBase16(zResult, zDigest); |
| 431 | return mprintf("%s", zDigest); |
| 432 | } |
| 433 | |
| 434 | /* |
| @@ -407,11 +475,11 @@ | |
| 475 | SHA1Update(&ctx, (unsigned char*)zProjCode, strlen(zProjCode)); |
| 476 | SHA1Update(&ctx, (unsigned char*)"/", 1); |
| 477 | SHA1Update(&ctx, (unsigned char*)zLogin, strlen(zLogin)); |
| 478 | SHA1Update(&ctx, (unsigned char*)"/", 1); |
| 479 | SHA1Update(&ctx, (unsigned const char*)zPw, strlen(zPw)); |
| 480 | SHA1Final(zResult, &ctx); |
| 481 | DigestToBase16(zResult, zDigest); |
| 482 | return mprintf("%s", zDigest); |
| 483 | } |
| 484 | |
| 485 | /* |
| 486 | |
| 487 | DDED src/sha1hard.c |
| 488 | DDED src/sha3.c |
No diff available
+2
| --- a/src/sha3.c | ||
| +++ b/src/sha3.c | ||
| @@ -0,0 +1,2 @@ | ||
| 1 | +/* | |
| 2 | +*testfile_wd 128and 5124 |
| --- a/src/sha3.c | |
| +++ b/src/sha3.c | |
| @@ -0,0 +1,2 @@ | |
| --- a/src/sha3.c | |
| +++ b/src/sha3.c | |
| @@ -0,0 +1,2 @@ | |
| 1 | /* |
| 2 | *testfile_wd 128and 5124 |
+1415
-233
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -452,32 +452,10 @@ | ||
| 452 | 452 | while( IsDigit(*z) ){ z++; } |
| 453 | 453 | if( realnum ) *realnum = 1; |
| 454 | 454 | } |
| 455 | 455 | return *z==0; |
| 456 | 456 | } |
| 457 | - | |
| 458 | -/* | |
| 459 | -** A global char* and an SQL function to access its current value | |
| 460 | -** from within an SQL statement. This program used to use the | |
| 461 | -** sqlite_exec_printf() API to substitue a string into an SQL statement. | |
| 462 | -** The correct way to do this with sqlite3 is to use the bind API, but | |
| 463 | -** since the shell is built around the callback paradigm it would be a lot | |
| 464 | -** of work. Instead just use this hack, which is quite harmless. | |
| 465 | -*/ | |
| 466 | -static const char *zShellStatic = 0; | |
| 467 | -static void shellstaticFunc( | |
| 468 | - sqlite3_context *context, | |
| 469 | - int argc, | |
| 470 | - sqlite3_value **argv | |
| 471 | -){ | |
| 472 | - assert( 0==argc ); | |
| 473 | - assert( zShellStatic ); | |
| 474 | - UNUSED_PARAMETER(argc); | |
| 475 | - UNUSED_PARAMETER(argv); | |
| 476 | - sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); | |
| 477 | -} | |
| 478 | - | |
| 479 | 457 | |
| 480 | 458 | /* |
| 481 | 459 | ** Compute a string length that is limited to what can be stored in |
| 482 | 460 | ** lower 30 bits of a 32-bit signed integer. |
| 483 | 461 | */ |
| @@ -575,10 +553,783 @@ | ||
| 575 | 553 | if( zResult && *zResult ) shell_add_history(zResult); |
| 576 | 554 | #endif |
| 577 | 555 | } |
| 578 | 556 | return zResult; |
| 579 | 557 | } |
| 558 | +/* | |
| 559 | +** A variable length string to which one can append text. | |
| 560 | +*/ | |
| 561 | +typedef struct ShellText ShellText; | |
| 562 | +struct ShellText { | |
| 563 | + char *z; | |
| 564 | + int n; | |
| 565 | + int nAlloc; | |
| 566 | +}; | |
| 567 | + | |
| 568 | +/* | |
| 569 | +** Initialize and destroy a ShellText object | |
| 570 | +*/ | |
| 571 | +static void initText(ShellText *p){ | |
| 572 | + memset(p, 0, sizeof(*p)); | |
| 573 | +} | |
| 574 | +static void freeText(ShellText *p){ | |
| 575 | + free(p->z); | |
| 576 | + initText(p); | |
| 577 | +} | |
| 578 | + | |
| 579 | +/* zIn is either a pointer to a NULL-terminated string in memory obtained | |
| 580 | +** from malloc(), or a NULL pointer. The string pointed to by zAppend is | |
| 581 | +** added to zIn, and the result returned in memory obtained from malloc(). | |
| 582 | +** zIn, if it was not NULL, is freed. | |
| 583 | +** | |
| 584 | +** If the third argument, quote, is not '\0', then it is used as a | |
| 585 | +** quote character for zAppend. | |
| 586 | +*/ | |
| 587 | +static void appendText(ShellText *p, char const *zAppend, char quote){ | |
| 588 | + int len; | |
| 589 | + int i; | |
| 590 | + int nAppend = strlen30(zAppend); | |
| 591 | + | |
| 592 | + len = nAppend+p->n+1; | |
| 593 | + if( quote ){ | |
| 594 | + len += 2; | |
| 595 | + for(i=0; i<nAppend; i++){ | |
| 596 | + if( zAppend[i]==quote ) len++; | |
| 597 | + } | |
| 598 | + } | |
| 599 | + | |
| 600 | + if( p->n+len>=p->nAlloc ){ | |
| 601 | + p->nAlloc = p->nAlloc*2 + len + 20; | |
| 602 | + p->z = realloc(p->z, p->nAlloc); | |
| 603 | + if( p->z==0 ){ | |
| 604 | + memset(p, 0, sizeof(*p)); | |
| 605 | + return; | |
| 606 | + } | |
| 607 | + } | |
| 608 | + | |
| 609 | + if( quote ){ | |
| 610 | + char *zCsr = p->z+p->n; | |
| 611 | + *zCsr++ = quote; | |
| 612 | + for(i=0; i<nAppend; i++){ | |
| 613 | + *zCsr++ = zAppend[i]; | |
| 614 | + if( zAppend[i]==quote ) *zCsr++ = quote; | |
| 615 | + } | |
| 616 | + *zCsr++ = quote; | |
| 617 | + p->n = (int)(zCsr - p->z); | |
| 618 | + *zCsr = '\0'; | |
| 619 | + }else{ | |
| 620 | + memcpy(p->z+p->n, zAppend, nAppend); | |
| 621 | + p->n += nAppend; | |
| 622 | + p->z[p->n] = '\0'; | |
| 623 | + } | |
| 624 | +} | |
| 625 | + | |
| 626 | +/* | |
| 627 | +** Attempt to determine if identifier zName needs to be quoted, either | |
| 628 | +** because it contains non-alphanumeric characters, or because it is an | |
| 629 | +** SQLite keyword. Be conservative in this estimate: When in doubt assume | |
| 630 | +** that quoting is required. | |
| 631 | +** | |
| 632 | +** Return '"' if quoting is required. Return 0 if no quoting is required. | |
| 633 | +*/ | |
| 634 | +static char quoteChar(const char *zName){ | |
| 635 | + /* All SQLite keywords, in alphabetical order */ | |
| 636 | + static const char *azKeywords[] = { | |
| 637 | + "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", | |
| 638 | + "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", | |
| 639 | + "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", | |
| 640 | + "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", | |
| 641 | + "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", | |
| 642 | + "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", | |
| 643 | + "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", | |
| 644 | + "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", | |
| 645 | + "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", | |
| 646 | + "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", | |
| 647 | + "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", | |
| 648 | + "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", | |
| 649 | + "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", | |
| 650 | + "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", | |
| 651 | + "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", | |
| 652 | + "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", | |
| 653 | + "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", | |
| 654 | + "WITH", "WITHOUT", | |
| 655 | + }; | |
| 656 | + int i, lwr, upr, mid, c; | |
| 657 | + if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; | |
| 658 | + for(i=0; zName[i]; i++){ | |
| 659 | + if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; | |
| 660 | + } | |
| 661 | + lwr = 0; | |
| 662 | + upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; | |
| 663 | + while( lwr<=upr ){ | |
| 664 | + mid = (lwr+upr)/2; | |
| 665 | + c = sqlite3_stricmp(azKeywords[mid], zName); | |
| 666 | + if( c==0 ) return '"'; | |
| 667 | + if( c<0 ){ | |
| 668 | + lwr = mid+1; | |
| 669 | + }else{ | |
| 670 | + upr = mid-1; | |
| 671 | + } | |
| 672 | + } | |
| 673 | + return 0; | |
| 674 | +} | |
| 675 | + | |
| 676 | +/****************************************************************************** | |
| 677 | +** SHA3 hash implementation copied from ../ext/misc/shathree.c | |
| 678 | +*/ | |
| 679 | +typedef sqlite3_uint64 u64; | |
| 680 | +/* | |
| 681 | +** Macros to determine whether the machine is big or little endian, | |
| 682 | +** and whether or not that determination is run-time or compile-time. | |
| 683 | +** | |
| 684 | +** For best performance, an attempt is made to guess at the byte-order | |
| 685 | +** using C-preprocessor macros. If that is unsuccessful, or if | |
| 686 | +** -DSHA3_BYTEORDER=0 is set, then byte-order is determined | |
| 687 | +** at run-time. | |
| 688 | +*/ | |
| 689 | +#ifndef SHA3_BYTEORDER | |
| 690 | +# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ | |
| 691 | + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ | |
| 692 | + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ | |
| 693 | + defined(__arm__) | |
| 694 | +# define SHA3_BYTEORDER 1234 | |
| 695 | +# elif defined(sparc) || defined(__ppc__) | |
| 696 | +# define SHA3_BYTEORDER 4321 | |
| 697 | +# else | |
| 698 | +# define SHA3_BYTEORDER 0 | |
| 699 | +# endif | |
| 700 | +#endif | |
| 701 | + | |
| 702 | + | |
| 703 | +/* | |
| 704 | +** State structure for a SHA3 hash in progress | |
| 705 | +*/ | |
| 706 | +typedef struct SHA3Context SHA3Context; | |
| 707 | +struct SHA3Context { | |
| 708 | + union { | |
| 709 | + u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ | |
| 710 | + unsigned char x[1600]; /* ... or 1600 bytes */ | |
| 711 | + } u; | |
| 712 | + unsigned nRate; /* Bytes of input accepted per Keccak iteration */ | |
| 713 | + unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ | |
| 714 | + unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ | |
| 715 | +}; | |
| 716 | + | |
| 717 | +/* | |
| 718 | +** A single step of the Keccak mixing function for a 1600-bit state | |
| 719 | +*/ | |
| 720 | +static void KeccakF1600Step(SHA3Context *p){ | |
| 721 | + int i; | |
| 722 | + u64 B0, B1, B2, B3, B4; | |
| 723 | + u64 C0, C1, C2, C3, C4; | |
| 724 | + u64 D0, D1, D2, D3, D4; | |
| 725 | + static const u64 RC[] = { | |
| 726 | + 0x0000000000000001ULL, 0x0000000000008082ULL, | |
| 727 | + 0x800000000000808aULL, 0x8000000080008000ULL, | |
| 728 | + 0x000000000000808bULL, 0x0000000080000001ULL, | |
| 729 | + 0x8000000080008081ULL, 0x8000000000008009ULL, | |
| 730 | + 0x000000000000008aULL, 0x0000000000000088ULL, | |
| 731 | + 0x0000000080008009ULL, 0x000000008000000aULL, | |
| 732 | + 0x000000008000808bULL, 0x800000000000008bULL, | |
| 733 | + 0x8000000000008089ULL, 0x8000000000008003ULL, | |
| 734 | + 0x8000000000008002ULL, 0x8000000000000080ULL, | |
| 735 | + 0x000000000000800aULL, 0x800000008000000aULL, | |
| 736 | + 0x8000000080008081ULL, 0x8000000000008080ULL, | |
| 737 | + 0x0000000080000001ULL, 0x8000000080008008ULL | |
| 738 | + }; | |
| 739 | +# define A00 (p->u.s[0]) | |
| 740 | +# define A01 (p->u.s[1]) | |
| 741 | +# define A02 (p->u.s[2]) | |
| 742 | +# define A03 (p->u.s[3]) | |
| 743 | +# define A04 (p->u.s[4]) | |
| 744 | +# define A10 (p->u.s[5]) | |
| 745 | +# define A11 (p->u.s[6]) | |
| 746 | +# define A12 (p->u.s[7]) | |
| 747 | +# define A13 (p->u.s[8]) | |
| 748 | +# define A14 (p->u.s[9]) | |
| 749 | +# define A20 (p->u.s[10]) | |
| 750 | +# define A21 (p->u.s[11]) | |
| 751 | +# define A22 (p->u.s[12]) | |
| 752 | +# define A23 (p->u.s[13]) | |
| 753 | +# define A24 (p->u.s[14]) | |
| 754 | +# define A30 (p->u.s[15]) | |
| 755 | +# define A31 (p->u.s[16]) | |
| 756 | +# define A32 (p->u.s[17]) | |
| 757 | +# define A33 (p->u.s[18]) | |
| 758 | +# define A34 (p->u.s[19]) | |
| 759 | +# define A40 (p->u.s[20]) | |
| 760 | +# define A41 (p->u.s[21]) | |
| 761 | +# define A42 (p->u.s[22]) | |
| 762 | +# define A43 (p->u.s[23]) | |
| 763 | +# define A44 (p->u.s[24]) | |
| 764 | +# define ROL64(a,x) ((a<<x)|(a>>(64-x))) | |
| 765 | + | |
| 766 | + for(i=0; i<24; i+=4){ | |
| 767 | + C0 = A00^A10^A20^A30^A40; | |
| 768 | + C1 = A01^A11^A21^A31^A41; | |
| 769 | + C2 = A02^A12^A22^A32^A42; | |
| 770 | + C3 = A03^A13^A23^A33^A43; | |
| 771 | + C4 = A04^A14^A24^A34^A44; | |
| 772 | + D0 = C4^ROL64(C1, 1); | |
| 773 | + D1 = C0^ROL64(C2, 1); | |
| 774 | + D2 = C1^ROL64(C3, 1); | |
| 775 | + D3 = C2^ROL64(C4, 1); | |
| 776 | + D4 = C3^ROL64(C0, 1); | |
| 777 | + | |
| 778 | + B0 = (A00^D0); | |
| 779 | + B1 = ROL64((A11^D1), 44); | |
| 780 | + B2 = ROL64((A22^D2), 43); | |
| 781 | + B3 = ROL64((A33^D3), 21); | |
| 782 | + B4 = ROL64((A44^D4), 14); | |
| 783 | + A00 = B0 ^((~B1)& B2 ); | |
| 784 | + A00 ^= RC[i]; | |
| 785 | + A11 = B1 ^((~B2)& B3 ); | |
| 786 | + A22 = B2 ^((~B3)& B4 ); | |
| 787 | + A33 = B3 ^((~B4)& B0 ); | |
| 788 | + A44 = B4 ^((~B0)& B1 ); | |
| 789 | + | |
| 790 | + B2 = ROL64((A20^D0), 3); | |
| 791 | + B3 = ROL64((A31^D1), 45); | |
| 792 | + B4 = ROL64((A42^D2), 61); | |
| 793 | + B0 = ROL64((A03^D3), 28); | |
| 794 | + B1 = ROL64((A14^D4), 20); | |
| 795 | + A20 = B0 ^((~B1)& B2 ); | |
| 796 | + A31 = B1 ^((~B2)& B3 ); | |
| 797 | + A42 = B2 ^((~B3)& B4 ); | |
| 798 | + A03 = B3 ^((~B4)& B0 ); | |
| 799 | + A14 = B4 ^((~B0)& B1 ); | |
| 800 | + | |
| 801 | + B4 = ROL64((A40^D0), 18); | |
| 802 | + B0 = ROL64((A01^D1), 1); | |
| 803 | + B1 = ROL64((A12^D2), 6); | |
| 804 | + B2 = ROL64((A23^D3), 25); | |
| 805 | + B3 = ROL64((A34^D4), 8); | |
| 806 | + A40 = B0 ^((~B1)& B2 ); | |
| 807 | + A01 = B1 ^((~B2)& B3 ); | |
| 808 | + A12 = B2 ^((~B3)& B4 ); | |
| 809 | + A23 = B3 ^((~B4)& B0 ); | |
| 810 | + A34 = B4 ^((~B0)& B1 ); | |
| 811 | + | |
| 812 | + B1 = ROL64((A10^D0), 36); | |
| 813 | + B2 = ROL64((A21^D1), 10); | |
| 814 | + B3 = ROL64((A32^D2), 15); | |
| 815 | + B4 = ROL64((A43^D3), 56); | |
| 816 | + B0 = ROL64((A04^D4), 27); | |
| 817 | + A10 = B0 ^((~B1)& B2 ); | |
| 818 | + A21 = B1 ^((~B2)& B3 ); | |
| 819 | + A32 = B2 ^((~B3)& B4 ); | |
| 820 | + A43 = B3 ^((~B4)& B0 ); | |
| 821 | + A04 = B4 ^((~B0)& B1 ); | |
| 822 | + | |
| 823 | + B3 = ROL64((A30^D0), 41); | |
| 824 | + B4 = ROL64((A41^D1), 2); | |
| 825 | + B0 = ROL64((A02^D2), 62); | |
| 826 | + B1 = ROL64((A13^D3), 55); | |
| 827 | + B2 = ROL64((A24^D4), 39); | |
| 828 | + A30 = B0 ^((~B1)& B2 ); | |
| 829 | + A41 = B1 ^((~B2)& B3 ); | |
| 830 | + A02 = B2 ^((~B3)& B4 ); | |
| 831 | + A13 = B3 ^((~B4)& B0 ); | |
| 832 | + A24 = B4 ^((~B0)& B1 ); | |
| 833 | + | |
| 834 | + C0 = A00^A20^A40^A10^A30; | |
| 835 | + C1 = A11^A31^A01^A21^A41; | |
| 836 | + C2 = A22^A42^A12^A32^A02; | |
| 837 | + C3 = A33^A03^A23^A43^A13; | |
| 838 | + C4 = A44^A14^A34^A04^A24; | |
| 839 | + D0 = C4^ROL64(C1, 1); | |
| 840 | + D1 = C0^ROL64(C2, 1); | |
| 841 | + D2 = C1^ROL64(C3, 1); | |
| 842 | + D3 = C2^ROL64(C4, 1); | |
| 843 | + D4 = C3^ROL64(C0, 1); | |
| 844 | + | |
| 845 | + B0 = (A00^D0); | |
| 846 | + B1 = ROL64((A31^D1), 44); | |
| 847 | + B2 = ROL64((A12^D2), 43); | |
| 848 | + B3 = ROL64((A43^D3), 21); | |
| 849 | + B4 = ROL64((A24^D4), 14); | |
| 850 | + A00 = B0 ^((~B1)& B2 ); | |
| 851 | + A00 ^= RC[i+1]; | |
| 852 | + A31 = B1 ^((~B2)& B3 ); | |
| 853 | + A12 = B2 ^((~B3)& B4 ); | |
| 854 | + A43 = B3 ^((~B4)& B0 ); | |
| 855 | + A24 = B4 ^((~B0)& B1 ); | |
| 856 | + | |
| 857 | + B2 = ROL64((A40^D0), 3); | |
| 858 | + B3 = ROL64((A21^D1), 45); | |
| 859 | + B4 = ROL64((A02^D2), 61); | |
| 860 | + B0 = ROL64((A33^D3), 28); | |
| 861 | + B1 = ROL64((A14^D4), 20); | |
| 862 | + A40 = B0 ^((~B1)& B2 ); | |
| 863 | + A21 = B1 ^((~B2)& B3 ); | |
| 864 | + A02 = B2 ^((~B3)& B4 ); | |
| 865 | + A33 = B3 ^((~B4)& B0 ); | |
| 866 | + A14 = B4 ^((~B0)& B1 ); | |
| 867 | + | |
| 868 | + B4 = ROL64((A30^D0), 18); | |
| 869 | + B0 = ROL64((A11^D1), 1); | |
| 870 | + B1 = ROL64((A42^D2), 6); | |
| 871 | + B2 = ROL64((A23^D3), 25); | |
| 872 | + B3 = ROL64((A04^D4), 8); | |
| 873 | + A30 = B0 ^((~B1)& B2 ); | |
| 874 | + A11 = B1 ^((~B2)& B3 ); | |
| 875 | + A42 = B2 ^((~B3)& B4 ); | |
| 876 | + A23 = B3 ^((~B4)& B0 ); | |
| 877 | + A04 = B4 ^((~B0)& B1 ); | |
| 878 | + | |
| 879 | + B1 = ROL64((A20^D0), 36); | |
| 880 | + B2 = ROL64((A01^D1), 10); | |
| 881 | + B3 = ROL64((A32^D2), 15); | |
| 882 | + B4 = ROL64((A13^D3), 56); | |
| 883 | + B0 = ROL64((A44^D4), 27); | |
| 884 | + A20 = B0 ^((~B1)& B2 ); | |
| 885 | + A01 = B1 ^((~B2)& B3 ); | |
| 886 | + A32 = B2 ^((~B3)& B4 ); | |
| 887 | + A13 = B3 ^((~B4)& B0 ); | |
| 888 | + A44 = B4 ^((~B0)& B1 ); | |
| 889 | + | |
| 890 | + B3 = ROL64((A10^D0), 41); | |
| 891 | + B4 = ROL64((A41^D1), 2); | |
| 892 | + B0 = ROL64((A22^D2), 62); | |
| 893 | + B1 = ROL64((A03^D3), 55); | |
| 894 | + B2 = ROL64((A34^D4), 39); | |
| 895 | + A10 = B0 ^((~B1)& B2 ); | |
| 896 | + A41 = B1 ^((~B2)& B3 ); | |
| 897 | + A22 = B2 ^((~B3)& B4 ); | |
| 898 | + A03 = B3 ^((~B4)& B0 ); | |
| 899 | + A34 = B4 ^((~B0)& B1 ); | |
| 900 | + | |
| 901 | + C0 = A00^A40^A30^A20^A10; | |
| 902 | + C1 = A31^A21^A11^A01^A41; | |
| 903 | + C2 = A12^A02^A42^A32^A22; | |
| 904 | + C3 = A43^A33^A23^A13^A03; | |
| 905 | + C4 = A24^A14^A04^A44^A34; | |
| 906 | + D0 = C4^ROL64(C1, 1); | |
| 907 | + D1 = C0^ROL64(C2, 1); | |
| 908 | + D2 = C1^ROL64(C3, 1); | |
| 909 | + D3 = C2^ROL64(C4, 1); | |
| 910 | + D4 = C3^ROL64(C0, 1); | |
| 911 | + | |
| 912 | + B0 = (A00^D0); | |
| 913 | + B1 = ROL64((A21^D1), 44); | |
| 914 | + B2 = ROL64((A42^D2), 43); | |
| 915 | + B3 = ROL64((A13^D3), 21); | |
| 916 | + B4 = ROL64((A34^D4), 14); | |
| 917 | + A00 = B0 ^((~B1)& B2 ); | |
| 918 | + A00 ^= RC[i+2]; | |
| 919 | + A21 = B1 ^((~B2)& B3 ); | |
| 920 | + A42 = B2 ^((~B3)& B4 ); | |
| 921 | + A13 = B3 ^((~B4)& B0 ); | |
| 922 | + A34 = B4 ^((~B0)& B1 ); | |
| 923 | + | |
| 924 | + B2 = ROL64((A30^D0), 3); | |
| 925 | + B3 = ROL64((A01^D1), 45); | |
| 926 | + B4 = ROL64((A22^D2), 61); | |
| 927 | + B0 = ROL64((A43^D3), 28); | |
| 928 | + B1 = ROL64((A14^D4), 20); | |
| 929 | + A30 = B0 ^((~B1)& B2 ); | |
| 930 | + A01 = B1 ^((~B2)& B3 ); | |
| 931 | + A22 = B2 ^((~B3)& B4 ); | |
| 932 | + A43 = B3 ^((~B4)& B0 ); | |
| 933 | + A14 = B4 ^((~B0)& B1 ); | |
| 934 | + | |
| 935 | + B4 = ROL64((A10^D0), 18); | |
| 936 | + B0 = ROL64((A31^D1), 1); | |
| 937 | + B1 = ROL64((A02^D2), 6); | |
| 938 | + B2 = ROL64((A23^D3), 25); | |
| 939 | + B3 = ROL64((A44^D4), 8); | |
| 940 | + A10 = B0 ^((~B1)& B2 ); | |
| 941 | + A31 = B1 ^((~B2)& B3 ); | |
| 942 | + A02 = B2 ^((~B3)& B4 ); | |
| 943 | + A23 = B3 ^((~B4)& B0 ); | |
| 944 | + A44 = B4 ^((~B0)& B1 ); | |
| 945 | + | |
| 946 | + B1 = ROL64((A40^D0), 36); | |
| 947 | + B2 = ROL64((A11^D1), 10); | |
| 948 | + B3 = ROL64((A32^D2), 15); | |
| 949 | + B4 = ROL64((A03^D3), 56); | |
| 950 | + B0 = ROL64((A24^D4), 27); | |
| 951 | + A40 = B0 ^((~B1)& B2 ); | |
| 952 | + A11 = B1 ^((~B2)& B3 ); | |
| 953 | + A32 = B2 ^((~B3)& B4 ); | |
| 954 | + A03 = B3 ^((~B4)& B0 ); | |
| 955 | + A24 = B4 ^((~B0)& B1 ); | |
| 956 | + | |
| 957 | + B3 = ROL64((A20^D0), 41); | |
| 958 | + B4 = ROL64((A41^D1), 2); | |
| 959 | + B0 = ROL64((A12^D2), 62); | |
| 960 | + B1 = ROL64((A33^D3), 55); | |
| 961 | + B2 = ROL64((A04^D4), 39); | |
| 962 | + A20 = B0 ^((~B1)& B2 ); | |
| 963 | + A41 = B1 ^((~B2)& B3 ); | |
| 964 | + A12 = B2 ^((~B3)& B4 ); | |
| 965 | + A33 = B3 ^((~B4)& B0 ); | |
| 966 | + A04 = B4 ^((~B0)& B1 ); | |
| 967 | + | |
| 968 | + C0 = A00^A30^A10^A40^A20; | |
| 969 | + C1 = A21^A01^A31^A11^A41; | |
| 970 | + C2 = A42^A22^A02^A32^A12; | |
| 971 | + C3 = A13^A43^A23^A03^A33; | |
| 972 | + C4 = A34^A14^A44^A24^A04; | |
| 973 | + D0 = C4^ROL64(C1, 1); | |
| 974 | + D1 = C0^ROL64(C2, 1); | |
| 975 | + D2 = C1^ROL64(C3, 1); | |
| 976 | + D3 = C2^ROL64(C4, 1); | |
| 977 | + D4 = C3^ROL64(C0, 1); | |
| 978 | + | |
| 979 | + B0 = (A00^D0); | |
| 980 | + B1 = ROL64((A01^D1), 44); | |
| 981 | + B2 = ROL64((A02^D2), 43); | |
| 982 | + B3 = ROL64((A03^D3), 21); | |
| 983 | + B4 = ROL64((A04^D4), 14); | |
| 984 | + A00 = B0 ^((~B1)& B2 ); | |
| 985 | + A00 ^= RC[i+3]; | |
| 986 | + A01 = B1 ^((~B2)& B3 ); | |
| 987 | + A02 = B2 ^((~B3)& B4 ); | |
| 988 | + A03 = B3 ^((~B4)& B0 ); | |
| 989 | + A04 = B4 ^((~B0)& B1 ); | |
| 990 | + | |
| 991 | + B2 = ROL64((A10^D0), 3); | |
| 992 | + B3 = ROL64((A11^D1), 45); | |
| 993 | + B4 = ROL64((A12^D2), 61); | |
| 994 | + B0 = ROL64((A13^D3), 28); | |
| 995 | + B1 = ROL64((A14^D4), 20); | |
| 996 | + A10 = B0 ^((~B1)& B2 ); | |
| 997 | + A11 = B1 ^((~B2)& B3 ); | |
| 998 | + A12 = B2 ^((~B3)& B4 ); | |
| 999 | + A13 = B3 ^((~B4)& B0 ); | |
| 1000 | + A14 = B4 ^((~B0)& B1 ); | |
| 1001 | + | |
| 1002 | + B4 = ROL64((A20^D0), 18); | |
| 1003 | + B0 = ROL64((A21^D1), 1); | |
| 1004 | + B1 = ROL64((A22^D2), 6); | |
| 1005 | + B2 = ROL64((A23^D3), 25); | |
| 1006 | + B3 = ROL64((A24^D4), 8); | |
| 1007 | + A20 = B0 ^((~B1)& B2 ); | |
| 1008 | + A21 = B1 ^((~B2)& B3 ); | |
| 1009 | + A22 = B2 ^((~B3)& B4 ); | |
| 1010 | + A23 = B3 ^((~B4)& B0 ); | |
| 1011 | + A24 = B4 ^((~B0)& B1 ); | |
| 1012 | + | |
| 1013 | + B1 = ROL64((A30^D0), 36); | |
| 1014 | + B2 = ROL64((A31^D1), 10); | |
| 1015 | + B3 = ROL64((A32^D2), 15); | |
| 1016 | + B4 = ROL64((A33^D3), 56); | |
| 1017 | + B0 = ROL64((A34^D4), 27); | |
| 1018 | + A30 = B0 ^((~B1)& B2 ); | |
| 1019 | + A31 = B1 ^((~B2)& B3 ); | |
| 1020 | + A32 = B2 ^((~B3)& B4 ); | |
| 1021 | + A33 = B3 ^((~B4)& B0 ); | |
| 1022 | + A34 = B4 ^((~B0)& B1 ); | |
| 1023 | + | |
| 1024 | + B3 = ROL64((A40^D0), 41); | |
| 1025 | + B4 = ROL64((A41^D1), 2); | |
| 1026 | + B0 = ROL64((A42^D2), 62); | |
| 1027 | + B1 = ROL64((A43^D3), 55); | |
| 1028 | + B2 = ROL64((A44^D4), 39); | |
| 1029 | + A40 = B0 ^((~B1)& B2 ); | |
| 1030 | + A41 = B1 ^((~B2)& B3 ); | |
| 1031 | + A42 = B2 ^((~B3)& B4 ); | |
| 1032 | + A43 = B3 ^((~B4)& B0 ); | |
| 1033 | + A44 = B4 ^((~B0)& B1 ); | |
| 1034 | + } | |
| 1035 | +} | |
| 1036 | + | |
| 1037 | +/* | |
| 1038 | +** Initialize a new hash. iSize determines the size of the hash | |
| 1039 | +** in bits and should be one of 224, 256, 384, or 512. Or iSize | |
| 1040 | +** can be zero to use the default hash size of 256 bits. | |
| 1041 | +*/ | |
| 1042 | +static void SHA3Init(SHA3Context *p, int iSize){ | |
| 1043 | + memset(p, 0, sizeof(*p)); | |
| 1044 | + if( iSize>=128 && iSize<=512 ){ | |
| 1045 | + p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; | |
| 1046 | + }else{ | |
| 1047 | + p->nRate = (1600 - 2*256)/8; | |
| 1048 | + } | |
| 1049 | +#if SHA3_BYTEORDER==1234 | |
| 1050 | + /* Known to be little-endian at compile-time. No-op */ | |
| 1051 | +#elif SHA3_BYTEORDER==4321 | |
| 1052 | + p->ixMask = 7; /* Big-endian */ | |
| 1053 | +#else | |
| 1054 | + { | |
| 1055 | + static unsigned int one = 1; | |
| 1056 | + if( 1==*(unsigned char*)&one ){ | |
| 1057 | + /* Little endian. No byte swapping. */ | |
| 1058 | + p->ixMask = 0; | |
| 1059 | + }else{ | |
| 1060 | + /* Big endian. Byte swap. */ | |
| 1061 | + p->ixMask = 7; | |
| 1062 | + } | |
| 1063 | + } | |
| 1064 | +#endif | |
| 1065 | +} | |
| 1066 | + | |
| 1067 | +/* | |
| 1068 | +** Make consecutive calls to the SHA3Update function to add new content | |
| 1069 | +** to the hash | |
| 1070 | +*/ | |
| 1071 | +static void SHA3Update( | |
| 1072 | + SHA3Context *p, | |
| 1073 | + const unsigned char *aData, | |
| 1074 | + unsigned int nData | |
| 1075 | +){ | |
| 1076 | + unsigned int i = 0; | |
| 1077 | +#if SHA3_BYTEORDER==1234 | |
| 1078 | + if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ | |
| 1079 | + for(; i+7<nData; i+=8){ | |
| 1080 | + p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; | |
| 1081 | + p->nLoaded += 8; | |
| 1082 | + if( p->nLoaded>=p->nRate ){ | |
| 1083 | + KeccakF1600Step(p); | |
| 1084 | + p->nLoaded = 0; | |
| 1085 | + } | |
| 1086 | + } | |
| 1087 | + } | |
| 1088 | +#endif | |
| 1089 | + for(; i<nData; i++){ | |
| 1090 | +#if SHA3_BYTEORDER==1234 | |
| 1091 | + p->u.x[p->nLoaded] ^= aData[i]; | |
| 1092 | +#elif SHA3_BYTEORDER==4321 | |
| 1093 | + p->u.x[p->nLoaded^0x07] ^= aData[i]; | |
| 1094 | +#else | |
| 1095 | + p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; | |
| 1096 | +#endif | |
| 1097 | + p->nLoaded++; | |
| 1098 | + if( p->nLoaded==p->nRate ){ | |
| 1099 | + KeccakF1600Step(p); | |
| 1100 | + p->nLoaded = 0; | |
| 1101 | + } | |
| 1102 | + } | |
| 1103 | +} | |
| 1104 | + | |
| 1105 | +/* | |
| 1106 | +** After all content has been added, invoke SHA3Final() to compute | |
| 1107 | +** the final hash. The function returns a pointer to the binary | |
| 1108 | +** hash value. | |
| 1109 | +*/ | |
| 1110 | +static unsigned char *SHA3Final(SHA3Context *p){ | |
| 1111 | + unsigned int i; | |
| 1112 | + if( p->nLoaded==p->nRate-1 ){ | |
| 1113 | + const unsigned char c1 = 0x86; | |
| 1114 | + SHA3Update(p, &c1, 1); | |
| 1115 | + }else{ | |
| 1116 | + const unsigned char c2 = 0x06; | |
| 1117 | + const unsigned char c3 = 0x80; | |
| 1118 | + SHA3Update(p, &c2, 1); | |
| 1119 | + p->nLoaded = p->nRate - 1; | |
| 1120 | + SHA3Update(p, &c3, 1); | |
| 1121 | + } | |
| 1122 | + for(i=0; i<p->nRate; i++){ | |
| 1123 | + p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; | |
| 1124 | + } | |
| 1125 | + return &p->u.x[p->nRate]; | |
| 1126 | +} | |
| 1127 | + | |
| 1128 | +/* | |
| 1129 | +** Implementation of the sha3(X,SIZE) function. | |
| 1130 | +** | |
| 1131 | +** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default | |
| 1132 | +** size is 256. If X is a BLOB, it is hashed as is. | |
| 1133 | +** For all other non-NULL types of input, X is converted into a UTF-8 string | |
| 1134 | +** and the string is hashed without the trailing 0x00 terminator. The hash | |
| 1135 | +** of a NULL value is NULL. | |
| 1136 | +*/ | |
| 1137 | +static void sha3Func( | |
| 1138 | + sqlite3_context *context, | |
| 1139 | + int argc, | |
| 1140 | + sqlite3_value **argv | |
| 1141 | +){ | |
| 1142 | + SHA3Context cx; | |
| 1143 | + int eType = sqlite3_value_type(argv[0]); | |
| 1144 | + int nByte = sqlite3_value_bytes(argv[0]); | |
| 1145 | + int iSize; | |
| 1146 | + if( argc==1 ){ | |
| 1147 | + iSize = 256; | |
| 1148 | + }else{ | |
| 1149 | + iSize = sqlite3_value_int(argv[1]); | |
| 1150 | + if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ | |
| 1151 | + sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " | |
| 1152 | + "384 512", -1); | |
| 1153 | + return; | |
| 1154 | + } | |
| 1155 | + } | |
| 1156 | + if( eType==SQLITE_NULL ) return; | |
| 1157 | + SHA3Init(&cx, iSize); | |
| 1158 | + if( eType==SQLITE_BLOB ){ | |
| 1159 | + SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); | |
| 1160 | + }else{ | |
| 1161 | + SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); | |
| 1162 | + } | |
| 1163 | + sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); | |
| 1164 | +} | |
| 1165 | + | |
| 1166 | +/* Compute a string using sqlite3_vsnprintf() with a maximum length | |
| 1167 | +** of 50 bytes and add it to the hash. | |
| 1168 | +*/ | |
| 1169 | +static void hash_step_vformat( | |
| 1170 | + SHA3Context *p, /* Add content to this context */ | |
| 1171 | + const char *zFormat, | |
| 1172 | + ... | |
| 1173 | +){ | |
| 1174 | + va_list ap; | |
| 1175 | + int n; | |
| 1176 | + char zBuf[50]; | |
| 1177 | + va_start(ap, zFormat); | |
| 1178 | + sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); | |
| 1179 | + va_end(ap); | |
| 1180 | + n = (int)strlen(zBuf); | |
| 1181 | + SHA3Update(p, (unsigned char*)zBuf, n); | |
| 1182 | +} | |
| 1183 | + | |
| 1184 | +/* | |
| 1185 | +** Implementation of the sha3_query(SQL,SIZE) function. | |
| 1186 | +** | |
| 1187 | +** This function compiles and runs the SQL statement(s) given in the | |
| 1188 | +** argument. The results are hashed using a SIZE-bit SHA3. The default | |
| 1189 | +** size is 256. | |
| 1190 | +** | |
| 1191 | +** The format of the byte stream that is hashed is summarized as follows: | |
| 1192 | +** | |
| 1193 | +** S<n>:<sql> | |
| 1194 | +** R | |
| 1195 | +** N | |
| 1196 | +** I<int> | |
| 1197 | +** F<ieee-float> | |
| 1198 | +** B<size>:<bytes> | |
| 1199 | +** T<size>:<text> | |
| 1200 | +** | |
| 1201 | +** <sql> is the original SQL text for each statement run and <n> is | |
| 1202 | +** the size of that text. The SQL text is UTF-8. A single R character | |
| 1203 | +** occurs before the start of each row. N means a NULL value. | |
| 1204 | +** I mean an 8-byte little-endian integer <int>. F is a floating point | |
| 1205 | +** number with an 8-byte little-endian IEEE floating point value <ieee-float>. | |
| 1206 | +** B means blobs of <size> bytes. T means text rendered as <size> | |
| 1207 | +** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII | |
| 1208 | +** text integers. | |
| 1209 | +** | |
| 1210 | +** For each SQL statement in the X input, there is one S segment. Each | |
| 1211 | +** S segment is followed by zero or more R segments, one for each row in the | |
| 1212 | +** result set. After each R, there are one or more N, I, F, B, or T segments, | |
| 1213 | +** one for each column in the result set. Segments are concatentated directly | |
| 1214 | +** with no delimiters of any kind. | |
| 1215 | +*/ | |
| 1216 | +static void sha3QueryFunc( | |
| 1217 | + sqlite3_context *context, | |
| 1218 | + int argc, | |
| 1219 | + sqlite3_value **argv | |
| 1220 | +){ | |
| 1221 | + sqlite3 *db = sqlite3_context_db_handle(context); | |
| 1222 | + const char *zSql = (const char*)sqlite3_value_text(argv[0]); | |
| 1223 | + sqlite3_stmt *pStmt = 0; | |
| 1224 | + int nCol; /* Number of columns in the result set */ | |
| 1225 | + int i; /* Loop counter */ | |
| 1226 | + int rc; | |
| 1227 | + int n; | |
| 1228 | + const char *z; | |
| 1229 | + SHA3Context cx; | |
| 1230 | + int iSize; | |
| 1231 | + | |
| 1232 | + if( argc==1 ){ | |
| 1233 | + iSize = 256; | |
| 1234 | + }else{ | |
| 1235 | + iSize = sqlite3_value_int(argv[1]); | |
| 1236 | + if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ | |
| 1237 | + sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " | |
| 1238 | + "384 512", -1); | |
| 1239 | + return; | |
| 1240 | + } | |
| 1241 | + } | |
| 1242 | + if( zSql==0 ) return; | |
| 1243 | + SHA3Init(&cx, iSize); | |
| 1244 | + while( zSql[0] ){ | |
| 1245 | + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); | |
| 1246 | + if( rc ){ | |
| 1247 | + char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", | |
| 1248 | + zSql, sqlite3_errmsg(db)); | |
| 1249 | + sqlite3_finalize(pStmt); | |
| 1250 | + sqlite3_result_error(context, zMsg, -1); | |
| 1251 | + sqlite3_free(zMsg); | |
| 1252 | + return; | |
| 1253 | + } | |
| 1254 | + if( !sqlite3_stmt_readonly(pStmt) ){ | |
| 1255 | + char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); | |
| 1256 | + sqlite3_finalize(pStmt); | |
| 1257 | + sqlite3_result_error(context, zMsg, -1); | |
| 1258 | + sqlite3_free(zMsg); | |
| 1259 | + return; | |
| 1260 | + } | |
| 1261 | + nCol = sqlite3_column_count(pStmt); | |
| 1262 | + z = sqlite3_sql(pStmt); | |
| 1263 | + if( z==0 ){ | |
| 1264 | + sqlite3_finalize(pStmt); | |
| 1265 | + continue; | |
| 1266 | + } | |
| 1267 | + n = (int)strlen(z); | |
| 1268 | + hash_step_vformat(&cx,"S%d:",n); | |
| 1269 | + SHA3Update(&cx,(unsigned char*)z,n); | |
| 1270 | + | |
| 1271 | + /* Compute a hash over the result of the query */ | |
| 1272 | + while( SQLITE_ROW==sqlite3_step(pStmt) ){ | |
| 1273 | + SHA3Update(&cx,(const unsigned char*)"R",1); | |
| 1274 | + for(i=0; i<nCol; i++){ | |
| 1275 | + switch( sqlite3_column_type(pStmt,i) ){ | |
| 1276 | + case SQLITE_NULL: { | |
| 1277 | + SHA3Update(&cx, (const unsigned char*)"N",1); | |
| 1278 | + break; | |
| 1279 | + } | |
| 1280 | + case SQLITE_INTEGER: { | |
| 1281 | + sqlite3_uint64 u; | |
| 1282 | + int j; | |
| 1283 | + unsigned char x[9]; | |
| 1284 | + sqlite3_int64 v = sqlite3_column_int64(pStmt,i); | |
| 1285 | + memcpy(&u, &v, 8); | |
| 1286 | + for(j=8; j>=1; j--){ | |
| 1287 | + x[j] = u & 0xff; | |
| 1288 | + u >>= 8; | |
| 1289 | + } | |
| 1290 | + x[0] = 'I'; | |
| 1291 | + SHA3Update(&cx, x, 9); | |
| 1292 | + break; | |
| 1293 | + } | |
| 1294 | + case SQLITE_FLOAT: { | |
| 1295 | + sqlite3_uint64 u; | |
| 1296 | + int j; | |
| 1297 | + unsigned char x[9]; | |
| 1298 | + double r = sqlite3_column_double(pStmt,i); | |
| 1299 | + memcpy(&u, &r, 8); | |
| 1300 | + for(j=8; j>=1; j--){ | |
| 1301 | + x[j] = u & 0xff; | |
| 1302 | + u >>= 8; | |
| 1303 | + } | |
| 1304 | + x[0] = 'F'; | |
| 1305 | + SHA3Update(&cx,x,9); | |
| 1306 | + break; | |
| 1307 | + } | |
| 1308 | + case SQLITE_TEXT: { | |
| 1309 | + int n2 = sqlite3_column_bytes(pStmt, i); | |
| 1310 | + const unsigned char *z2 = sqlite3_column_text(pStmt, i); | |
| 1311 | + hash_step_vformat(&cx,"T%d:",n2); | |
| 1312 | + SHA3Update(&cx, z2, n2); | |
| 1313 | + break; | |
| 1314 | + } | |
| 1315 | + case SQLITE_BLOB: { | |
| 1316 | + int n2 = sqlite3_column_bytes(pStmt, i); | |
| 1317 | + const unsigned char *z2 = sqlite3_column_blob(pStmt, i); | |
| 1318 | + hash_step_vformat(&cx,"B%d:",n2); | |
| 1319 | + SHA3Update(&cx, z2, n2); | |
| 1320 | + break; | |
| 1321 | + } | |
| 1322 | + } | |
| 1323 | + } | |
| 1324 | + } | |
| 1325 | + sqlite3_finalize(pStmt); | |
| 1326 | + } | |
| 1327 | + sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); | |
| 1328 | +} | |
| 1329 | +/* End of SHA3 hashing logic copy/pasted from ../ext/misc/shathree.c | |
| 1330 | +********************************************************************************/ | |
| 580 | 1331 | |
| 581 | 1332 | #if defined(SQLITE_ENABLE_SESSION) |
| 582 | 1333 | /* |
| 583 | 1334 | ** State information for a single open session |
| 584 | 1335 | */ |
| @@ -608,17 +1359,14 @@ | ||
| 608 | 1359 | ** instance of the following structure. |
| 609 | 1360 | */ |
| 610 | 1361 | typedef struct ShellState ShellState; |
| 611 | 1362 | struct ShellState { |
| 612 | 1363 | sqlite3 *db; /* The database */ |
| 613 | - int echoOn; /* True to echo input commands */ | |
| 614 | 1364 | int autoExplain; /* Automatically turn on .explain mode */ |
| 615 | 1365 | int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
| 616 | 1366 | int statsOn; /* True to display memory stats before each finalize */ |
| 617 | 1367 | int scanstatsOn; /* True to display scan stats before each finalize */ |
| 618 | - int countChanges; /* True to display change counts */ | |
| 619 | - int backslashOn; /* Resolve C-style \x escapes in SQL input text */ | |
| 620 | 1368 | int outCount; /* Revert to stdout when reaching zero */ |
| 621 | 1369 | int cnt; /* Number of records displayed so far */ |
| 622 | 1370 | FILE *out; /* Write results here */ |
| 623 | 1371 | FILE *traceOut; /* Output for sqlite3_trace() */ |
| 624 | 1372 | int nErr; /* Number of errors seen */ |
| @@ -653,13 +1401,24 @@ | ||
| 653 | 1401 | }; |
| 654 | 1402 | |
| 655 | 1403 | /* |
| 656 | 1404 | ** These are the allowed shellFlgs values |
| 657 | 1405 | */ |
| 658 | -#define SHFLG_Scratch 0x00001 /* The --scratch option is used */ | |
| 659 | -#define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ | |
| 660 | -#define SHFLG_Lookaside 0x00004 /* Lookaside memory is used */ | |
| 1406 | +#define SHFLG_Scratch 0x00000001 /* The --scratch option is used */ | |
| 1407 | +#define SHFLG_Pagecache 0x00000002 /* The --pagecache option is used */ | |
| 1408 | +#define SHFLG_Lookaside 0x00000004 /* Lookaside memory is used */ | |
| 1409 | +#define SHFLG_Backslash 0x00000008 /* The --backslash option is used */ | |
| 1410 | +#define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */ | |
| 1411 | +#define SHFLG_CountChanges 0x00000020 /* .changes setting */ | |
| 1412 | +#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */ | |
| 1413 | + | |
| 1414 | +/* | |
| 1415 | +** Macros for testing and setting shellFlgs | |
| 1416 | +*/ | |
| 1417 | +#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0) | |
| 1418 | +#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X)) | |
| 1419 | +#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X))) | |
| 661 | 1420 | |
| 662 | 1421 | /* |
| 663 | 1422 | ** These are the allowed modes. |
| 664 | 1423 | */ |
| 665 | 1424 | #define MODE_Line 0 /* One column per line. Blank line between records */ |
| @@ -1292,92 +2051,106 @@ | ||
| 1292 | 2051 | */ |
| 1293 | 2052 | static int callback(void *pArg, int nArg, char **azArg, char **azCol){ |
| 1294 | 2053 | /* since we don't have type info, call the shell_callback with a NULL value */ |
| 1295 | 2054 | return shell_callback(pArg, nArg, azArg, azCol, NULL); |
| 1296 | 2055 | } |
| 2056 | + | |
| 2057 | +/* | |
| 2058 | +** This is the callback routine from sqlite3_exec() that appends all | |
| 2059 | +** output onto the end of a ShellText object. | |
| 2060 | +*/ | |
| 2061 | +static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){ | |
| 2062 | + ShellText *p = (ShellText*)pArg; | |
| 2063 | + int i; | |
| 2064 | + if( p->n ) appendText(p, "|", 0); | |
| 2065 | + for(i=0; i<nArg; i++){ | |
| 2066 | + if( i ) appendText(p, ",", 0); | |
| 2067 | + if( azArg[i] ) appendText(p, azArg[i], 0); | |
| 2068 | + } | |
| 2069 | + return 0; | |
| 2070 | +} | |
| 2071 | + | |
| 2072 | +/* | |
| 2073 | +** Generate an appropriate SELFTEST table in the main database. | |
| 2074 | +*/ | |
| 2075 | +static void createSelftestTable(ShellState *p){ | |
| 2076 | + char *zErrMsg = 0; | |
| 2077 | + sqlite3_exec(p->db, | |
| 2078 | + "SAVEPOINT selftest_init;\n" | |
| 2079 | + "CREATE TABLE IF NOT EXISTS selftest(\n" | |
| 2080 | + " tno INTEGER PRIMARY KEY,\n" /* Test number */ | |
| 2081 | + " op TEXT,\n" /* Operator: memo run */ | |
| 2082 | + " cmd TEXT,\n" /* Command text */ | |
| 2083 | + " ans TEXT\n" /* Desired answer */ | |
| 2084 | + ");" | |
| 2085 | + "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n" | |
| 2086 | + "INSERT INTO [_shell$self](rowid,op,cmd)\n" | |
| 2087 | + " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n" | |
| 2088 | + " 'memo','Tests generated by --init');\n" | |
| 2089 | + "INSERT INTO [_shell$self]\n" | |
| 2090 | + " SELECT 'run',\n" | |
| 2091 | + " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql " | |
| 2092 | + "FROM sqlite_master ORDER BY 2'',224))',\n" | |
| 2093 | + " hex(sha3_query('SELECT type,name,tbl_name,sql " | |
| 2094 | + "FROM sqlite_master ORDER BY 2',224));\n" | |
| 2095 | + "INSERT INTO [_shell$self]\n" | |
| 2096 | + " SELECT 'run'," | |
| 2097 | + " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||" | |
| 2098 | + " printf('%w',name) || '\" NOT INDEXED'',224))',\n" | |
| 2099 | + " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n" | |
| 2100 | + " FROM (\n" | |
| 2101 | + " SELECT name FROM sqlite_master\n" | |
| 2102 | + " WHERE type='table'\n" | |
| 2103 | + " AND name<>'selftest'\n" | |
| 2104 | + " AND coalesce(rootpage,0)>0\n" | |
| 2105 | + " )\n" | |
| 2106 | + " ORDER BY name;\n" | |
| 2107 | + "INSERT INTO [_shell$self]\n" | |
| 2108 | + " VALUES('run','PRAGMA integrity_check','ok');\n" | |
| 2109 | + "INSERT INTO selftest(tno,op,cmd,ans)" | |
| 2110 | + " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" | |
| 2111 | + "DROP TABLE [_shell$self];" | |
| 2112 | + ,0,0,&zErrMsg); | |
| 2113 | + if( zErrMsg ){ | |
| 2114 | + utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); | |
| 2115 | + sqlite3_free(zErrMsg); | |
| 2116 | + } | |
| 2117 | + sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); | |
| 2118 | +} | |
| 2119 | + | |
| 1297 | 2120 | |
| 1298 | 2121 | /* |
| 1299 | 2122 | ** Set the destination table field of the ShellState structure to |
| 1300 | 2123 | ** the name of the table given. Escape any quote characters in the |
| 1301 | 2124 | ** table name. |
| 1302 | 2125 | */ |
| 1303 | 2126 | static void set_table_name(ShellState *p, const char *zName){ |
| 1304 | 2127 | int i, n; |
| 1305 | - int needQuote; | |
| 2128 | + int cQuote; | |
| 1306 | 2129 | char *z; |
| 1307 | 2130 | |
| 1308 | 2131 | if( p->zDestTable ){ |
| 1309 | 2132 | free(p->zDestTable); |
| 1310 | 2133 | p->zDestTable = 0; |
| 1311 | 2134 | } |
| 1312 | 2135 | if( zName==0 ) return; |
| 1313 | - needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; | |
| 1314 | - for(i=n=0; zName[i]; i++, n++){ | |
| 1315 | - if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ | |
| 1316 | - needQuote = 1; | |
| 1317 | - if( zName[i]=='\'' ) n++; | |
| 1318 | - } | |
| 1319 | - } | |
| 1320 | - if( needQuote ) n += 2; | |
| 2136 | + cQuote = quoteChar(zName); | |
| 2137 | + n = strlen30(zName); | |
| 2138 | + if( cQuote ) n += 2; | |
| 1321 | 2139 | z = p->zDestTable = malloc( n+1 ); |
| 1322 | 2140 | if( z==0 ){ |
| 1323 | 2141 | raw_printf(stderr,"Error: out of memory\n"); |
| 1324 | 2142 | exit(1); |
| 1325 | 2143 | } |
| 1326 | 2144 | n = 0; |
| 1327 | - if( needQuote ) z[n++] = '\''; | |
| 2145 | + if( cQuote ) z[n++] = cQuote; | |
| 1328 | 2146 | for(i=0; zName[i]; i++){ |
| 1329 | 2147 | z[n++] = zName[i]; |
| 1330 | - if( zName[i]=='\'' ) z[n++] = '\''; | |
| 1331 | - } | |
| 1332 | - if( needQuote ) z[n++] = '\''; | |
| 1333 | - z[n] = 0; | |
| 1334 | -} | |
| 1335 | - | |
| 1336 | -/* zIn is either a pointer to a NULL-terminated string in memory obtained | |
| 1337 | -** from malloc(), or a NULL pointer. The string pointed to by zAppend is | |
| 1338 | -** added to zIn, and the result returned in memory obtained from malloc(). | |
| 1339 | -** zIn, if it was not NULL, is freed. | |
| 1340 | -** | |
| 1341 | -** If the third argument, quote, is not '\0', then it is used as a | |
| 1342 | -** quote character for zAppend. | |
| 1343 | -*/ | |
| 1344 | -static char *appendText(char *zIn, char const *zAppend, char quote){ | |
| 1345 | - int len; | |
| 1346 | - int i; | |
| 1347 | - int nAppend = strlen30(zAppend); | |
| 1348 | - int nIn = (zIn?strlen30(zIn):0); | |
| 1349 | - | |
| 1350 | - len = nAppend+nIn+1; | |
| 1351 | - if( quote ){ | |
| 1352 | - len += 2; | |
| 1353 | - for(i=0; i<nAppend; i++){ | |
| 1354 | - if( zAppend[i]==quote ) len++; | |
| 1355 | - } | |
| 1356 | - } | |
| 1357 | - | |
| 1358 | - zIn = (char *)realloc(zIn, len); | |
| 1359 | - if( !zIn ){ | |
| 1360 | - return 0; | |
| 1361 | - } | |
| 1362 | - | |
| 1363 | - if( quote ){ | |
| 1364 | - char *zCsr = &zIn[nIn]; | |
| 1365 | - *zCsr++ = quote; | |
| 1366 | - for(i=0; i<nAppend; i++){ | |
| 1367 | - *zCsr++ = zAppend[i]; | |
| 1368 | - if( zAppend[i]==quote ) *zCsr++ = quote; | |
| 1369 | - } | |
| 1370 | - *zCsr++ = quote; | |
| 1371 | - *zCsr++ = '\0'; | |
| 1372 | - assert( (zCsr-zIn)==len ); | |
| 1373 | - }else{ | |
| 1374 | - memcpy(&zIn[nIn], zAppend, nAppend); | |
| 1375 | - zIn[len-1] = '\0'; | |
| 1376 | - } | |
| 1377 | - | |
| 1378 | - return zIn; | |
| 2148 | + if( zName[i]==cQuote ) z[n++] = cQuote; | |
| 2149 | + } | |
| 2150 | + if( cQuote ) z[n++] = cQuote; | |
| 2151 | + z[n] = 0; | |
| 1379 | 2152 | } |
| 1380 | 2153 | |
| 1381 | 2154 | |
| 1382 | 2155 | /* |
| 1383 | 2156 | ** Execute a query statement that will generate SQL output. Print |
| @@ -1484,10 +2257,35 @@ | ||
| 1484 | 2257 | } |
| 1485 | 2258 | fclose(in); |
| 1486 | 2259 | } |
| 1487 | 2260 | #endif |
| 1488 | 2261 | |
| 2262 | +/* | |
| 2263 | +** Display a single line of status using 64-bit values. | |
| 2264 | +*/ | |
| 2265 | +static void displayStatLine( | |
| 2266 | + ShellState *p, /* The shell context */ | |
| 2267 | + char *zLabel, /* Label for this one line */ | |
| 2268 | + char *zFormat, /* Format for the result */ | |
| 2269 | + int iStatusCtrl, /* Which status to display */ | |
| 2270 | + int bReset /* True to reset the stats */ | |
| 2271 | +){ | |
| 2272 | + sqlite3_int64 iCur = -1; | |
| 2273 | + sqlite3_int64 iHiwtr = -1; | |
| 2274 | + int i, nPercent; | |
| 2275 | + char zLine[200]; | |
| 2276 | + sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset); | |
| 2277 | + for(i=0, nPercent=0; zFormat[i]; i++){ | |
| 2278 | + if( zFormat[i]=='%' ) nPercent++; | |
| 2279 | + } | |
| 2280 | + if( nPercent>1 ){ | |
| 2281 | + sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr); | |
| 2282 | + }else{ | |
| 2283 | + sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr); | |
| 2284 | + } | |
| 2285 | + raw_printf(p->out, "%-36s %s\n", zLabel, zLine); | |
| 2286 | +} | |
| 1489 | 2287 | |
| 1490 | 2288 | /* |
| 1491 | 2289 | ** Display memory stats. |
| 1492 | 2290 | */ |
| 1493 | 2291 | static int display_stats( |
| @@ -1497,61 +2295,35 @@ | ||
| 1497 | 2295 | ){ |
| 1498 | 2296 | int iCur; |
| 1499 | 2297 | int iHiwtr; |
| 1500 | 2298 | |
| 1501 | 2299 | if( pArg && pArg->out ){ |
| 1502 | - | |
| 1503 | - iHiwtr = iCur = -1; | |
| 1504 | - sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); | |
| 1505 | - raw_printf(pArg->out, | |
| 1506 | - "Memory Used: %d (max %d) bytes\n", | |
| 1507 | - iCur, iHiwtr); | |
| 1508 | - iHiwtr = iCur = -1; | |
| 1509 | - sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); | |
| 1510 | - raw_printf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", | |
| 1511 | - iCur, iHiwtr); | |
| 2300 | + displayStatLine(pArg, "Memory Used:", | |
| 2301 | + "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); | |
| 2302 | + displayStatLine(pArg, "Number of Outstanding Allocations:", | |
| 2303 | + "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); | |
| 1512 | 2304 | if( pArg->shellFlgs & SHFLG_Pagecache ){ |
| 1513 | - iHiwtr = iCur = -1; | |
| 1514 | - sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); | |
| 1515 | - raw_printf(pArg->out, | |
| 1516 | - "Number of Pcache Pages Used: %d (max %d) pages\n", | |
| 1517 | - iCur, iHiwtr); | |
| 1518 | - } | |
| 1519 | - iHiwtr = iCur = -1; | |
| 1520 | - sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); | |
| 1521 | - raw_printf(pArg->out, | |
| 1522 | - "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", | |
| 1523 | - iCur, iHiwtr); | |
| 2305 | + displayStatLine(pArg, "Number of Pcache Pages Used:", | |
| 2306 | + "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); | |
| 2307 | + } | |
| 2308 | + displayStatLine(pArg, "Number of Pcache Overflow Bytes:", | |
| 2309 | + "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); | |
| 1524 | 2310 | if( pArg->shellFlgs & SHFLG_Scratch ){ |
| 1525 | - iHiwtr = iCur = -1; | |
| 1526 | - sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); | |
| 1527 | - raw_printf(pArg->out, | |
| 1528 | - "Number of Scratch Allocations Used: %d (max %d)\n", | |
| 1529 | - iCur, iHiwtr); | |
| 1530 | - } | |
| 1531 | - iHiwtr = iCur = -1; | |
| 1532 | - sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); | |
| 1533 | - raw_printf(pArg->out, | |
| 1534 | - "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", | |
| 1535 | - iCur, iHiwtr); | |
| 1536 | - iHiwtr = iCur = -1; | |
| 1537 | - sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); | |
| 1538 | - raw_printf(pArg->out, "Largest Allocation: %d bytes\n", | |
| 1539 | - iHiwtr); | |
| 1540 | - iHiwtr = iCur = -1; | |
| 1541 | - sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); | |
| 1542 | - raw_printf(pArg->out, "Largest Pcache Allocation: %d bytes\n", | |
| 1543 | - iHiwtr); | |
| 1544 | - iHiwtr = iCur = -1; | |
| 1545 | - sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); | |
| 1546 | - raw_printf(pArg->out, "Largest Scratch Allocation: %d bytes\n", | |
| 1547 | - iHiwtr); | |
| 2311 | + displayStatLine(pArg, "Number of Scratch Allocations Used:", | |
| 2312 | + "%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset); | |
| 2313 | + } | |
| 2314 | + displayStatLine(pArg, "Number of Scratch Overflow Bytes:", | |
| 2315 | + "%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset); | |
| 2316 | + displayStatLine(pArg, "Largest Allocation:", | |
| 2317 | + "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); | |
| 2318 | + displayStatLine(pArg, "Largest Pcache Allocation:", | |
| 2319 | + "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); | |
| 2320 | + displayStatLine(pArg, "Largest Scratch Allocation:", | |
| 2321 | + "%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset); | |
| 1548 | 2322 | #ifdef YYTRACKMAXSTACKDEPTH |
| 1549 | - iHiwtr = iCur = -1; | |
| 1550 | - sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset); | |
| 1551 | - raw_printf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", | |
| 1552 | - iCur, iHiwtr); | |
| 2323 | + displayStatLine(pArg, "Deepest Parser Stack:", | |
| 2324 | + "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); | |
| 1553 | 2325 | #endif |
| 1554 | 2326 | } |
| 1555 | 2327 | |
| 1556 | 2328 | if( pArg && pArg->out && db ){ |
| 1557 | 2329 | if( pArg->shellFlgs & SHFLG_Lookaside ){ |
| @@ -1934,11 +2706,11 @@ | ||
| 1934 | 2706 | pArg->pStmt = pStmt; |
| 1935 | 2707 | pArg->cnt = 0; |
| 1936 | 2708 | } |
| 1937 | 2709 | |
| 1938 | 2710 | /* echo the sql statement if echo on */ |
| 1939 | - if( pArg && pArg->echoOn ){ | |
| 2711 | + if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){ | |
| 1940 | 2712 | utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); |
| 1941 | 2713 | } |
| 1942 | 2714 | |
| 1943 | 2715 | /* Show the EXPLAIN QUERY PLAN if .eqp is on */ |
| 1944 | 2716 | if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){ |
| @@ -2022,10 +2794,142 @@ | ||
| 2022 | 2794 | } /* end while */ |
| 2023 | 2795 | |
| 2024 | 2796 | return rc; |
| 2025 | 2797 | } |
| 2026 | 2798 | |
| 2799 | +/* | |
| 2800 | +** Release memory previously allocated by tableColumnList(). | |
| 2801 | +*/ | |
| 2802 | +static void freeColumnList(char **azCol){ | |
| 2803 | + int i; | |
| 2804 | + for(i=1; azCol[i]; i++){ | |
| 2805 | + sqlite3_free(azCol[i]); | |
| 2806 | + } | |
| 2807 | + /* azCol[0] is a static string */ | |
| 2808 | + sqlite3_free(azCol); | |
| 2809 | +} | |
| 2810 | + | |
| 2811 | +/* | |
| 2812 | +** Return a list of pointers to strings which are the names of all | |
| 2813 | +** columns in table zTab. The memory to hold the names is dynamically | |
| 2814 | +** allocated and must be released by the caller using a subsequent call | |
| 2815 | +** to freeColumnList(). | |
| 2816 | +** | |
| 2817 | +** The azCol[0] entry is usually NULL. However, if zTab contains a rowid | |
| 2818 | +** value that needs to be preserved, then azCol[0] is filled in with the | |
| 2819 | +** name of the rowid column. | |
| 2820 | +** | |
| 2821 | +** The first regular column in the table is azCol[1]. The list is terminated | |
| 2822 | +** by an entry with azCol[i]==0. | |
| 2823 | +*/ | |
| 2824 | +static char **tableColumnList(ShellState *p, const char *zTab){ | |
| 2825 | + char **azCol = 0; | |
| 2826 | + sqlite3_stmt *pStmt; | |
| 2827 | + char *zSql; | |
| 2828 | + int nCol = 0; | |
| 2829 | + int nAlloc = 0; | |
| 2830 | + int nPK = 0; /* Number of PRIMARY KEY columns seen */ | |
| 2831 | + int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */ | |
| 2832 | + int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid); | |
| 2833 | + int rc; | |
| 2834 | + | |
| 2835 | + zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); | |
| 2836 | + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
| 2837 | + sqlite3_free(zSql); | |
| 2838 | + if( rc ) return 0; | |
| 2839 | + while( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 2840 | + if( nCol>=nAlloc-2 ){ | |
| 2841 | + nAlloc = nAlloc*2 + nCol + 10; | |
| 2842 | + azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); | |
| 2843 | + if( azCol==0 ){ | |
| 2844 | + raw_printf(stderr, "Error: out of memory\n"); | |
| 2845 | + exit(1); | |
| 2846 | + } | |
| 2847 | + } | |
| 2848 | + azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); | |
| 2849 | + if( sqlite3_column_int(pStmt, 5) ){ | |
| 2850 | + nPK++; | |
| 2851 | + if( nPK==1 | |
| 2852 | + && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), | |
| 2853 | + "INTEGER")==0 | |
| 2854 | + ){ | |
| 2855 | + isIPK = 1; | |
| 2856 | + }else{ | |
| 2857 | + isIPK = 0; | |
| 2858 | + } | |
| 2859 | + } | |
| 2860 | + } | |
| 2861 | + sqlite3_finalize(pStmt); | |
| 2862 | + azCol[0] = 0; | |
| 2863 | + azCol[nCol+1] = 0; | |
| 2864 | + | |
| 2865 | + /* The decision of whether or not a rowid really needs to be preserved | |
| 2866 | + ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table | |
| 2867 | + ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve | |
| 2868 | + ** rowids on tables where the rowid is inaccessible because there are other | |
| 2869 | + ** columns in the table named "rowid", "_rowid_", and "oid". | |
| 2870 | + */ | |
| 2871 | + if( preserveRowid && isIPK ){ | |
| 2872 | + /* If a single PRIMARY KEY column with type INTEGER was seen, then it | |
| 2873 | + ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID | |
| 2874 | + ** table or a INTEGER PRIMARY KEY DESC column, neither of which are | |
| 2875 | + ** ROWID aliases. To distinguish these cases, check to see if | |
| 2876 | + ** there is a "pk" entry in "PRAGMA index_list". There will be | |
| 2877 | + ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID. | |
| 2878 | + */ | |
| 2879 | + zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)" | |
| 2880 | + " WHERE origin='pk'", zTab); | |
| 2881 | + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
| 2882 | + sqlite3_free(zSql); | |
| 2883 | + if( rc ){ | |
| 2884 | + freeColumnList(azCol); | |
| 2885 | + return 0; | |
| 2886 | + } | |
| 2887 | + rc = sqlite3_step(pStmt); | |
| 2888 | + sqlite3_finalize(pStmt); | |
| 2889 | + preserveRowid = rc==SQLITE_ROW; | |
| 2890 | + } | |
| 2891 | + if( preserveRowid ){ | |
| 2892 | + /* Only preserve the rowid if we can find a name to use for the | |
| 2893 | + ** rowid */ | |
| 2894 | + static char *azRowid[] = { "rowid", "_rowid_", "oid" }; | |
| 2895 | + int i, j; | |
| 2896 | + for(j=0; j<3; j++){ | |
| 2897 | + for(i=1; i<=nCol; i++){ | |
| 2898 | + if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break; | |
| 2899 | + } | |
| 2900 | + if( i>nCol ){ | |
| 2901 | + /* At this point, we know that azRowid[j] is not the name of any | |
| 2902 | + ** ordinary column in the table. Verify that azRowid[j] is a valid | |
| 2903 | + ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID | |
| 2904 | + ** tables will fail this last check */ | |
| 2905 | + int rc; | |
| 2906 | + rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0); | |
| 2907 | + if( rc==SQLITE_OK ) azCol[0] = azRowid[j]; | |
| 2908 | + break; | |
| 2909 | + } | |
| 2910 | + } | |
| 2911 | + } | |
| 2912 | + return azCol; | |
| 2913 | +} | |
| 2914 | + | |
| 2915 | +/* | |
| 2916 | +** Toggle the reverse_unordered_selects setting. | |
| 2917 | +*/ | |
| 2918 | +static void toggleSelectOrder(sqlite3 *db){ | |
| 2919 | + sqlite3_stmt *pStmt = 0; | |
| 2920 | + int iSetting = 0; | |
| 2921 | + char zStmt[100]; | |
| 2922 | + sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0); | |
| 2923 | + if( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 2924 | + iSetting = sqlite3_column_int(pStmt, 0); | |
| 2925 | + } | |
| 2926 | + sqlite3_finalize(pStmt); | |
| 2927 | + sqlite3_snprintf(sizeof(zStmt), zStmt, | |
| 2928 | + "PRAGMA reverse_unordered_selects(%d)", !iSetting); | |
| 2929 | + sqlite3_exec(db, zStmt, 0, 0, 0); | |
| 2930 | +} | |
| 2027 | 2931 | |
| 2028 | 2932 | /* |
| 2029 | 2933 | ** This is a different callback routine used for dumping the database. |
| 2030 | 2934 | ** Each row received by this callback consists of a table name, |
| 2031 | 2935 | ** the table type ("index" or "table") and SQL to create the table. |
| @@ -2034,21 +2938,20 @@ | ||
| 2034 | 2938 | static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ |
| 2035 | 2939 | int rc; |
| 2036 | 2940 | const char *zTable; |
| 2037 | 2941 | const char *zType; |
| 2038 | 2942 | const char *zSql; |
| 2039 | - const char *zPrepStmt = 0; | |
| 2040 | 2943 | ShellState *p = (ShellState *)pArg; |
| 2041 | 2944 | |
| 2042 | 2945 | UNUSED_PARAMETER(azCol); |
| 2043 | 2946 | if( nArg!=3 ) return 1; |
| 2044 | 2947 | zTable = azArg[0]; |
| 2045 | 2948 | zType = azArg[1]; |
| 2046 | 2949 | zSql = azArg[2]; |
| 2047 | 2950 | |
| 2048 | 2951 | if( strcmp(zTable, "sqlite_sequence")==0 ){ |
| 2049 | - zPrepStmt = "DELETE FROM sqlite_sequence;\n"; | |
| 2952 | + raw_printf(p->out, "DELETE FROM sqlite_sequence;\n"); | |
| 2050 | 2953 | }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ |
| 2051 | 2954 | raw_printf(p->out, "ANALYZE sqlite_master;\n"); |
| 2052 | 2955 | }else if( strncmp(zTable, "sqlite_", 7)==0 ){ |
| 2053 | 2956 | return 0; |
| 2054 | 2957 | }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ |
| @@ -2067,62 +2970,74 @@ | ||
| 2067 | 2970 | }else{ |
| 2068 | 2971 | printSchemaLine(p->out, zSql, ";\n"); |
| 2069 | 2972 | } |
| 2070 | 2973 | |
| 2071 | 2974 | if( strcmp(zType, "table")==0 ){ |
| 2072 | - sqlite3_stmt *pTableInfo = 0; | |
| 2073 | - char *zSelect = 0; | |
| 2074 | - char *zTableInfo = 0; | |
| 2075 | - char *zTmp = 0; | |
| 2076 | - int nRow = 0; | |
| 2077 | - | |
| 2078 | - zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); | |
| 2079 | - zTableInfo = appendText(zTableInfo, zTable, '"'); | |
| 2080 | - zTableInfo = appendText(zTableInfo, ");", 0); | |
| 2081 | - | |
| 2082 | - rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); | |
| 2083 | - free(zTableInfo); | |
| 2084 | - if( rc!=SQLITE_OK || !pTableInfo ){ | |
| 2085 | - return 1; | |
| 2086 | - } | |
| 2087 | - | |
| 2088 | - zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); | |
| 2975 | + ShellText sSelect; | |
| 2976 | + ShellText sTable; | |
| 2977 | + char **azCol; | |
| 2978 | + int i; | |
| 2979 | + char *savedDestTable; | |
| 2980 | + int savedMode; | |
| 2981 | + | |
| 2982 | + azCol = tableColumnList(p, zTable); | |
| 2983 | + if( azCol==0 ){ | |
| 2984 | + p->nErr++; | |
| 2985 | + return 0; | |
| 2986 | + } | |
| 2987 | + | |
| 2089 | 2988 | /* Always quote the table name, even if it appears to be pure ascii, |
| 2090 | 2989 | ** in case it is a keyword. Ex: INSERT INTO "table" ... */ |
| 2091 | - zTmp = appendText(zTmp, zTable, '"'); | |
| 2092 | - if( zTmp ){ | |
| 2093 | - zSelect = appendText(zSelect, zTmp, '\''); | |
| 2094 | - free(zTmp); | |
| 2095 | - } | |
| 2096 | - zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); | |
| 2097 | - rc = sqlite3_step(pTableInfo); | |
| 2098 | - while( rc==SQLITE_ROW ){ | |
| 2099 | - const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); | |
| 2100 | - zSelect = appendText(zSelect, "quote(", 0); | |
| 2101 | - zSelect = appendText(zSelect, zText, '"'); | |
| 2102 | - rc = sqlite3_step(pTableInfo); | |
| 2103 | - if( rc==SQLITE_ROW ){ | |
| 2104 | - zSelect = appendText(zSelect, "), ", 0); | |
| 2105 | - }else{ | |
| 2106 | - zSelect = appendText(zSelect, ") ", 0); | |
| 2107 | - } | |
| 2108 | - nRow++; | |
| 2109 | - } | |
| 2110 | - rc = sqlite3_finalize(pTableInfo); | |
| 2111 | - if( rc!=SQLITE_OK || nRow==0 ){ | |
| 2112 | - free(zSelect); | |
| 2113 | - return 1; | |
| 2114 | - } | |
| 2115 | - zSelect = appendText(zSelect, "|| ')' FROM ", 0); | |
| 2116 | - zSelect = appendText(zSelect, zTable, '"'); | |
| 2117 | - | |
| 2118 | - rc = run_table_dump_query(p, zSelect, zPrepStmt); | |
| 2119 | - if( rc==SQLITE_CORRUPT ){ | |
| 2120 | - zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); | |
| 2121 | - run_table_dump_query(p, zSelect, 0); | |
| 2122 | - } | |
| 2123 | - free(zSelect); | |
| 2990 | + initText(&sTable); | |
| 2991 | + appendText(&sTable, zTable, quoteChar(zTable)); | |
| 2992 | + /* If preserving the rowid, add a column list after the table name. | |
| 2993 | + ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)" | |
| 2994 | + ** instead of the usual "INSERT INTO tab VALUES(...)". | |
| 2995 | + */ | |
| 2996 | + if( azCol[0] ){ | |
| 2997 | + appendText(&sTable, "(", 0); | |
| 2998 | + appendText(&sTable, azCol[0], 0); | |
| 2999 | + for(i=1; azCol[i]; i++){ | |
| 3000 | + appendText(&sTable, ",", 0); | |
| 3001 | + appendText(&sTable, azCol[i], quoteChar(azCol[i])); | |
| 3002 | + } | |
| 3003 | + appendText(&sTable, ")", 0); | |
| 3004 | + } | |
| 3005 | + | |
| 3006 | + /* Build an appropriate SELECT statement */ | |
| 3007 | + initText(&sSelect); | |
| 3008 | + appendText(&sSelect, "SELECT ", 0); | |
| 3009 | + if( azCol[0] ){ | |
| 3010 | + appendText(&sSelect, azCol[0], 0); | |
| 3011 | + appendText(&sSelect, ",", 0); | |
| 3012 | + } | |
| 3013 | + for(i=1; azCol[i]; i++){ | |
| 3014 | + appendText(&sSelect, azCol[i], quoteChar(azCol[i])); | |
| 3015 | + if( azCol[i+1] ){ | |
| 3016 | + appendText(&sSelect, ",", 0); | |
| 3017 | + } | |
| 3018 | + } | |
| 3019 | + freeColumnList(azCol); | |
| 3020 | + appendText(&sSelect, " FROM ", 0); | |
| 3021 | + appendText(&sSelect, zTable, quoteChar(zTable)); | |
| 3022 | + | |
| 3023 | + savedDestTable = p->zDestTable; | |
| 3024 | + savedMode = p->mode; | |
| 3025 | + p->zDestTable = sTable.z; | |
| 3026 | + p->mode = p->cMode = MODE_Insert; | |
| 3027 | + rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0); | |
| 3028 | + if( (rc&0xff)==SQLITE_CORRUPT ){ | |
| 3029 | + raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); | |
| 3030 | + toggleSelectOrder(p->db); | |
| 3031 | + shell_exec(p->db, sSelect.z, shell_callback, p, 0); | |
| 3032 | + toggleSelectOrder(p->db); | |
| 3033 | + } | |
| 3034 | + p->zDestTable = savedDestTable; | |
| 3035 | + p->mode = savedMode; | |
| 3036 | + freeText(&sTable); | |
| 3037 | + freeText(&sSelect); | |
| 3038 | + if( rc ) p->nErr++; | |
| 2124 | 3039 | } |
| 2125 | 3040 | return 0; |
| 2126 | 3041 | } |
| 2127 | 3042 | |
| 2128 | 3043 | /* |
| @@ -2210,11 +3125,11 @@ | ||
| 2210 | 3125 | " csv Comma-separated values\n" |
| 2211 | 3126 | " column Left-aligned columns. (See .width)\n" |
| 2212 | 3127 | " html HTML <table> code\n" |
| 2213 | 3128 | " insert SQL insert statements for TABLE\n" |
| 2214 | 3129 | " line One value per line\n" |
| 2215 | - " list Values delimited by .separator strings\n" | |
| 3130 | + " list Values delimited by \"|\"\n" | |
| 2216 | 3131 | " quote Escape answers as for SQL\n" |
| 2217 | 3132 | " tabs Tab-separated values\n" |
| 2218 | 3133 | " tcl TCL list elements\n" |
| 2219 | 3134 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2220 | 3135 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| @@ -2233,10 +3148,11 @@ | ||
| 2233 | 3148 | ".separator COL ?ROW? Change the column separator and optionally the row\n" |
| 2234 | 3149 | " separator for both the output mode and .import\n" |
| 2235 | 3150 | #if defined(SQLITE_ENABLE_SESSION) |
| 2236 | 3151 | ".session CMD ... Create or control sessions\n" |
| 2237 | 3152 | #endif |
| 3153 | + ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n" | |
| 2238 | 3154 | ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" |
| 2239 | 3155 | ".show Show the current values for various settings\n" |
| 2240 | 3156 | ".stats ?on|off? Show stats or turn stats on or off\n" |
| 2241 | 3157 | ".system CMD ARGS... Run CMD ARGS... in a system shell\n" |
| 2242 | 3158 | ".tables ?TABLE? List names of tables\n" |
| @@ -2423,14 +3339,10 @@ | ||
| 2423 | 3339 | static void open_db(ShellState *p, int keepAlive){ |
| 2424 | 3340 | if( p->db==0 ){ |
| 2425 | 3341 | sqlite3_initialize(); |
| 2426 | 3342 | sqlite3_open(p->zDbFilename, &p->db); |
| 2427 | 3343 | globalDb = p->db; |
| 2428 | - if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){ | |
| 2429 | - sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0, | |
| 2430 | - shellstaticFunc, 0, 0); | |
| 2431 | - } | |
| 2432 | 3344 | if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ |
| 2433 | 3345 | utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", |
| 2434 | 3346 | p->zDbFilename, sqlite3_errmsg(p->db)); |
| 2435 | 3347 | if( keepAlive ) return; |
| 2436 | 3348 | exit(1); |
| @@ -2440,10 +3352,18 @@ | ||
| 2440 | 3352 | #endif |
| 2441 | 3353 | sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0, |
| 2442 | 3354 | readfileFunc, 0, 0); |
| 2443 | 3355 | sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0, |
| 2444 | 3356 | writefileFunc, 0, 0); |
| 3357 | + sqlite3_create_function(p->db, "sha3", 1, SQLITE_UTF8, 0, | |
| 3358 | + sha3Func, 0, 0); | |
| 3359 | + sqlite3_create_function(p->db, "sha3", 2, SQLITE_UTF8, 0, | |
| 3360 | + sha3Func, 0, 0); | |
| 3361 | + sqlite3_create_function(p->db, "sha3_query", 1, SQLITE_UTF8, 0, | |
| 3362 | + sha3QueryFunc, 0, 0); | |
| 3363 | + sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0, | |
| 3364 | + sha3QueryFunc, 0, 0); | |
| 2445 | 3365 | } |
| 2446 | 3366 | } |
| 2447 | 3367 | |
| 2448 | 3368 | /* |
| 2449 | 3369 | ** Do C-language style dequoting. |
| @@ -2564,11 +3484,11 @@ | ||
| 2564 | 3484 | |
| 2565 | 3485 | /* |
| 2566 | 3486 | ** Interpret zArg as either an integer or a boolean value. Return 1 or 0 |
| 2567 | 3487 | ** for TRUE and FALSE. Return the integer value if appropriate. |
| 2568 | 3488 | */ |
| 2569 | -static int booleanValue(char *zArg){ | |
| 3489 | +static int booleanValue(const char *zArg){ | |
| 2570 | 3490 | int i; |
| 2571 | 3491 | if( zArg[0]=='0' && zArg[1]=='x' ){ |
| 2572 | 3492 | for(i=2; hexDigitValue(zArg[i])>=0; i++){} |
| 2573 | 3493 | }else{ |
| 2574 | 3494 | for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} |
| @@ -2582,10 +3502,21 @@ | ||
| 2582 | 3502 | } |
| 2583 | 3503 | utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", |
| 2584 | 3504 | zArg); |
| 2585 | 3505 | return 0; |
| 2586 | 3506 | } |
| 3507 | + | |
| 3508 | +/* | |
| 3509 | +** Set or clear a shell flag according to a boolean value. | |
| 3510 | +*/ | |
| 3511 | +static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){ | |
| 3512 | + if( booleanValue(zArg) ){ | |
| 3513 | + ShellSetFlag(p, mFlag); | |
| 3514 | + }else{ | |
| 3515 | + ShellClearFlag(p, mFlag); | |
| 3516 | + } | |
| 3517 | +} | |
| 2587 | 3518 | |
| 2588 | 3519 | /* |
| 2589 | 3520 | ** Close an output file, assuming it is not stderr or stdout |
| 2590 | 3521 | */ |
| 2591 | 3522 | static void output_file_close(FILE *f){ |
| @@ -3656,11 +4587,11 @@ | ||
| 3656 | 4587 | test_breakpoint(); |
| 3657 | 4588 | }else |
| 3658 | 4589 | |
| 3659 | 4590 | if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ |
| 3660 | 4591 | if( nArg==2 ){ |
| 3661 | - p->countChanges = booleanValue(azArg[1]); | |
| 4592 | + setOrClearFlag(p, SHFLG_CountChanges, azArg[1]); | |
| 3662 | 4593 | }else{ |
| 3663 | 4594 | raw_printf(stderr, "Usage: .changes on|off\n"); |
| 3664 | 4595 | rc = 1; |
| 3665 | 4596 | } |
| 3666 | 4597 | }else |
| @@ -3720,25 +4651,46 @@ | ||
| 3720 | 4651 | if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ |
| 3721 | 4652 | rc = shell_dbinfo_command(p, nArg, azArg); |
| 3722 | 4653 | }else |
| 3723 | 4654 | |
| 3724 | 4655 | if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ |
| 4656 | + const char *zLike = 0; | |
| 4657 | + int i; | |
| 4658 | + ShellClearFlag(p, SHFLG_PreserveRowid); | |
| 4659 | + for(i=1; i<nArg; i++){ | |
| 4660 | + if( azArg[i][0]=='-' ){ | |
| 4661 | + const char *z = azArg[i]+1; | |
| 4662 | + if( z[0]=='-' ) z++; | |
| 4663 | + if( strcmp(z,"preserve-rowids")==0 ){ | |
| 4664 | + ShellSetFlag(p, SHFLG_PreserveRowid); | |
| 4665 | + }else | |
| 4666 | + { | |
| 4667 | + raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]); | |
| 4668 | + rc = 1; | |
| 4669 | + goto meta_command_exit; | |
| 4670 | + } | |
| 4671 | + }else if( zLike ){ | |
| 4672 | + raw_printf(stderr, "Usage: .dump ?--preserve-rowids? ?LIKE-PATTERN?\n"); | |
| 4673 | + rc = 1; | |
| 4674 | + goto meta_command_exit; | |
| 4675 | + }else{ | |
| 4676 | + zLike = azArg[i]; | |
| 4677 | + } | |
| 4678 | + } | |
| 3725 | 4679 | open_db(p, 0); |
| 3726 | 4680 | /* When playing back a "dump", the content might appear in an order |
| 3727 | 4681 | ** which causes immediate foreign key constraints to be violated. |
| 3728 | 4682 | ** So disable foreign-key constraint enforcement to prevent problems. */ |
| 3729 | - if( nArg!=1 && nArg!=2 ){ | |
| 3730 | - raw_printf(stderr, "Usage: .dump ?LIKE-PATTERN?\n"); | |
| 3731 | - rc = 1; | |
| 3732 | - goto meta_command_exit; | |
| 3733 | - } | |
| 3734 | 4683 | raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); |
| 3735 | 4684 | raw_printf(p->out, "BEGIN TRANSACTION;\n"); |
| 3736 | 4685 | p->writableSchema = 0; |
| 4686 | + /* Set writable_schema=ON since doing so forces SQLite to initialize | |
| 4687 | + ** as much of the schema as it can even if the sqlite_master table is | |
| 4688 | + ** corrupt. */ | |
| 3737 | 4689 | sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); |
| 3738 | 4690 | p->nErr = 0; |
| 3739 | - if( nArg==1 ){ | |
| 4691 | + if( zLike==0 ){ | |
| 3740 | 4692 | run_schema_dump_query(p, |
| 3741 | 4693 | "SELECT name, type, sql FROM sqlite_master " |
| 3742 | 4694 | "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" |
| 3743 | 4695 | ); |
| 3744 | 4696 | run_schema_dump_query(p, |
| @@ -3748,25 +4700,24 @@ | ||
| 3748 | 4700 | run_table_dump_query(p, |
| 3749 | 4701 | "SELECT sql FROM sqlite_master " |
| 3750 | 4702 | "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 |
| 3751 | 4703 | ); |
| 3752 | 4704 | }else{ |
| 3753 | - int i; | |
| 3754 | - for(i=1; i<nArg; i++){ | |
| 3755 | - zShellStatic = azArg[i]; | |
| 3756 | - run_schema_dump_query(p, | |
| 3757 | - "SELECT name, type, sql FROM sqlite_master " | |
| 3758 | - "WHERE tbl_name LIKE shellstatic() AND type=='table'" | |
| 3759 | - " AND sql NOT NULL"); | |
| 3760 | - run_table_dump_query(p, | |
| 3761 | - "SELECT sql FROM sqlite_master " | |
| 3762 | - "WHERE sql NOT NULL" | |
| 3763 | - " AND type IN ('index','trigger','view')" | |
| 3764 | - " AND tbl_name LIKE shellstatic()", 0 | |
| 3765 | - ); | |
| 3766 | - zShellStatic = 0; | |
| 3767 | - } | |
| 4705 | + char *zSql; | |
| 4706 | + zSql = sqlite3_mprintf( | |
| 4707 | + "SELECT name, type, sql FROM sqlite_master " | |
| 4708 | + "WHERE tbl_name LIKE %Q AND type=='table'" | |
| 4709 | + " AND sql NOT NULL", zLike); | |
| 4710 | + run_schema_dump_query(p,zSql); | |
| 4711 | + sqlite3_free(zSql); | |
| 4712 | + zSql = sqlite3_mprintf( | |
| 4713 | + "SELECT sql FROM sqlite_master " | |
| 4714 | + "WHERE sql NOT NULL" | |
| 4715 | + " AND type IN ('index','trigger','view')" | |
| 4716 | + " AND tbl_name LIKE %Q", zLike); | |
| 4717 | + run_table_dump_query(p, zSql, 0); | |
| 4718 | + sqlite3_free(zSql); | |
| 3768 | 4719 | } |
| 3769 | 4720 | if( p->writableSchema ){ |
| 3770 | 4721 | raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); |
| 3771 | 4722 | p->writableSchema = 0; |
| 3772 | 4723 | } |
| @@ -3775,11 +4726,11 @@ | ||
| 3775 | 4726 | raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); |
| 3776 | 4727 | }else |
| 3777 | 4728 | |
| 3778 | 4729 | if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ |
| 3779 | 4730 | if( nArg==2 ){ |
| 3780 | - p->echoOn = booleanValue(azArg[1]); | |
| 4731 | + setOrClearFlag(p, SHFLG_Echo, azArg[1]); | |
| 3781 | 4732 | }else{ |
| 3782 | 4733 | raw_printf(stderr, "Usage: .echo on|off\n"); |
| 3783 | 4734 | rc = 1; |
| 3784 | 4735 | } |
| 3785 | 4736 | }else |
| @@ -4342,10 +5293,11 @@ | ||
| 4342 | 5293 | int newFlag = 0; /* True to delete file before opening */ |
| 4343 | 5294 | /* Close the existing database */ |
| 4344 | 5295 | session_close_all(p); |
| 4345 | 5296 | sqlite3_close(p->db); |
| 4346 | 5297 | p->db = 0; |
| 5298 | + p->zDbFilename = 0; | |
| 4347 | 5299 | sqlite3_free(p->zFreeOnClose); |
| 4348 | 5300 | p->zFreeOnClose = 0; |
| 4349 | 5301 | /* Check for command-line arguments */ |
| 4350 | 5302 | for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){ |
| 4351 | 5303 | const char *z = azArg[iName]; |
| @@ -4571,21 +5523,21 @@ | ||
| 4571 | 5523 | new_colv[0] = "sql"; |
| 4572 | 5524 | new_colv[1] = 0; |
| 4573 | 5525 | callback(&data, 1, new_argv, new_colv); |
| 4574 | 5526 | rc = SQLITE_OK; |
| 4575 | 5527 | }else{ |
| 4576 | - zShellStatic = azArg[1]; | |
| 4577 | - rc = sqlite3_exec(p->db, | |
| 5528 | + char *zSql; | |
| 5529 | + zSql = sqlite3_mprintf( | |
| 4578 | 5530 | "SELECT sql FROM " |
| 4579 | 5531 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 4580 | 5532 | " FROM sqlite_master UNION ALL" |
| 4581 | 5533 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 4582 | - "WHERE lower(tbl_name) LIKE shellstatic()" | |
| 5534 | + "WHERE lower(tbl_name) LIKE %Q" | |
| 4583 | 5535 | " AND type!='meta' AND sql NOTNULL " |
| 4584 | - "ORDER BY rowid", | |
| 4585 | - callback, &data, &zErrMsg); | |
| 4586 | - zShellStatic = 0; | |
| 5536 | + "ORDER BY rowid", azArg[1]); | |
| 5537 | + rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg); | |
| 5538 | + sqlite3_free(zSql); | |
| 4587 | 5539 | } |
| 4588 | 5540 | }else if( nArg==1 ){ |
| 4589 | 5541 | rc = sqlite3_exec(p->db, |
| 4590 | 5542 | "SELECT sql FROM " |
| 4591 | 5543 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| @@ -4612,11 +5564,11 @@ | ||
| 4612 | 5564 | } |
| 4613 | 5565 | }else |
| 4614 | 5566 | |
| 4615 | 5567 | #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 4616 | 5568 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ |
| 4617 | - sqlite3SelectTrace = integerValue(azArg[1]); | |
| 5569 | + sqlite3SelectTrace = (int)integerValue(azArg[1]); | |
| 4618 | 5570 | }else |
| 4619 | 5571 | #endif |
| 4620 | 5572 | |
| 4621 | 5573 | #if defined(SQLITE_ENABLE_SESSION) |
| 4622 | 5574 | if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ |
| @@ -4834,10 +5786,123 @@ | ||
| 4834 | 5786 | utf8_printf(p->out, "%s", zBuf); |
| 4835 | 5787 | } |
| 4836 | 5788 | } |
| 4837 | 5789 | }else |
| 4838 | 5790 | #endif |
| 5791 | + | |
| 5792 | + if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ | |
| 5793 | + int bIsInit = 0; /* True to initialize the SELFTEST table */ | |
| 5794 | + int bVerbose = 0; /* Verbose output */ | |
| 5795 | + int bSelftestExists; /* True if SELFTEST already exists */ | |
| 5796 | + char **azTest = 0; /* Content of the SELFTEST table */ | |
| 5797 | + int nRow = 0; /* Number of rows in the SELFTEST table */ | |
| 5798 | + int nCol = 4; /* Number of columns in the SELFTEST table */ | |
| 5799 | + int i; /* Loop counter */ | |
| 5800 | + int nTest = 0; /* Number of tests runs */ | |
| 5801 | + int nErr = 0; /* Number of errors seen */ | |
| 5802 | + ShellText str; /* Answer for a query */ | |
| 5803 | + static char *azDefaultTest[] = { | |
| 5804 | + 0, 0, 0, 0, | |
| 5805 | + "0", "memo", "Missing SELFTEST table - default checks only", "", | |
| 5806 | + "1", "run", "PRAGMA integrity_check", "ok" | |
| 5807 | + }; | |
| 5808 | + static const int nDefaultRow = 2; | |
| 5809 | + | |
| 5810 | + open_db(p,0); | |
| 5811 | + for(i=1; i<nArg; i++){ | |
| 5812 | + const char *z = azArg[i]; | |
| 5813 | + if( z[0]=='-' && z[1]=='-' ) z++; | |
| 5814 | + if( strcmp(z,"-init")==0 ){ | |
| 5815 | + bIsInit = 1; | |
| 5816 | + }else | |
| 5817 | + if( strcmp(z,"-v")==0 ){ | |
| 5818 | + bVerbose++; | |
| 5819 | + }else | |
| 5820 | + { | |
| 5821 | + utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", | |
| 5822 | + azArg[i], azArg[0]); | |
| 5823 | + raw_printf(stderr, "Should be one of: --init -v\n"); | |
| 5824 | + rc = 1; | |
| 5825 | + goto meta_command_exit; | |
| 5826 | + } | |
| 5827 | + } | |
| 5828 | + if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0) | |
| 5829 | + != SQLITE_OK ){ | |
| 5830 | + bSelftestExists = 0; | |
| 5831 | + }else{ | |
| 5832 | + bSelftestExists = 1; | |
| 5833 | + } | |
| 5834 | + if( bIsInit ){ | |
| 5835 | + createSelftestTable(p); | |
| 5836 | + bSelftestExists = 1; | |
| 5837 | + } | |
| 5838 | + if( bSelftestExists ){ | |
| 5839 | + rc = sqlite3_get_table(p->db, | |
| 5840 | + "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", | |
| 5841 | + &azTest, &nRow, &nCol, 0); | |
| 5842 | + if( rc ){ | |
| 5843 | + raw_printf(stderr, "Error querying the selftest table\n"); | |
| 5844 | + rc = 1; | |
| 5845 | + sqlite3_free_table(azTest); | |
| 5846 | + goto meta_command_exit; | |
| 5847 | + }else if( nRow==0 ){ | |
| 5848 | + sqlite3_free_table(azTest); | |
| 5849 | + azTest = azDefaultTest; | |
| 5850 | + nRow = nDefaultRow; | |
| 5851 | + } | |
| 5852 | + }else{ | |
| 5853 | + azTest = azDefaultTest; | |
| 5854 | + nRow = nDefaultRow; | |
| 5855 | + } | |
| 5856 | + initText(&str); | |
| 5857 | + appendText(&str, "x", 0); | |
| 5858 | + for(i=1; i<=nRow; i++){ | |
| 5859 | + int tno = atoi(azTest[i*nCol]); | |
| 5860 | + const char *zOp = azTest[i*nCol+1]; | |
| 5861 | + const char *zSql = azTest[i*nCol+2]; | |
| 5862 | + const char *zAns = azTest[i*nCol+3]; | |
| 5863 | + | |
| 5864 | + if( bVerbose>0 ){ | |
| 5865 | + char *zQuote = sqlite3_mprintf("%q", zSql); | |
| 5866 | + printf("%d: %s %s\n", tno, zOp, zSql); | |
| 5867 | + sqlite3_free(zQuote); | |
| 5868 | + } | |
| 5869 | + if( strcmp(zOp,"memo")==0 ){ | |
| 5870 | + utf8_printf(p->out, "%s\n", zSql); | |
| 5871 | + }else | |
| 5872 | + if( strcmp(zOp,"run")==0 ){ | |
| 5873 | + char *zErrMsg = 0; | |
| 5874 | + str.n = 0; | |
| 5875 | + str.z[0] = 0; | |
| 5876 | + rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); | |
| 5877 | + nTest++; | |
| 5878 | + if( bVerbose ){ | |
| 5879 | + utf8_printf(p->out, "Result: %s\n", str.z); | |
| 5880 | + } | |
| 5881 | + if( rc || zErrMsg ){ | |
| 5882 | + nErr++; | |
| 5883 | + rc = 1; | |
| 5884 | + utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); | |
| 5885 | + sqlite3_free(zErrMsg); | |
| 5886 | + }else if( strcmp(zAns,str.z)!=0 ){ | |
| 5887 | + nErr++; | |
| 5888 | + rc = 1; | |
| 5889 | + utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); | |
| 5890 | + utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); | |
| 5891 | + } | |
| 5892 | + }else | |
| 5893 | + { | |
| 5894 | + utf8_printf(stderr, | |
| 5895 | + "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); | |
| 5896 | + rc = 1; | |
| 5897 | + break; | |
| 5898 | + } | |
| 5899 | + } | |
| 5900 | + freeText(&str); | |
| 5901 | + if( azTest!=azDefaultTest ) sqlite3_free_table(azTest); | |
| 5902 | + utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); | |
| 5903 | + }else | |
| 4839 | 5904 | |
| 4840 | 5905 | if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ |
| 4841 | 5906 | if( nArg<2 || nArg>3 ){ |
| 4842 | 5907 | raw_printf(stderr, "Usage: .separator COL ?ROW?\n"); |
| 4843 | 5908 | rc = 1; |
| @@ -4849,10 +5914,126 @@ | ||
| 4849 | 5914 | if( nArg>=3 ){ |
| 4850 | 5915 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, |
| 4851 | 5916 | "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); |
| 4852 | 5917 | } |
| 4853 | 5918 | }else |
| 5919 | + | |
| 5920 | + if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){ | |
| 5921 | + const char *zLike = 0; /* Which table to checksum. 0 means everything */ | |
| 5922 | + int i; /* Loop counter */ | |
| 5923 | + int bSchema = 0; /* Also hash the schema */ | |
| 5924 | + int bSeparate = 0; /* Hash each table separately */ | |
| 5925 | + int iSize = 224; /* Hash algorithm to use */ | |
| 5926 | + int bDebug = 0; /* Only show the query that would have run */ | |
| 5927 | + sqlite3_stmt *pStmt; /* For querying tables names */ | |
| 5928 | + char *zSql; /* SQL to be run */ | |
| 5929 | + char *zSep; /* Separator */ | |
| 5930 | + ShellText sSql; /* Complete SQL for the query to run the hash */ | |
| 5931 | + ShellText sQuery; /* Set of queries used to read all content */ | |
| 5932 | + open_db(p, 0); | |
| 5933 | + for(i=1; i<nArg; i++){ | |
| 5934 | + const char *z = azArg[i]; | |
| 5935 | + if( z[0]=='-' ){ | |
| 5936 | + z++; | |
| 5937 | + if( z[0]=='-' ) z++; | |
| 5938 | + if( strcmp(z,"schema")==0 ){ | |
| 5939 | + bSchema = 1; | |
| 5940 | + }else | |
| 5941 | + if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0 | |
| 5942 | + || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0 | |
| 5943 | + ){ | |
| 5944 | + iSize = atoi(&z[5]); | |
| 5945 | + }else | |
| 5946 | + if( strcmp(z,"debug")==0 ){ | |
| 5947 | + bDebug = 1; | |
| 5948 | + }else | |
| 5949 | + { | |
| 5950 | + utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", | |
| 5951 | + azArg[i], azArg[0]); | |
| 5952 | + raw_printf(stderr, "Should be one of: --schema" | |
| 5953 | + " --sha3-224 --sha3-255 --sha3-384 --sha3-512\n"); | |
| 5954 | + rc = 1; | |
| 5955 | + goto meta_command_exit; | |
| 5956 | + } | |
| 5957 | + }else if( zLike ){ | |
| 5958 | + raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); | |
| 5959 | + rc = 1; | |
| 5960 | + goto meta_command_exit; | |
| 5961 | + }else{ | |
| 5962 | + zLike = z; | |
| 5963 | + bSeparate = 1; | |
| 5964 | + if( sqlite3_strlike("sqlite_%", zLike, 0)==0 ) bSchema = 1; | |
| 5965 | + } | |
| 5966 | + } | |
| 5967 | + if( bSchema ){ | |
| 5968 | + zSql = "SELECT lower(name) FROM sqlite_master" | |
| 5969 | + " WHERE type='table' AND coalesce(rootpage,0)>1" | |
| 5970 | + " UNION ALL SELECT 'sqlite_master'" | |
| 5971 | + " ORDER BY 1 collate nocase"; | |
| 5972 | + }else{ | |
| 5973 | + zSql = "SELECT lower(name) FROM sqlite_master" | |
| 5974 | + " WHERE type='table' AND coalesce(rootpage,0)>1" | |
| 5975 | + " AND name NOT LIKE 'sqlite_%'" | |
| 5976 | + " ORDER BY 1 collate nocase"; | |
| 5977 | + } | |
| 5978 | + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
| 5979 | + initText(&sQuery); | |
| 5980 | + initText(&sSql); | |
| 5981 | + appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0); | |
| 5982 | + zSep = "VALUES("; | |
| 5983 | + while( SQLITE_ROW==sqlite3_step(pStmt) ){ | |
| 5984 | + const char *zTab = (const char*)sqlite3_column_text(pStmt,0); | |
| 5985 | + if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue; | |
| 5986 | + if( strncmp(zTab, "sqlite_",7)!=0 ){ | |
| 5987 | + appendText(&sQuery,"SELECT * FROM ", 0); | |
| 5988 | + appendText(&sQuery,zTab,'"'); | |
| 5989 | + appendText(&sQuery," NOT INDEXED;", 0); | |
| 5990 | + }else if( strcmp(zTab, "sqlite_master")==0 ){ | |
| 5991 | + appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master" | |
| 5992 | + " ORDER BY name;", 0); | |
| 5993 | + }else if( strcmp(zTab, "sqlite_sequence")==0 ){ | |
| 5994 | + appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence" | |
| 5995 | + " ORDER BY name;", 0); | |
| 5996 | + }else if( strcmp(zTab, "sqlite_stat1")==0 ){ | |
| 5997 | + appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1" | |
| 5998 | + " ORDER BY tbl,idx;", 0); | |
| 5999 | + }else if( strcmp(zTab, "sqlite_stat3")==0 | |
| 6000 | + || strcmp(zTab, "sqlite_stat4")==0 ){ | |
| 6001 | + appendText(&sQuery, "SELECT * FROM ", 0); | |
| 6002 | + appendText(&sQuery, zTab, 0); | |
| 6003 | + appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0); | |
| 6004 | + } | |
| 6005 | + appendText(&sSql, zSep, 0); | |
| 6006 | + appendText(&sSql, sQuery.z, '\''); | |
| 6007 | + sQuery.n = 0; | |
| 6008 | + appendText(&sSql, ",", 0); | |
| 6009 | + appendText(&sSql, zTab, '\''); | |
| 6010 | + zSep = "),("; | |
| 6011 | + } | |
| 6012 | + sqlite3_finalize(pStmt); | |
| 6013 | + if( bSeparate ){ | |
| 6014 | + zSql = sqlite3_mprintf( | |
| 6015 | + "%s))" | |
| 6016 | + " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label" | |
| 6017 | + " FROM [sha3sum$query]", | |
| 6018 | + sSql.z, iSize); | |
| 6019 | + }else{ | |
| 6020 | + zSql = sqlite3_mprintf( | |
| 6021 | + "%s))" | |
| 6022 | + " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash" | |
| 6023 | + " FROM [sha3sum$query]", | |
| 6024 | + sSql.z, iSize); | |
| 6025 | + } | |
| 6026 | + freeText(&sQuery); | |
| 6027 | + freeText(&sSql); | |
| 6028 | + if( bDebug ){ | |
| 6029 | + utf8_printf(p->out, "%s\n", zSql); | |
| 6030 | + }else{ | |
| 6031 | + shell_exec(p->db, zSql, shell_callback, p, 0); | |
| 6032 | + } | |
| 6033 | + sqlite3_free(zSql); | |
| 6034 | + }else | |
| 4854 | 6035 | |
| 4855 | 6036 | if( c=='s' |
| 4856 | 6037 | && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) |
| 4857 | 6038 | ){ |
| 4858 | 6039 | char *zCmd; |
| @@ -4878,11 +6059,12 @@ | ||
| 4878 | 6059 | if( nArg!=1 ){ |
| 4879 | 6060 | raw_printf(stderr, "Usage: .show\n"); |
| 4880 | 6061 | rc = 1; |
| 4881 | 6062 | goto meta_command_exit; |
| 4882 | 6063 | } |
| 4883 | - utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[p->echoOn!=0]); | |
| 6064 | + utf8_printf(p->out, "%12.12s: %s\n","echo", | |
| 6065 | + azBool[ShellHasFlag(p, SHFLG_Echo)]); | |
| 4884 | 6066 | utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); |
| 4885 | 6067 | utf8_printf(p->out, "%12.12s: %s\n","explain", |
| 4886 | 6068 | p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); |
| 4887 | 6069 | utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); |
| 4888 | 6070 | utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); |
| @@ -5190,10 +6372,11 @@ | ||
| 5190 | 6372 | azArg[1]); |
| 5191 | 6373 | break; |
| 5192 | 6374 | } |
| 5193 | 6375 | } |
| 5194 | 6376 | }else |
| 6377 | +#endif /* !defined(SQLITE_UNTESTABLE) */ | |
| 5195 | 6378 | |
| 5196 | 6379 | if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ |
| 5197 | 6380 | open_db(p, 0); |
| 5198 | 6381 | sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); |
| 5199 | 6382 | }else |
| @@ -5226,11 +6409,10 @@ | ||
| 5226 | 6409 | }else{ |
| 5227 | 6410 | sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut); |
| 5228 | 6411 | } |
| 5229 | 6412 | #endif |
| 5230 | 6413 | }else |
| 5231 | -#endif /* !defined(SQLITE_UNTESTABLE) */ | |
| 5232 | 6414 | |
| 5233 | 6415 | #if SQLITE_USER_AUTHENTICATION |
| 5234 | 6416 | if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ |
| 5235 | 6417 | if( nArg<2 ){ |
| 5236 | 6418 | raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); |
| @@ -5443,11 +6625,11 @@ | ||
| 5443 | 6625 | static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ |
| 5444 | 6626 | int rc; |
| 5445 | 6627 | char *zErrMsg = 0; |
| 5446 | 6628 | |
| 5447 | 6629 | open_db(p, 0); |
| 5448 | - if( p->backslashOn ) resolve_backslashes(zSql); | |
| 6630 | + if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); | |
| 5449 | 6631 | BEGIN_TIMER; |
| 5450 | 6632 | rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); |
| 5451 | 6633 | END_TIMER; |
| 5452 | 6634 | if( rc || zErrMsg ){ |
| 5453 | 6635 | char zPrefix[100]; |
| @@ -5463,11 +6645,11 @@ | ||
| 5463 | 6645 | zErrMsg = 0; |
| 5464 | 6646 | }else{ |
| 5465 | 6647 | utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); |
| 5466 | 6648 | } |
| 5467 | 6649 | return 1; |
| 5468 | - }else if( p->countChanges ){ | |
| 6650 | + }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ | |
| 5469 | 6651 | raw_printf(p->out, "changes: %3d total_changes: %d\n", |
| 5470 | 6652 | sqlite3_changes(p->db), sqlite3_total_changes(p->db)); |
| 5471 | 6653 | } |
| 5472 | 6654 | return 0; |
| 5473 | 6655 | } |
| @@ -5506,15 +6688,15 @@ | ||
| 5506 | 6688 | if( in!=0 ) break; |
| 5507 | 6689 | seenInterrupt = 0; |
| 5508 | 6690 | } |
| 5509 | 6691 | lineno++; |
| 5510 | 6692 | if( nSql==0 && _all_whitespace(zLine) ){ |
| 5511 | - if( p->echoOn ) printf("%s\n", zLine); | |
| 6693 | + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); | |
| 5512 | 6694 | continue; |
| 5513 | 6695 | } |
| 5514 | 6696 | if( zLine && zLine[0]=='.' && nSql==0 ){ |
| 5515 | - if( p->echoOn ) printf("%s\n", zLine); | |
| 6697 | + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); | |
| 5516 | 6698 | rc = do_meta_command(zLine, p); |
| 5517 | 6699 | if( rc==2 ){ /* exit requested */ |
| 5518 | 6700 | break; |
| 5519 | 6701 | }else if( rc ){ |
| 5520 | 6702 | errCnt++; |
| @@ -5553,11 +6735,11 @@ | ||
| 5553 | 6735 | if( p->outCount ){ |
| 5554 | 6736 | output_reset(p); |
| 5555 | 6737 | p->outCount = 0; |
| 5556 | 6738 | } |
| 5557 | 6739 | }else if( nSql && _all_whitespace(zSql) ){ |
| 5558 | - if( p->echoOn ) printf("%s\n", zSql); | |
| 6740 | + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); | |
| 5559 | 6741 | nSql = 0; |
| 5560 | 6742 | } |
| 5561 | 6743 | } |
| 5562 | 6744 | if( nSql && !_all_whitespace(zSql) ){ |
| 5563 | 6745 | runOneSqlLine(p, zSql, in, startline); |
| @@ -6022,11 +7204,11 @@ | ||
| 6022 | 7204 | }else if( strcmp(z,"-header")==0 ){ |
| 6023 | 7205 | data.showHeader = 1; |
| 6024 | 7206 | }else if( strcmp(z,"-noheader")==0 ){ |
| 6025 | 7207 | data.showHeader = 0; |
| 6026 | 7208 | }else if( strcmp(z,"-echo")==0 ){ |
| 6027 | - data.echoOn = 1; | |
| 7209 | + ShellSetFlag(&data, SHFLG_Echo); | |
| 6028 | 7210 | }else if( strcmp(z,"-eqp")==0 ){ |
| 6029 | 7211 | data.autoEQP = 1; |
| 6030 | 7212 | }else if( strcmp(z,"-eqpfull")==0 ){ |
| 6031 | 7213 | data.autoEQP = 2; |
| 6032 | 7214 | }else if( strcmp(z,"-stats")==0 ){ |
| @@ -6037,11 +7219,11 @@ | ||
| 6037 | 7219 | /* Undocumented command-line option: -backslash |
| 6038 | 7220 | ** Causes C-style backslash escapes to be evaluated in SQL statements |
| 6039 | 7221 | ** prior to sending the SQL into SQLite. Useful for injecting |
| 6040 | 7222 | ** crazy bytes in the middle of SQL statements for testing and debugging. |
| 6041 | 7223 | */ |
| 6042 | - data.backslashOn = 1; | |
| 7224 | + ShellSetFlag(&data, SHFLG_Backslash); | |
| 6043 | 7225 | }else if( strcmp(z,"-bail")==0 ){ |
| 6044 | 7226 | bail_on_error = 1; |
| 6045 | 7227 | }else if( strcmp(z,"-version")==0 ){ |
| 6046 | 7228 | printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); |
| 6047 | 7229 | return 0; |
| 6048 | 7230 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -452,32 +452,10 @@ | |
| 452 | while( IsDigit(*z) ){ z++; } |
| 453 | if( realnum ) *realnum = 1; |
| 454 | } |
| 455 | return *z==0; |
| 456 | } |
| 457 | |
| 458 | /* |
| 459 | ** A global char* and an SQL function to access its current value |
| 460 | ** from within an SQL statement. This program used to use the |
| 461 | ** sqlite_exec_printf() API to substitue a string into an SQL statement. |
| 462 | ** The correct way to do this with sqlite3 is to use the bind API, but |
| 463 | ** since the shell is built around the callback paradigm it would be a lot |
| 464 | ** of work. Instead just use this hack, which is quite harmless. |
| 465 | */ |
| 466 | static const char *zShellStatic = 0; |
| 467 | static void shellstaticFunc( |
| 468 | sqlite3_context *context, |
| 469 | int argc, |
| 470 | sqlite3_value **argv |
| 471 | ){ |
| 472 | assert( 0==argc ); |
| 473 | assert( zShellStatic ); |
| 474 | UNUSED_PARAMETER(argc); |
| 475 | UNUSED_PARAMETER(argv); |
| 476 | sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); |
| 477 | } |
| 478 | |
| 479 | |
| 480 | /* |
| 481 | ** Compute a string length that is limited to what can be stored in |
| 482 | ** lower 30 bits of a 32-bit signed integer. |
| 483 | */ |
| @@ -575,10 +553,783 @@ | |
| 575 | if( zResult && *zResult ) shell_add_history(zResult); |
| 576 | #endif |
| 577 | } |
| 578 | return zResult; |
| 579 | } |
| 580 | |
| 581 | #if defined(SQLITE_ENABLE_SESSION) |
| 582 | /* |
| 583 | ** State information for a single open session |
| 584 | */ |
| @@ -608,17 +1359,14 @@ | |
| 608 | ** instance of the following structure. |
| 609 | */ |
| 610 | typedef struct ShellState ShellState; |
| 611 | struct ShellState { |
| 612 | sqlite3 *db; /* The database */ |
| 613 | int echoOn; /* True to echo input commands */ |
| 614 | int autoExplain; /* Automatically turn on .explain mode */ |
| 615 | int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
| 616 | int statsOn; /* True to display memory stats before each finalize */ |
| 617 | int scanstatsOn; /* True to display scan stats before each finalize */ |
| 618 | int countChanges; /* True to display change counts */ |
| 619 | int backslashOn; /* Resolve C-style \x escapes in SQL input text */ |
| 620 | int outCount; /* Revert to stdout when reaching zero */ |
| 621 | int cnt; /* Number of records displayed so far */ |
| 622 | FILE *out; /* Write results here */ |
| 623 | FILE *traceOut; /* Output for sqlite3_trace() */ |
| 624 | int nErr; /* Number of errors seen */ |
| @@ -653,13 +1401,24 @@ | |
| 653 | }; |
| 654 | |
| 655 | /* |
| 656 | ** These are the allowed shellFlgs values |
| 657 | */ |
| 658 | #define SHFLG_Scratch 0x00001 /* The --scratch option is used */ |
| 659 | #define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ |
| 660 | #define SHFLG_Lookaside 0x00004 /* Lookaside memory is used */ |
| 661 | |
| 662 | /* |
| 663 | ** These are the allowed modes. |
| 664 | */ |
| 665 | #define MODE_Line 0 /* One column per line. Blank line between records */ |
| @@ -1292,92 +2051,106 @@ | |
| 1292 | */ |
| 1293 | static int callback(void *pArg, int nArg, char **azArg, char **azCol){ |
| 1294 | /* since we don't have type info, call the shell_callback with a NULL value */ |
| 1295 | return shell_callback(pArg, nArg, azArg, azCol, NULL); |
| 1296 | } |
| 1297 | |
| 1298 | /* |
| 1299 | ** Set the destination table field of the ShellState structure to |
| 1300 | ** the name of the table given. Escape any quote characters in the |
| 1301 | ** table name. |
| 1302 | */ |
| 1303 | static void set_table_name(ShellState *p, const char *zName){ |
| 1304 | int i, n; |
| 1305 | int needQuote; |
| 1306 | char *z; |
| 1307 | |
| 1308 | if( p->zDestTable ){ |
| 1309 | free(p->zDestTable); |
| 1310 | p->zDestTable = 0; |
| 1311 | } |
| 1312 | if( zName==0 ) return; |
| 1313 | needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; |
| 1314 | for(i=n=0; zName[i]; i++, n++){ |
| 1315 | if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ |
| 1316 | needQuote = 1; |
| 1317 | if( zName[i]=='\'' ) n++; |
| 1318 | } |
| 1319 | } |
| 1320 | if( needQuote ) n += 2; |
| 1321 | z = p->zDestTable = malloc( n+1 ); |
| 1322 | if( z==0 ){ |
| 1323 | raw_printf(stderr,"Error: out of memory\n"); |
| 1324 | exit(1); |
| 1325 | } |
| 1326 | n = 0; |
| 1327 | if( needQuote ) z[n++] = '\''; |
| 1328 | for(i=0; zName[i]; i++){ |
| 1329 | z[n++] = zName[i]; |
| 1330 | if( zName[i]=='\'' ) z[n++] = '\''; |
| 1331 | } |
| 1332 | if( needQuote ) z[n++] = '\''; |
| 1333 | z[n] = 0; |
| 1334 | } |
| 1335 | |
| 1336 | /* zIn is either a pointer to a NULL-terminated string in memory obtained |
| 1337 | ** from malloc(), or a NULL pointer. The string pointed to by zAppend is |
| 1338 | ** added to zIn, and the result returned in memory obtained from malloc(). |
| 1339 | ** zIn, if it was not NULL, is freed. |
| 1340 | ** |
| 1341 | ** If the third argument, quote, is not '\0', then it is used as a |
| 1342 | ** quote character for zAppend. |
| 1343 | */ |
| 1344 | static char *appendText(char *zIn, char const *zAppend, char quote){ |
| 1345 | int len; |
| 1346 | int i; |
| 1347 | int nAppend = strlen30(zAppend); |
| 1348 | int nIn = (zIn?strlen30(zIn):0); |
| 1349 | |
| 1350 | len = nAppend+nIn+1; |
| 1351 | if( quote ){ |
| 1352 | len += 2; |
| 1353 | for(i=0; i<nAppend; i++){ |
| 1354 | if( zAppend[i]==quote ) len++; |
| 1355 | } |
| 1356 | } |
| 1357 | |
| 1358 | zIn = (char *)realloc(zIn, len); |
| 1359 | if( !zIn ){ |
| 1360 | return 0; |
| 1361 | } |
| 1362 | |
| 1363 | if( quote ){ |
| 1364 | char *zCsr = &zIn[nIn]; |
| 1365 | *zCsr++ = quote; |
| 1366 | for(i=0; i<nAppend; i++){ |
| 1367 | *zCsr++ = zAppend[i]; |
| 1368 | if( zAppend[i]==quote ) *zCsr++ = quote; |
| 1369 | } |
| 1370 | *zCsr++ = quote; |
| 1371 | *zCsr++ = '\0'; |
| 1372 | assert( (zCsr-zIn)==len ); |
| 1373 | }else{ |
| 1374 | memcpy(&zIn[nIn], zAppend, nAppend); |
| 1375 | zIn[len-1] = '\0'; |
| 1376 | } |
| 1377 | |
| 1378 | return zIn; |
| 1379 | } |
| 1380 | |
| 1381 | |
| 1382 | /* |
| 1383 | ** Execute a query statement that will generate SQL output. Print |
| @@ -1484,10 +2257,35 @@ | |
| 1484 | } |
| 1485 | fclose(in); |
| 1486 | } |
| 1487 | #endif |
| 1488 | |
| 1489 | |
| 1490 | /* |
| 1491 | ** Display memory stats. |
| 1492 | */ |
| 1493 | static int display_stats( |
| @@ -1497,61 +2295,35 @@ | |
| 1497 | ){ |
| 1498 | int iCur; |
| 1499 | int iHiwtr; |
| 1500 | |
| 1501 | if( pArg && pArg->out ){ |
| 1502 | |
| 1503 | iHiwtr = iCur = -1; |
| 1504 | sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); |
| 1505 | raw_printf(pArg->out, |
| 1506 | "Memory Used: %d (max %d) bytes\n", |
| 1507 | iCur, iHiwtr); |
| 1508 | iHiwtr = iCur = -1; |
| 1509 | sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); |
| 1510 | raw_printf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", |
| 1511 | iCur, iHiwtr); |
| 1512 | if( pArg->shellFlgs & SHFLG_Pagecache ){ |
| 1513 | iHiwtr = iCur = -1; |
| 1514 | sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); |
| 1515 | raw_printf(pArg->out, |
| 1516 | "Number of Pcache Pages Used: %d (max %d) pages\n", |
| 1517 | iCur, iHiwtr); |
| 1518 | } |
| 1519 | iHiwtr = iCur = -1; |
| 1520 | sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); |
| 1521 | raw_printf(pArg->out, |
| 1522 | "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", |
| 1523 | iCur, iHiwtr); |
| 1524 | if( pArg->shellFlgs & SHFLG_Scratch ){ |
| 1525 | iHiwtr = iCur = -1; |
| 1526 | sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); |
| 1527 | raw_printf(pArg->out, |
| 1528 | "Number of Scratch Allocations Used: %d (max %d)\n", |
| 1529 | iCur, iHiwtr); |
| 1530 | } |
| 1531 | iHiwtr = iCur = -1; |
| 1532 | sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); |
| 1533 | raw_printf(pArg->out, |
| 1534 | "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", |
| 1535 | iCur, iHiwtr); |
| 1536 | iHiwtr = iCur = -1; |
| 1537 | sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); |
| 1538 | raw_printf(pArg->out, "Largest Allocation: %d bytes\n", |
| 1539 | iHiwtr); |
| 1540 | iHiwtr = iCur = -1; |
| 1541 | sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); |
| 1542 | raw_printf(pArg->out, "Largest Pcache Allocation: %d bytes\n", |
| 1543 | iHiwtr); |
| 1544 | iHiwtr = iCur = -1; |
| 1545 | sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); |
| 1546 | raw_printf(pArg->out, "Largest Scratch Allocation: %d bytes\n", |
| 1547 | iHiwtr); |
| 1548 | #ifdef YYTRACKMAXSTACKDEPTH |
| 1549 | iHiwtr = iCur = -1; |
| 1550 | sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset); |
| 1551 | raw_printf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", |
| 1552 | iCur, iHiwtr); |
| 1553 | #endif |
| 1554 | } |
| 1555 | |
| 1556 | if( pArg && pArg->out && db ){ |
| 1557 | if( pArg->shellFlgs & SHFLG_Lookaside ){ |
| @@ -1934,11 +2706,11 @@ | |
| 1934 | pArg->pStmt = pStmt; |
| 1935 | pArg->cnt = 0; |
| 1936 | } |
| 1937 | |
| 1938 | /* echo the sql statement if echo on */ |
| 1939 | if( pArg && pArg->echoOn ){ |
| 1940 | utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); |
| 1941 | } |
| 1942 | |
| 1943 | /* Show the EXPLAIN QUERY PLAN if .eqp is on */ |
| 1944 | if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){ |
| @@ -2022,10 +2794,142 @@ | |
| 2022 | } /* end while */ |
| 2023 | |
| 2024 | return rc; |
| 2025 | } |
| 2026 | |
| 2027 | |
| 2028 | /* |
| 2029 | ** This is a different callback routine used for dumping the database. |
| 2030 | ** Each row received by this callback consists of a table name, |
| 2031 | ** the table type ("index" or "table") and SQL to create the table. |
| @@ -2034,21 +2938,20 @@ | |
| 2034 | static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ |
| 2035 | int rc; |
| 2036 | const char *zTable; |
| 2037 | const char *zType; |
| 2038 | const char *zSql; |
| 2039 | const char *zPrepStmt = 0; |
| 2040 | ShellState *p = (ShellState *)pArg; |
| 2041 | |
| 2042 | UNUSED_PARAMETER(azCol); |
| 2043 | if( nArg!=3 ) return 1; |
| 2044 | zTable = azArg[0]; |
| 2045 | zType = azArg[1]; |
| 2046 | zSql = azArg[2]; |
| 2047 | |
| 2048 | if( strcmp(zTable, "sqlite_sequence")==0 ){ |
| 2049 | zPrepStmt = "DELETE FROM sqlite_sequence;\n"; |
| 2050 | }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ |
| 2051 | raw_printf(p->out, "ANALYZE sqlite_master;\n"); |
| 2052 | }else if( strncmp(zTable, "sqlite_", 7)==0 ){ |
| 2053 | return 0; |
| 2054 | }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ |
| @@ -2067,62 +2970,74 @@ | |
| 2067 | }else{ |
| 2068 | printSchemaLine(p->out, zSql, ";\n"); |
| 2069 | } |
| 2070 | |
| 2071 | if( strcmp(zType, "table")==0 ){ |
| 2072 | sqlite3_stmt *pTableInfo = 0; |
| 2073 | char *zSelect = 0; |
| 2074 | char *zTableInfo = 0; |
| 2075 | char *zTmp = 0; |
| 2076 | int nRow = 0; |
| 2077 | |
| 2078 | zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); |
| 2079 | zTableInfo = appendText(zTableInfo, zTable, '"'); |
| 2080 | zTableInfo = appendText(zTableInfo, ");", 0); |
| 2081 | |
| 2082 | rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); |
| 2083 | free(zTableInfo); |
| 2084 | if( rc!=SQLITE_OK || !pTableInfo ){ |
| 2085 | return 1; |
| 2086 | } |
| 2087 | |
| 2088 | zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); |
| 2089 | /* Always quote the table name, even if it appears to be pure ascii, |
| 2090 | ** in case it is a keyword. Ex: INSERT INTO "table" ... */ |
| 2091 | zTmp = appendText(zTmp, zTable, '"'); |
| 2092 | if( zTmp ){ |
| 2093 | zSelect = appendText(zSelect, zTmp, '\''); |
| 2094 | free(zTmp); |
| 2095 | } |
| 2096 | zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); |
| 2097 | rc = sqlite3_step(pTableInfo); |
| 2098 | while( rc==SQLITE_ROW ){ |
| 2099 | const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); |
| 2100 | zSelect = appendText(zSelect, "quote(", 0); |
| 2101 | zSelect = appendText(zSelect, zText, '"'); |
| 2102 | rc = sqlite3_step(pTableInfo); |
| 2103 | if( rc==SQLITE_ROW ){ |
| 2104 | zSelect = appendText(zSelect, "), ", 0); |
| 2105 | }else{ |
| 2106 | zSelect = appendText(zSelect, ") ", 0); |
| 2107 | } |
| 2108 | nRow++; |
| 2109 | } |
| 2110 | rc = sqlite3_finalize(pTableInfo); |
| 2111 | if( rc!=SQLITE_OK || nRow==0 ){ |
| 2112 | free(zSelect); |
| 2113 | return 1; |
| 2114 | } |
| 2115 | zSelect = appendText(zSelect, "|| ')' FROM ", 0); |
| 2116 | zSelect = appendText(zSelect, zTable, '"'); |
| 2117 | |
| 2118 | rc = run_table_dump_query(p, zSelect, zPrepStmt); |
| 2119 | if( rc==SQLITE_CORRUPT ){ |
| 2120 | zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); |
| 2121 | run_table_dump_query(p, zSelect, 0); |
| 2122 | } |
| 2123 | free(zSelect); |
| 2124 | } |
| 2125 | return 0; |
| 2126 | } |
| 2127 | |
| 2128 | /* |
| @@ -2210,11 +3125,11 @@ | |
| 2210 | " csv Comma-separated values\n" |
| 2211 | " column Left-aligned columns. (See .width)\n" |
| 2212 | " html HTML <table> code\n" |
| 2213 | " insert SQL insert statements for TABLE\n" |
| 2214 | " line One value per line\n" |
| 2215 | " list Values delimited by .separator strings\n" |
| 2216 | " quote Escape answers as for SQL\n" |
| 2217 | " tabs Tab-separated values\n" |
| 2218 | " tcl TCL list elements\n" |
| 2219 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2220 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| @@ -2233,10 +3148,11 @@ | |
| 2233 | ".separator COL ?ROW? Change the column separator and optionally the row\n" |
| 2234 | " separator for both the output mode and .import\n" |
| 2235 | #if defined(SQLITE_ENABLE_SESSION) |
| 2236 | ".session CMD ... Create or control sessions\n" |
| 2237 | #endif |
| 2238 | ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" |
| 2239 | ".show Show the current values for various settings\n" |
| 2240 | ".stats ?on|off? Show stats or turn stats on or off\n" |
| 2241 | ".system CMD ARGS... Run CMD ARGS... in a system shell\n" |
| 2242 | ".tables ?TABLE? List names of tables\n" |
| @@ -2423,14 +3339,10 @@ | |
| 2423 | static void open_db(ShellState *p, int keepAlive){ |
| 2424 | if( p->db==0 ){ |
| 2425 | sqlite3_initialize(); |
| 2426 | sqlite3_open(p->zDbFilename, &p->db); |
| 2427 | globalDb = p->db; |
| 2428 | if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){ |
| 2429 | sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0, |
| 2430 | shellstaticFunc, 0, 0); |
| 2431 | } |
| 2432 | if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ |
| 2433 | utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", |
| 2434 | p->zDbFilename, sqlite3_errmsg(p->db)); |
| 2435 | if( keepAlive ) return; |
| 2436 | exit(1); |
| @@ -2440,10 +3352,18 @@ | |
| 2440 | #endif |
| 2441 | sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0, |
| 2442 | readfileFunc, 0, 0); |
| 2443 | sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0, |
| 2444 | writefileFunc, 0, 0); |
| 2445 | } |
| 2446 | } |
| 2447 | |
| 2448 | /* |
| 2449 | ** Do C-language style dequoting. |
| @@ -2564,11 +3484,11 @@ | |
| 2564 | |
| 2565 | /* |
| 2566 | ** Interpret zArg as either an integer or a boolean value. Return 1 or 0 |
| 2567 | ** for TRUE and FALSE. Return the integer value if appropriate. |
| 2568 | */ |
| 2569 | static int booleanValue(char *zArg){ |
| 2570 | int i; |
| 2571 | if( zArg[0]=='0' && zArg[1]=='x' ){ |
| 2572 | for(i=2; hexDigitValue(zArg[i])>=0; i++){} |
| 2573 | }else{ |
| 2574 | for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} |
| @@ -2582,10 +3502,21 @@ | |
| 2582 | } |
| 2583 | utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", |
| 2584 | zArg); |
| 2585 | return 0; |
| 2586 | } |
| 2587 | |
| 2588 | /* |
| 2589 | ** Close an output file, assuming it is not stderr or stdout |
| 2590 | */ |
| 2591 | static void output_file_close(FILE *f){ |
| @@ -3656,11 +4587,11 @@ | |
| 3656 | test_breakpoint(); |
| 3657 | }else |
| 3658 | |
| 3659 | if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ |
| 3660 | if( nArg==2 ){ |
| 3661 | p->countChanges = booleanValue(azArg[1]); |
| 3662 | }else{ |
| 3663 | raw_printf(stderr, "Usage: .changes on|off\n"); |
| 3664 | rc = 1; |
| 3665 | } |
| 3666 | }else |
| @@ -3720,25 +4651,46 @@ | |
| 3720 | if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ |
| 3721 | rc = shell_dbinfo_command(p, nArg, azArg); |
| 3722 | }else |
| 3723 | |
| 3724 | if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ |
| 3725 | open_db(p, 0); |
| 3726 | /* When playing back a "dump", the content might appear in an order |
| 3727 | ** which causes immediate foreign key constraints to be violated. |
| 3728 | ** So disable foreign-key constraint enforcement to prevent problems. */ |
| 3729 | if( nArg!=1 && nArg!=2 ){ |
| 3730 | raw_printf(stderr, "Usage: .dump ?LIKE-PATTERN?\n"); |
| 3731 | rc = 1; |
| 3732 | goto meta_command_exit; |
| 3733 | } |
| 3734 | raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); |
| 3735 | raw_printf(p->out, "BEGIN TRANSACTION;\n"); |
| 3736 | p->writableSchema = 0; |
| 3737 | sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); |
| 3738 | p->nErr = 0; |
| 3739 | if( nArg==1 ){ |
| 3740 | run_schema_dump_query(p, |
| 3741 | "SELECT name, type, sql FROM sqlite_master " |
| 3742 | "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" |
| 3743 | ); |
| 3744 | run_schema_dump_query(p, |
| @@ -3748,25 +4700,24 @@ | |
| 3748 | run_table_dump_query(p, |
| 3749 | "SELECT sql FROM sqlite_master " |
| 3750 | "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 |
| 3751 | ); |
| 3752 | }else{ |
| 3753 | int i; |
| 3754 | for(i=1; i<nArg; i++){ |
| 3755 | zShellStatic = azArg[i]; |
| 3756 | run_schema_dump_query(p, |
| 3757 | "SELECT name, type, sql FROM sqlite_master " |
| 3758 | "WHERE tbl_name LIKE shellstatic() AND type=='table'" |
| 3759 | " AND sql NOT NULL"); |
| 3760 | run_table_dump_query(p, |
| 3761 | "SELECT sql FROM sqlite_master " |
| 3762 | "WHERE sql NOT NULL" |
| 3763 | " AND type IN ('index','trigger','view')" |
| 3764 | " AND tbl_name LIKE shellstatic()", 0 |
| 3765 | ); |
| 3766 | zShellStatic = 0; |
| 3767 | } |
| 3768 | } |
| 3769 | if( p->writableSchema ){ |
| 3770 | raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); |
| 3771 | p->writableSchema = 0; |
| 3772 | } |
| @@ -3775,11 +4726,11 @@ | |
| 3775 | raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); |
| 3776 | }else |
| 3777 | |
| 3778 | if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ |
| 3779 | if( nArg==2 ){ |
| 3780 | p->echoOn = booleanValue(azArg[1]); |
| 3781 | }else{ |
| 3782 | raw_printf(stderr, "Usage: .echo on|off\n"); |
| 3783 | rc = 1; |
| 3784 | } |
| 3785 | }else |
| @@ -4342,10 +5293,11 @@ | |
| 4342 | int newFlag = 0; /* True to delete file before opening */ |
| 4343 | /* Close the existing database */ |
| 4344 | session_close_all(p); |
| 4345 | sqlite3_close(p->db); |
| 4346 | p->db = 0; |
| 4347 | sqlite3_free(p->zFreeOnClose); |
| 4348 | p->zFreeOnClose = 0; |
| 4349 | /* Check for command-line arguments */ |
| 4350 | for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){ |
| 4351 | const char *z = azArg[iName]; |
| @@ -4571,21 +5523,21 @@ | |
| 4571 | new_colv[0] = "sql"; |
| 4572 | new_colv[1] = 0; |
| 4573 | callback(&data, 1, new_argv, new_colv); |
| 4574 | rc = SQLITE_OK; |
| 4575 | }else{ |
| 4576 | zShellStatic = azArg[1]; |
| 4577 | rc = sqlite3_exec(p->db, |
| 4578 | "SELECT sql FROM " |
| 4579 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 4580 | " FROM sqlite_master UNION ALL" |
| 4581 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 4582 | "WHERE lower(tbl_name) LIKE shellstatic()" |
| 4583 | " AND type!='meta' AND sql NOTNULL " |
| 4584 | "ORDER BY rowid", |
| 4585 | callback, &data, &zErrMsg); |
| 4586 | zShellStatic = 0; |
| 4587 | } |
| 4588 | }else if( nArg==1 ){ |
| 4589 | rc = sqlite3_exec(p->db, |
| 4590 | "SELECT sql FROM " |
| 4591 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| @@ -4612,11 +5564,11 @@ | |
| 4612 | } |
| 4613 | }else |
| 4614 | |
| 4615 | #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 4616 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ |
| 4617 | sqlite3SelectTrace = integerValue(azArg[1]); |
| 4618 | }else |
| 4619 | #endif |
| 4620 | |
| 4621 | #if defined(SQLITE_ENABLE_SESSION) |
| 4622 | if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ |
| @@ -4834,10 +5786,123 @@ | |
| 4834 | utf8_printf(p->out, "%s", zBuf); |
| 4835 | } |
| 4836 | } |
| 4837 | }else |
| 4838 | #endif |
| 4839 | |
| 4840 | if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ |
| 4841 | if( nArg<2 || nArg>3 ){ |
| 4842 | raw_printf(stderr, "Usage: .separator COL ?ROW?\n"); |
| 4843 | rc = 1; |
| @@ -4849,10 +5914,126 @@ | |
| 4849 | if( nArg>=3 ){ |
| 4850 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, |
| 4851 | "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); |
| 4852 | } |
| 4853 | }else |
| 4854 | |
| 4855 | if( c=='s' |
| 4856 | && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) |
| 4857 | ){ |
| 4858 | char *zCmd; |
| @@ -4878,11 +6059,12 @@ | |
| 4878 | if( nArg!=1 ){ |
| 4879 | raw_printf(stderr, "Usage: .show\n"); |
| 4880 | rc = 1; |
| 4881 | goto meta_command_exit; |
| 4882 | } |
| 4883 | utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[p->echoOn!=0]); |
| 4884 | utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); |
| 4885 | utf8_printf(p->out, "%12.12s: %s\n","explain", |
| 4886 | p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); |
| 4887 | utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); |
| 4888 | utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); |
| @@ -5190,10 +6372,11 @@ | |
| 5190 | azArg[1]); |
| 5191 | break; |
| 5192 | } |
| 5193 | } |
| 5194 | }else |
| 5195 | |
| 5196 | if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ |
| 5197 | open_db(p, 0); |
| 5198 | sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); |
| 5199 | }else |
| @@ -5226,11 +6409,10 @@ | |
| 5226 | }else{ |
| 5227 | sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut); |
| 5228 | } |
| 5229 | #endif |
| 5230 | }else |
| 5231 | #endif /* !defined(SQLITE_UNTESTABLE) */ |
| 5232 | |
| 5233 | #if SQLITE_USER_AUTHENTICATION |
| 5234 | if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ |
| 5235 | if( nArg<2 ){ |
| 5236 | raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); |
| @@ -5443,11 +6625,11 @@ | |
| 5443 | static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ |
| 5444 | int rc; |
| 5445 | char *zErrMsg = 0; |
| 5446 | |
| 5447 | open_db(p, 0); |
| 5448 | if( p->backslashOn ) resolve_backslashes(zSql); |
| 5449 | BEGIN_TIMER; |
| 5450 | rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); |
| 5451 | END_TIMER; |
| 5452 | if( rc || zErrMsg ){ |
| 5453 | char zPrefix[100]; |
| @@ -5463,11 +6645,11 @@ | |
| 5463 | zErrMsg = 0; |
| 5464 | }else{ |
| 5465 | utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); |
| 5466 | } |
| 5467 | return 1; |
| 5468 | }else if( p->countChanges ){ |
| 5469 | raw_printf(p->out, "changes: %3d total_changes: %d\n", |
| 5470 | sqlite3_changes(p->db), sqlite3_total_changes(p->db)); |
| 5471 | } |
| 5472 | return 0; |
| 5473 | } |
| @@ -5506,15 +6688,15 @@ | |
| 5506 | if( in!=0 ) break; |
| 5507 | seenInterrupt = 0; |
| 5508 | } |
| 5509 | lineno++; |
| 5510 | if( nSql==0 && _all_whitespace(zLine) ){ |
| 5511 | if( p->echoOn ) printf("%s\n", zLine); |
| 5512 | continue; |
| 5513 | } |
| 5514 | if( zLine && zLine[0]=='.' && nSql==0 ){ |
| 5515 | if( p->echoOn ) printf("%s\n", zLine); |
| 5516 | rc = do_meta_command(zLine, p); |
| 5517 | if( rc==2 ){ /* exit requested */ |
| 5518 | break; |
| 5519 | }else if( rc ){ |
| 5520 | errCnt++; |
| @@ -5553,11 +6735,11 @@ | |
| 5553 | if( p->outCount ){ |
| 5554 | output_reset(p); |
| 5555 | p->outCount = 0; |
| 5556 | } |
| 5557 | }else if( nSql && _all_whitespace(zSql) ){ |
| 5558 | if( p->echoOn ) printf("%s\n", zSql); |
| 5559 | nSql = 0; |
| 5560 | } |
| 5561 | } |
| 5562 | if( nSql && !_all_whitespace(zSql) ){ |
| 5563 | runOneSqlLine(p, zSql, in, startline); |
| @@ -6022,11 +7204,11 @@ | |
| 6022 | }else if( strcmp(z,"-header")==0 ){ |
| 6023 | data.showHeader = 1; |
| 6024 | }else if( strcmp(z,"-noheader")==0 ){ |
| 6025 | data.showHeader = 0; |
| 6026 | }else if( strcmp(z,"-echo")==0 ){ |
| 6027 | data.echoOn = 1; |
| 6028 | }else if( strcmp(z,"-eqp")==0 ){ |
| 6029 | data.autoEQP = 1; |
| 6030 | }else if( strcmp(z,"-eqpfull")==0 ){ |
| 6031 | data.autoEQP = 2; |
| 6032 | }else if( strcmp(z,"-stats")==0 ){ |
| @@ -6037,11 +7219,11 @@ | |
| 6037 | /* Undocumented command-line option: -backslash |
| 6038 | ** Causes C-style backslash escapes to be evaluated in SQL statements |
| 6039 | ** prior to sending the SQL into SQLite. Useful for injecting |
| 6040 | ** crazy bytes in the middle of SQL statements for testing and debugging. |
| 6041 | */ |
| 6042 | data.backslashOn = 1; |
| 6043 | }else if( strcmp(z,"-bail")==0 ){ |
| 6044 | bail_on_error = 1; |
| 6045 | }else if( strcmp(z,"-version")==0 ){ |
| 6046 | printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); |
| 6047 | return 0; |
| 6048 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -452,32 +452,10 @@ | |
| 452 | while( IsDigit(*z) ){ z++; } |
| 453 | if( realnum ) *realnum = 1; |
| 454 | } |
| 455 | return *z==0; |
| 456 | } |
| 457 | |
| 458 | /* |
| 459 | ** Compute a string length that is limited to what can be stored in |
| 460 | ** lower 30 bits of a 32-bit signed integer. |
| 461 | */ |
| @@ -575,10 +553,783 @@ | |
| 553 | if( zResult && *zResult ) shell_add_history(zResult); |
| 554 | #endif |
| 555 | } |
| 556 | return zResult; |
| 557 | } |
| 558 | /* |
| 559 | ** A variable length string to which one can append text. |
| 560 | */ |
| 561 | typedef struct ShellText ShellText; |
| 562 | struct ShellText { |
| 563 | char *z; |
| 564 | int n; |
| 565 | int nAlloc; |
| 566 | }; |
| 567 | |
| 568 | /* |
| 569 | ** Initialize and destroy a ShellText object |
| 570 | */ |
| 571 | static void initText(ShellText *p){ |
| 572 | memset(p, 0, sizeof(*p)); |
| 573 | } |
| 574 | static void freeText(ShellText *p){ |
| 575 | free(p->z); |
| 576 | initText(p); |
| 577 | } |
| 578 | |
| 579 | /* zIn is either a pointer to a NULL-terminated string in memory obtained |
| 580 | ** from malloc(), or a NULL pointer. The string pointed to by zAppend is |
| 581 | ** added to zIn, and the result returned in memory obtained from malloc(). |
| 582 | ** zIn, if it was not NULL, is freed. |
| 583 | ** |
| 584 | ** If the third argument, quote, is not '\0', then it is used as a |
| 585 | ** quote character for zAppend. |
| 586 | */ |
| 587 | static void appendText(ShellText *p, char const *zAppend, char quote){ |
| 588 | int len; |
| 589 | int i; |
| 590 | int nAppend = strlen30(zAppend); |
| 591 | |
| 592 | len = nAppend+p->n+1; |
| 593 | if( quote ){ |
| 594 | len += 2; |
| 595 | for(i=0; i<nAppend; i++){ |
| 596 | if( zAppend[i]==quote ) len++; |
| 597 | } |
| 598 | } |
| 599 | |
| 600 | if( p->n+len>=p->nAlloc ){ |
| 601 | p->nAlloc = p->nAlloc*2 + len + 20; |
| 602 | p->z = realloc(p->z, p->nAlloc); |
| 603 | if( p->z==0 ){ |
| 604 | memset(p, 0, sizeof(*p)); |
| 605 | return; |
| 606 | } |
| 607 | } |
| 608 | |
| 609 | if( quote ){ |
| 610 | char *zCsr = p->z+p->n; |
| 611 | *zCsr++ = quote; |
| 612 | for(i=0; i<nAppend; i++){ |
| 613 | *zCsr++ = zAppend[i]; |
| 614 | if( zAppend[i]==quote ) *zCsr++ = quote; |
| 615 | } |
| 616 | *zCsr++ = quote; |
| 617 | p->n = (int)(zCsr - p->z); |
| 618 | *zCsr = '\0'; |
| 619 | }else{ |
| 620 | memcpy(p->z+p->n, zAppend, nAppend); |
| 621 | p->n += nAppend; |
| 622 | p->z[p->n] = '\0'; |
| 623 | } |
| 624 | } |
| 625 | |
| 626 | /* |
| 627 | ** Attempt to determine if identifier zName needs to be quoted, either |
| 628 | ** because it contains non-alphanumeric characters, or because it is an |
| 629 | ** SQLite keyword. Be conservative in this estimate: When in doubt assume |
| 630 | ** that quoting is required. |
| 631 | ** |
| 632 | ** Return '"' if quoting is required. Return 0 if no quoting is required. |
| 633 | */ |
| 634 | static char quoteChar(const char *zName){ |
| 635 | /* All SQLite keywords, in alphabetical order */ |
| 636 | static const char *azKeywords[] = { |
| 637 | "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", |
| 638 | "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", |
| 639 | "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", |
| 640 | "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", |
| 641 | "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", |
| 642 | "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", |
| 643 | "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", |
| 644 | "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", |
| 645 | "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", |
| 646 | "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", |
| 647 | "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", |
| 648 | "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", |
| 649 | "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", |
| 650 | "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", |
| 651 | "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", |
| 652 | "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", |
| 653 | "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", |
| 654 | "WITH", "WITHOUT", |
| 655 | }; |
| 656 | int i, lwr, upr, mid, c; |
| 657 | if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; |
| 658 | for(i=0; zName[i]; i++){ |
| 659 | if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; |
| 660 | } |
| 661 | lwr = 0; |
| 662 | upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; |
| 663 | while( lwr<=upr ){ |
| 664 | mid = (lwr+upr)/2; |
| 665 | c = sqlite3_stricmp(azKeywords[mid], zName); |
| 666 | if( c==0 ) return '"'; |
| 667 | if( c<0 ){ |
| 668 | lwr = mid+1; |
| 669 | }else{ |
| 670 | upr = mid-1; |
| 671 | } |
| 672 | } |
| 673 | return 0; |
| 674 | } |
| 675 | |
| 676 | /****************************************************************************** |
| 677 | ** SHA3 hash implementation copied from ../ext/misc/shathree.c |
| 678 | */ |
| 679 | typedef sqlite3_uint64 u64; |
| 680 | /* |
| 681 | ** Macros to determine whether the machine is big or little endian, |
| 682 | ** and whether or not that determination is run-time or compile-time. |
| 683 | ** |
| 684 | ** For best performance, an attempt is made to guess at the byte-order |
| 685 | ** using C-preprocessor macros. If that is unsuccessful, or if |
| 686 | ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined |
| 687 | ** at run-time. |
| 688 | */ |
| 689 | #ifndef SHA3_BYTEORDER |
| 690 | # if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ |
| 691 | defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ |
| 692 | defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ |
| 693 | defined(__arm__) |
| 694 | # define SHA3_BYTEORDER 1234 |
| 695 | # elif defined(sparc) || defined(__ppc__) |
| 696 | # define SHA3_BYTEORDER 4321 |
| 697 | # else |
| 698 | # define SHA3_BYTEORDER 0 |
| 699 | # endif |
| 700 | #endif |
| 701 | |
| 702 | |
| 703 | /* |
| 704 | ** State structure for a SHA3 hash in progress |
| 705 | */ |
| 706 | typedef struct SHA3Context SHA3Context; |
| 707 | struct SHA3Context { |
| 708 | union { |
| 709 | u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ |
| 710 | unsigned char x[1600]; /* ... or 1600 bytes */ |
| 711 | } u; |
| 712 | unsigned nRate; /* Bytes of input accepted per Keccak iteration */ |
| 713 | unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ |
| 714 | unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ |
| 715 | }; |
| 716 | |
| 717 | /* |
| 718 | ** A single step of the Keccak mixing function for a 1600-bit state |
| 719 | */ |
| 720 | static void KeccakF1600Step(SHA3Context *p){ |
| 721 | int i; |
| 722 | u64 B0, B1, B2, B3, B4; |
| 723 | u64 C0, C1, C2, C3, C4; |
| 724 | u64 D0, D1, D2, D3, D4; |
| 725 | static const u64 RC[] = { |
| 726 | 0x0000000000000001ULL, 0x0000000000008082ULL, |
| 727 | 0x800000000000808aULL, 0x8000000080008000ULL, |
| 728 | 0x000000000000808bULL, 0x0000000080000001ULL, |
| 729 | 0x8000000080008081ULL, 0x8000000000008009ULL, |
| 730 | 0x000000000000008aULL, 0x0000000000000088ULL, |
| 731 | 0x0000000080008009ULL, 0x000000008000000aULL, |
| 732 | 0x000000008000808bULL, 0x800000000000008bULL, |
| 733 | 0x8000000000008089ULL, 0x8000000000008003ULL, |
| 734 | 0x8000000000008002ULL, 0x8000000000000080ULL, |
| 735 | 0x000000000000800aULL, 0x800000008000000aULL, |
| 736 | 0x8000000080008081ULL, 0x8000000000008080ULL, |
| 737 | 0x0000000080000001ULL, 0x8000000080008008ULL |
| 738 | }; |
| 739 | # define A00 (p->u.s[0]) |
| 740 | # define A01 (p->u.s[1]) |
| 741 | # define A02 (p->u.s[2]) |
| 742 | # define A03 (p->u.s[3]) |
| 743 | # define A04 (p->u.s[4]) |
| 744 | # define A10 (p->u.s[5]) |
| 745 | # define A11 (p->u.s[6]) |
| 746 | # define A12 (p->u.s[7]) |
| 747 | # define A13 (p->u.s[8]) |
| 748 | # define A14 (p->u.s[9]) |
| 749 | # define A20 (p->u.s[10]) |
| 750 | # define A21 (p->u.s[11]) |
| 751 | # define A22 (p->u.s[12]) |
| 752 | # define A23 (p->u.s[13]) |
| 753 | # define A24 (p->u.s[14]) |
| 754 | # define A30 (p->u.s[15]) |
| 755 | # define A31 (p->u.s[16]) |
| 756 | # define A32 (p->u.s[17]) |
| 757 | # define A33 (p->u.s[18]) |
| 758 | # define A34 (p->u.s[19]) |
| 759 | # define A40 (p->u.s[20]) |
| 760 | # define A41 (p->u.s[21]) |
| 761 | # define A42 (p->u.s[22]) |
| 762 | # define A43 (p->u.s[23]) |
| 763 | # define A44 (p->u.s[24]) |
| 764 | # define ROL64(a,x) ((a<<x)|(a>>(64-x))) |
| 765 | |
| 766 | for(i=0; i<24; i+=4){ |
| 767 | C0 = A00^A10^A20^A30^A40; |
| 768 | C1 = A01^A11^A21^A31^A41; |
| 769 | C2 = A02^A12^A22^A32^A42; |
| 770 | C3 = A03^A13^A23^A33^A43; |
| 771 | C4 = A04^A14^A24^A34^A44; |
| 772 | D0 = C4^ROL64(C1, 1); |
| 773 | D1 = C0^ROL64(C2, 1); |
| 774 | D2 = C1^ROL64(C3, 1); |
| 775 | D3 = C2^ROL64(C4, 1); |
| 776 | D4 = C3^ROL64(C0, 1); |
| 777 | |
| 778 | B0 = (A00^D0); |
| 779 | B1 = ROL64((A11^D1), 44); |
| 780 | B2 = ROL64((A22^D2), 43); |
| 781 | B3 = ROL64((A33^D3), 21); |
| 782 | B4 = ROL64((A44^D4), 14); |
| 783 | A00 = B0 ^((~B1)& B2 ); |
| 784 | A00 ^= RC[i]; |
| 785 | A11 = B1 ^((~B2)& B3 ); |
| 786 | A22 = B2 ^((~B3)& B4 ); |
| 787 | A33 = B3 ^((~B4)& B0 ); |
| 788 | A44 = B4 ^((~B0)& B1 ); |
| 789 | |
| 790 | B2 = ROL64((A20^D0), 3); |
| 791 | B3 = ROL64((A31^D1), 45); |
| 792 | B4 = ROL64((A42^D2), 61); |
| 793 | B0 = ROL64((A03^D3), 28); |
| 794 | B1 = ROL64((A14^D4), 20); |
| 795 | A20 = B0 ^((~B1)& B2 ); |
| 796 | A31 = B1 ^((~B2)& B3 ); |
| 797 | A42 = B2 ^((~B3)& B4 ); |
| 798 | A03 = B3 ^((~B4)& B0 ); |
| 799 | A14 = B4 ^((~B0)& B1 ); |
| 800 | |
| 801 | B4 = ROL64((A40^D0), 18); |
| 802 | B0 = ROL64((A01^D1), 1); |
| 803 | B1 = ROL64((A12^D2), 6); |
| 804 | B2 = ROL64((A23^D3), 25); |
| 805 | B3 = ROL64((A34^D4), 8); |
| 806 | A40 = B0 ^((~B1)& B2 ); |
| 807 | A01 = B1 ^((~B2)& B3 ); |
| 808 | A12 = B2 ^((~B3)& B4 ); |
| 809 | A23 = B3 ^((~B4)& B0 ); |
| 810 | A34 = B4 ^((~B0)& B1 ); |
| 811 | |
| 812 | B1 = ROL64((A10^D0), 36); |
| 813 | B2 = ROL64((A21^D1), 10); |
| 814 | B3 = ROL64((A32^D2), 15); |
| 815 | B4 = ROL64((A43^D3), 56); |
| 816 | B0 = ROL64((A04^D4), 27); |
| 817 | A10 = B0 ^((~B1)& B2 ); |
| 818 | A21 = B1 ^((~B2)& B3 ); |
| 819 | A32 = B2 ^((~B3)& B4 ); |
| 820 | A43 = B3 ^((~B4)& B0 ); |
| 821 | A04 = B4 ^((~B0)& B1 ); |
| 822 | |
| 823 | B3 = ROL64((A30^D0), 41); |
| 824 | B4 = ROL64((A41^D1), 2); |
| 825 | B0 = ROL64((A02^D2), 62); |
| 826 | B1 = ROL64((A13^D3), 55); |
| 827 | B2 = ROL64((A24^D4), 39); |
| 828 | A30 = B0 ^((~B1)& B2 ); |
| 829 | A41 = B1 ^((~B2)& B3 ); |
| 830 | A02 = B2 ^((~B3)& B4 ); |
| 831 | A13 = B3 ^((~B4)& B0 ); |
| 832 | A24 = B4 ^((~B0)& B1 ); |
| 833 | |
| 834 | C0 = A00^A20^A40^A10^A30; |
| 835 | C1 = A11^A31^A01^A21^A41; |
| 836 | C2 = A22^A42^A12^A32^A02; |
| 837 | C3 = A33^A03^A23^A43^A13; |
| 838 | C4 = A44^A14^A34^A04^A24; |
| 839 | D0 = C4^ROL64(C1, 1); |
| 840 | D1 = C0^ROL64(C2, 1); |
| 841 | D2 = C1^ROL64(C3, 1); |
| 842 | D3 = C2^ROL64(C4, 1); |
| 843 | D4 = C3^ROL64(C0, 1); |
| 844 | |
| 845 | B0 = (A00^D0); |
| 846 | B1 = ROL64((A31^D1), 44); |
| 847 | B2 = ROL64((A12^D2), 43); |
| 848 | B3 = ROL64((A43^D3), 21); |
| 849 | B4 = ROL64((A24^D4), 14); |
| 850 | A00 = B0 ^((~B1)& B2 ); |
| 851 | A00 ^= RC[i+1]; |
| 852 | A31 = B1 ^((~B2)& B3 ); |
| 853 | A12 = B2 ^((~B3)& B4 ); |
| 854 | A43 = B3 ^((~B4)& B0 ); |
| 855 | A24 = B4 ^((~B0)& B1 ); |
| 856 | |
| 857 | B2 = ROL64((A40^D0), 3); |
| 858 | B3 = ROL64((A21^D1), 45); |
| 859 | B4 = ROL64((A02^D2), 61); |
| 860 | B0 = ROL64((A33^D3), 28); |
| 861 | B1 = ROL64((A14^D4), 20); |
| 862 | A40 = B0 ^((~B1)& B2 ); |
| 863 | A21 = B1 ^((~B2)& B3 ); |
| 864 | A02 = B2 ^((~B3)& B4 ); |
| 865 | A33 = B3 ^((~B4)& B0 ); |
| 866 | A14 = B4 ^((~B0)& B1 ); |
| 867 | |
| 868 | B4 = ROL64((A30^D0), 18); |
| 869 | B0 = ROL64((A11^D1), 1); |
| 870 | B1 = ROL64((A42^D2), 6); |
| 871 | B2 = ROL64((A23^D3), 25); |
| 872 | B3 = ROL64((A04^D4), 8); |
| 873 | A30 = B0 ^((~B1)& B2 ); |
| 874 | A11 = B1 ^((~B2)& B3 ); |
| 875 | A42 = B2 ^((~B3)& B4 ); |
| 876 | A23 = B3 ^((~B4)& B0 ); |
| 877 | A04 = B4 ^((~B0)& B1 ); |
| 878 | |
| 879 | B1 = ROL64((A20^D0), 36); |
| 880 | B2 = ROL64((A01^D1), 10); |
| 881 | B3 = ROL64((A32^D2), 15); |
| 882 | B4 = ROL64((A13^D3), 56); |
| 883 | B0 = ROL64((A44^D4), 27); |
| 884 | A20 = B0 ^((~B1)& B2 ); |
| 885 | A01 = B1 ^((~B2)& B3 ); |
| 886 | A32 = B2 ^((~B3)& B4 ); |
| 887 | A13 = B3 ^((~B4)& B0 ); |
| 888 | A44 = B4 ^((~B0)& B1 ); |
| 889 | |
| 890 | B3 = ROL64((A10^D0), 41); |
| 891 | B4 = ROL64((A41^D1), 2); |
| 892 | B0 = ROL64((A22^D2), 62); |
| 893 | B1 = ROL64((A03^D3), 55); |
| 894 | B2 = ROL64((A34^D4), 39); |
| 895 | A10 = B0 ^((~B1)& B2 ); |
| 896 | A41 = B1 ^((~B2)& B3 ); |
| 897 | A22 = B2 ^((~B3)& B4 ); |
| 898 | A03 = B3 ^((~B4)& B0 ); |
| 899 | A34 = B4 ^((~B0)& B1 ); |
| 900 | |
| 901 | C0 = A00^A40^A30^A20^A10; |
| 902 | C1 = A31^A21^A11^A01^A41; |
| 903 | C2 = A12^A02^A42^A32^A22; |
| 904 | C3 = A43^A33^A23^A13^A03; |
| 905 | C4 = A24^A14^A04^A44^A34; |
| 906 | D0 = C4^ROL64(C1, 1); |
| 907 | D1 = C0^ROL64(C2, 1); |
| 908 | D2 = C1^ROL64(C3, 1); |
| 909 | D3 = C2^ROL64(C4, 1); |
| 910 | D4 = C3^ROL64(C0, 1); |
| 911 | |
| 912 | B0 = (A00^D0); |
| 913 | B1 = ROL64((A21^D1), 44); |
| 914 | B2 = ROL64((A42^D2), 43); |
| 915 | B3 = ROL64((A13^D3), 21); |
| 916 | B4 = ROL64((A34^D4), 14); |
| 917 | A00 = B0 ^((~B1)& B2 ); |
| 918 | A00 ^= RC[i+2]; |
| 919 | A21 = B1 ^((~B2)& B3 ); |
| 920 | A42 = B2 ^((~B3)& B4 ); |
| 921 | A13 = B3 ^((~B4)& B0 ); |
| 922 | A34 = B4 ^((~B0)& B1 ); |
| 923 | |
| 924 | B2 = ROL64((A30^D0), 3); |
| 925 | B3 = ROL64((A01^D1), 45); |
| 926 | B4 = ROL64((A22^D2), 61); |
| 927 | B0 = ROL64((A43^D3), 28); |
| 928 | B1 = ROL64((A14^D4), 20); |
| 929 | A30 = B0 ^((~B1)& B2 ); |
| 930 | A01 = B1 ^((~B2)& B3 ); |
| 931 | A22 = B2 ^((~B3)& B4 ); |
| 932 | A43 = B3 ^((~B4)& B0 ); |
| 933 | A14 = B4 ^((~B0)& B1 ); |
| 934 | |
| 935 | B4 = ROL64((A10^D0), 18); |
| 936 | B0 = ROL64((A31^D1), 1); |
| 937 | B1 = ROL64((A02^D2), 6); |
| 938 | B2 = ROL64((A23^D3), 25); |
| 939 | B3 = ROL64((A44^D4), 8); |
| 940 | A10 = B0 ^((~B1)& B2 ); |
| 941 | A31 = B1 ^((~B2)& B3 ); |
| 942 | A02 = B2 ^((~B3)& B4 ); |
| 943 | A23 = B3 ^((~B4)& B0 ); |
| 944 | A44 = B4 ^((~B0)& B1 ); |
| 945 | |
| 946 | B1 = ROL64((A40^D0), 36); |
| 947 | B2 = ROL64((A11^D1), 10); |
| 948 | B3 = ROL64((A32^D2), 15); |
| 949 | B4 = ROL64((A03^D3), 56); |
| 950 | B0 = ROL64((A24^D4), 27); |
| 951 | A40 = B0 ^((~B1)& B2 ); |
| 952 | A11 = B1 ^((~B2)& B3 ); |
| 953 | A32 = B2 ^((~B3)& B4 ); |
| 954 | A03 = B3 ^((~B4)& B0 ); |
| 955 | A24 = B4 ^((~B0)& B1 ); |
| 956 | |
| 957 | B3 = ROL64((A20^D0), 41); |
| 958 | B4 = ROL64((A41^D1), 2); |
| 959 | B0 = ROL64((A12^D2), 62); |
| 960 | B1 = ROL64((A33^D3), 55); |
| 961 | B2 = ROL64((A04^D4), 39); |
| 962 | A20 = B0 ^((~B1)& B2 ); |
| 963 | A41 = B1 ^((~B2)& B3 ); |
| 964 | A12 = B2 ^((~B3)& B4 ); |
| 965 | A33 = B3 ^((~B4)& B0 ); |
| 966 | A04 = B4 ^((~B0)& B1 ); |
| 967 | |
| 968 | C0 = A00^A30^A10^A40^A20; |
| 969 | C1 = A21^A01^A31^A11^A41; |
| 970 | C2 = A42^A22^A02^A32^A12; |
| 971 | C3 = A13^A43^A23^A03^A33; |
| 972 | C4 = A34^A14^A44^A24^A04; |
| 973 | D0 = C4^ROL64(C1, 1); |
| 974 | D1 = C0^ROL64(C2, 1); |
| 975 | D2 = C1^ROL64(C3, 1); |
| 976 | D3 = C2^ROL64(C4, 1); |
| 977 | D4 = C3^ROL64(C0, 1); |
| 978 | |
| 979 | B0 = (A00^D0); |
| 980 | B1 = ROL64((A01^D1), 44); |
| 981 | B2 = ROL64((A02^D2), 43); |
| 982 | B3 = ROL64((A03^D3), 21); |
| 983 | B4 = ROL64((A04^D4), 14); |
| 984 | A00 = B0 ^((~B1)& B2 ); |
| 985 | A00 ^= RC[i+3]; |
| 986 | A01 = B1 ^((~B2)& B3 ); |
| 987 | A02 = B2 ^((~B3)& B4 ); |
| 988 | A03 = B3 ^((~B4)& B0 ); |
| 989 | A04 = B4 ^((~B0)& B1 ); |
| 990 | |
| 991 | B2 = ROL64((A10^D0), 3); |
| 992 | B3 = ROL64((A11^D1), 45); |
| 993 | B4 = ROL64((A12^D2), 61); |
| 994 | B0 = ROL64((A13^D3), 28); |
| 995 | B1 = ROL64((A14^D4), 20); |
| 996 | A10 = B0 ^((~B1)& B2 ); |
| 997 | A11 = B1 ^((~B2)& B3 ); |
| 998 | A12 = B2 ^((~B3)& B4 ); |
| 999 | A13 = B3 ^((~B4)& B0 ); |
| 1000 | A14 = B4 ^((~B0)& B1 ); |
| 1001 | |
| 1002 | B4 = ROL64((A20^D0), 18); |
| 1003 | B0 = ROL64((A21^D1), 1); |
| 1004 | B1 = ROL64((A22^D2), 6); |
| 1005 | B2 = ROL64((A23^D3), 25); |
| 1006 | B3 = ROL64((A24^D4), 8); |
| 1007 | A20 = B0 ^((~B1)& B2 ); |
| 1008 | A21 = B1 ^((~B2)& B3 ); |
| 1009 | A22 = B2 ^((~B3)& B4 ); |
| 1010 | A23 = B3 ^((~B4)& B0 ); |
| 1011 | A24 = B4 ^((~B0)& B1 ); |
| 1012 | |
| 1013 | B1 = ROL64((A30^D0), 36); |
| 1014 | B2 = ROL64((A31^D1), 10); |
| 1015 | B3 = ROL64((A32^D2), 15); |
| 1016 | B4 = ROL64((A33^D3), 56); |
| 1017 | B0 = ROL64((A34^D4), 27); |
| 1018 | A30 = B0 ^((~B1)& B2 ); |
| 1019 | A31 = B1 ^((~B2)& B3 ); |
| 1020 | A32 = B2 ^((~B3)& B4 ); |
| 1021 | A33 = B3 ^((~B4)& B0 ); |
| 1022 | A34 = B4 ^((~B0)& B1 ); |
| 1023 | |
| 1024 | B3 = ROL64((A40^D0), 41); |
| 1025 | B4 = ROL64((A41^D1), 2); |
| 1026 | B0 = ROL64((A42^D2), 62); |
| 1027 | B1 = ROL64((A43^D3), 55); |
| 1028 | B2 = ROL64((A44^D4), 39); |
| 1029 | A40 = B0 ^((~B1)& B2 ); |
| 1030 | A41 = B1 ^((~B2)& B3 ); |
| 1031 | A42 = B2 ^((~B3)& B4 ); |
| 1032 | A43 = B3 ^((~B4)& B0 ); |
| 1033 | A44 = B4 ^((~B0)& B1 ); |
| 1034 | } |
| 1035 | } |
| 1036 | |
| 1037 | /* |
| 1038 | ** Initialize a new hash. iSize determines the size of the hash |
| 1039 | ** in bits and should be one of 224, 256, 384, or 512. Or iSize |
| 1040 | ** can be zero to use the default hash size of 256 bits. |
| 1041 | */ |
| 1042 | static void SHA3Init(SHA3Context *p, int iSize){ |
| 1043 | memset(p, 0, sizeof(*p)); |
| 1044 | if( iSize>=128 && iSize<=512 ){ |
| 1045 | p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; |
| 1046 | }else{ |
| 1047 | p->nRate = (1600 - 2*256)/8; |
| 1048 | } |
| 1049 | #if SHA3_BYTEORDER==1234 |
| 1050 | /* Known to be little-endian at compile-time. No-op */ |
| 1051 | #elif SHA3_BYTEORDER==4321 |
| 1052 | p->ixMask = 7; /* Big-endian */ |
| 1053 | #else |
| 1054 | { |
| 1055 | static unsigned int one = 1; |
| 1056 | if( 1==*(unsigned char*)&one ){ |
| 1057 | /* Little endian. No byte swapping. */ |
| 1058 | p->ixMask = 0; |
| 1059 | }else{ |
| 1060 | /* Big endian. Byte swap. */ |
| 1061 | p->ixMask = 7; |
| 1062 | } |
| 1063 | } |
| 1064 | #endif |
| 1065 | } |
| 1066 | |
| 1067 | /* |
| 1068 | ** Make consecutive calls to the SHA3Update function to add new content |
| 1069 | ** to the hash |
| 1070 | */ |
| 1071 | static void SHA3Update( |
| 1072 | SHA3Context *p, |
| 1073 | const unsigned char *aData, |
| 1074 | unsigned int nData |
| 1075 | ){ |
| 1076 | unsigned int i = 0; |
| 1077 | #if SHA3_BYTEORDER==1234 |
| 1078 | if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ |
| 1079 | for(; i+7<nData; i+=8){ |
| 1080 | p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; |
| 1081 | p->nLoaded += 8; |
| 1082 | if( p->nLoaded>=p->nRate ){ |
| 1083 | KeccakF1600Step(p); |
| 1084 | p->nLoaded = 0; |
| 1085 | } |
| 1086 | } |
| 1087 | } |
| 1088 | #endif |
| 1089 | for(; i<nData; i++){ |
| 1090 | #if SHA3_BYTEORDER==1234 |
| 1091 | p->u.x[p->nLoaded] ^= aData[i]; |
| 1092 | #elif SHA3_BYTEORDER==4321 |
| 1093 | p->u.x[p->nLoaded^0x07] ^= aData[i]; |
| 1094 | #else |
| 1095 | p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; |
| 1096 | #endif |
| 1097 | p->nLoaded++; |
| 1098 | if( p->nLoaded==p->nRate ){ |
| 1099 | KeccakF1600Step(p); |
| 1100 | p->nLoaded = 0; |
| 1101 | } |
| 1102 | } |
| 1103 | } |
| 1104 | |
| 1105 | /* |
| 1106 | ** After all content has been added, invoke SHA3Final() to compute |
| 1107 | ** the final hash. The function returns a pointer to the binary |
| 1108 | ** hash value. |
| 1109 | */ |
| 1110 | static unsigned char *SHA3Final(SHA3Context *p){ |
| 1111 | unsigned int i; |
| 1112 | if( p->nLoaded==p->nRate-1 ){ |
| 1113 | const unsigned char c1 = 0x86; |
| 1114 | SHA3Update(p, &c1, 1); |
| 1115 | }else{ |
| 1116 | const unsigned char c2 = 0x06; |
| 1117 | const unsigned char c3 = 0x80; |
| 1118 | SHA3Update(p, &c2, 1); |
| 1119 | p->nLoaded = p->nRate - 1; |
| 1120 | SHA3Update(p, &c3, 1); |
| 1121 | } |
| 1122 | for(i=0; i<p->nRate; i++){ |
| 1123 | p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; |
| 1124 | } |
| 1125 | return &p->u.x[p->nRate]; |
| 1126 | } |
| 1127 | |
| 1128 | /* |
| 1129 | ** Implementation of the sha3(X,SIZE) function. |
| 1130 | ** |
| 1131 | ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default |
| 1132 | ** size is 256. If X is a BLOB, it is hashed as is. |
| 1133 | ** For all other non-NULL types of input, X is converted into a UTF-8 string |
| 1134 | ** and the string is hashed without the trailing 0x00 terminator. The hash |
| 1135 | ** of a NULL value is NULL. |
| 1136 | */ |
| 1137 | static void sha3Func( |
| 1138 | sqlite3_context *context, |
| 1139 | int argc, |
| 1140 | sqlite3_value **argv |
| 1141 | ){ |
| 1142 | SHA3Context cx; |
| 1143 | int eType = sqlite3_value_type(argv[0]); |
| 1144 | int nByte = sqlite3_value_bytes(argv[0]); |
| 1145 | int iSize; |
| 1146 | if( argc==1 ){ |
| 1147 | iSize = 256; |
| 1148 | }else{ |
| 1149 | iSize = sqlite3_value_int(argv[1]); |
| 1150 | if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ |
| 1151 | sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " |
| 1152 | "384 512", -1); |
| 1153 | return; |
| 1154 | } |
| 1155 | } |
| 1156 | if( eType==SQLITE_NULL ) return; |
| 1157 | SHA3Init(&cx, iSize); |
| 1158 | if( eType==SQLITE_BLOB ){ |
| 1159 | SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); |
| 1160 | }else{ |
| 1161 | SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); |
| 1162 | } |
| 1163 | sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); |
| 1164 | } |
| 1165 | |
| 1166 | /* Compute a string using sqlite3_vsnprintf() with a maximum length |
| 1167 | ** of 50 bytes and add it to the hash. |
| 1168 | */ |
| 1169 | static void hash_step_vformat( |
| 1170 | SHA3Context *p, /* Add content to this context */ |
| 1171 | const char *zFormat, |
| 1172 | ... |
| 1173 | ){ |
| 1174 | va_list ap; |
| 1175 | int n; |
| 1176 | char zBuf[50]; |
| 1177 | va_start(ap, zFormat); |
| 1178 | sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); |
| 1179 | va_end(ap); |
| 1180 | n = (int)strlen(zBuf); |
| 1181 | SHA3Update(p, (unsigned char*)zBuf, n); |
| 1182 | } |
| 1183 | |
| 1184 | /* |
| 1185 | ** Implementation of the sha3_query(SQL,SIZE) function. |
| 1186 | ** |
| 1187 | ** This function compiles and runs the SQL statement(s) given in the |
| 1188 | ** argument. The results are hashed using a SIZE-bit SHA3. The default |
| 1189 | ** size is 256. |
| 1190 | ** |
| 1191 | ** The format of the byte stream that is hashed is summarized as follows: |
| 1192 | ** |
| 1193 | ** S<n>:<sql> |
| 1194 | ** R |
| 1195 | ** N |
| 1196 | ** I<int> |
| 1197 | ** F<ieee-float> |
| 1198 | ** B<size>:<bytes> |
| 1199 | ** T<size>:<text> |
| 1200 | ** |
| 1201 | ** <sql> is the original SQL text for each statement run and <n> is |
| 1202 | ** the size of that text. The SQL text is UTF-8. A single R character |
| 1203 | ** occurs before the start of each row. N means a NULL value. |
| 1204 | ** I mean an 8-byte little-endian integer <int>. F is a floating point |
| 1205 | ** number with an 8-byte little-endian IEEE floating point value <ieee-float>. |
| 1206 | ** B means blobs of <size> bytes. T means text rendered as <size> |
| 1207 | ** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII |
| 1208 | ** text integers. |
| 1209 | ** |
| 1210 | ** For each SQL statement in the X input, there is one S segment. Each |
| 1211 | ** S segment is followed by zero or more R segments, one for each row in the |
| 1212 | ** result set. After each R, there are one or more N, I, F, B, or T segments, |
| 1213 | ** one for each column in the result set. Segments are concatentated directly |
| 1214 | ** with no delimiters of any kind. |
| 1215 | */ |
| 1216 | static void sha3QueryFunc( |
| 1217 | sqlite3_context *context, |
| 1218 | int argc, |
| 1219 | sqlite3_value **argv |
| 1220 | ){ |
| 1221 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 1222 | const char *zSql = (const char*)sqlite3_value_text(argv[0]); |
| 1223 | sqlite3_stmt *pStmt = 0; |
| 1224 | int nCol; /* Number of columns in the result set */ |
| 1225 | int i; /* Loop counter */ |
| 1226 | int rc; |
| 1227 | int n; |
| 1228 | const char *z; |
| 1229 | SHA3Context cx; |
| 1230 | int iSize; |
| 1231 | |
| 1232 | if( argc==1 ){ |
| 1233 | iSize = 256; |
| 1234 | }else{ |
| 1235 | iSize = sqlite3_value_int(argv[1]); |
| 1236 | if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ |
| 1237 | sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " |
| 1238 | "384 512", -1); |
| 1239 | return; |
| 1240 | } |
| 1241 | } |
| 1242 | if( zSql==0 ) return; |
| 1243 | SHA3Init(&cx, iSize); |
| 1244 | while( zSql[0] ){ |
| 1245 | rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); |
| 1246 | if( rc ){ |
| 1247 | char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", |
| 1248 | zSql, sqlite3_errmsg(db)); |
| 1249 | sqlite3_finalize(pStmt); |
| 1250 | sqlite3_result_error(context, zMsg, -1); |
| 1251 | sqlite3_free(zMsg); |
| 1252 | return; |
| 1253 | } |
| 1254 | if( !sqlite3_stmt_readonly(pStmt) ){ |
| 1255 | char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); |
| 1256 | sqlite3_finalize(pStmt); |
| 1257 | sqlite3_result_error(context, zMsg, -1); |
| 1258 | sqlite3_free(zMsg); |
| 1259 | return; |
| 1260 | } |
| 1261 | nCol = sqlite3_column_count(pStmt); |
| 1262 | z = sqlite3_sql(pStmt); |
| 1263 | if( z==0 ){ |
| 1264 | sqlite3_finalize(pStmt); |
| 1265 | continue; |
| 1266 | } |
| 1267 | n = (int)strlen(z); |
| 1268 | hash_step_vformat(&cx,"S%d:",n); |
| 1269 | SHA3Update(&cx,(unsigned char*)z,n); |
| 1270 | |
| 1271 | /* Compute a hash over the result of the query */ |
| 1272 | while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 1273 | SHA3Update(&cx,(const unsigned char*)"R",1); |
| 1274 | for(i=0; i<nCol; i++){ |
| 1275 | switch( sqlite3_column_type(pStmt,i) ){ |
| 1276 | case SQLITE_NULL: { |
| 1277 | SHA3Update(&cx, (const unsigned char*)"N",1); |
| 1278 | break; |
| 1279 | } |
| 1280 | case SQLITE_INTEGER: { |
| 1281 | sqlite3_uint64 u; |
| 1282 | int j; |
| 1283 | unsigned char x[9]; |
| 1284 | sqlite3_int64 v = sqlite3_column_int64(pStmt,i); |
| 1285 | memcpy(&u, &v, 8); |
| 1286 | for(j=8; j>=1; j--){ |
| 1287 | x[j] = u & 0xff; |
| 1288 | u >>= 8; |
| 1289 | } |
| 1290 | x[0] = 'I'; |
| 1291 | SHA3Update(&cx, x, 9); |
| 1292 | break; |
| 1293 | } |
| 1294 | case SQLITE_FLOAT: { |
| 1295 | sqlite3_uint64 u; |
| 1296 | int j; |
| 1297 | unsigned char x[9]; |
| 1298 | double r = sqlite3_column_double(pStmt,i); |
| 1299 | memcpy(&u, &r, 8); |
| 1300 | for(j=8; j>=1; j--){ |
| 1301 | x[j] = u & 0xff; |
| 1302 | u >>= 8; |
| 1303 | } |
| 1304 | x[0] = 'F'; |
| 1305 | SHA3Update(&cx,x,9); |
| 1306 | break; |
| 1307 | } |
| 1308 | case SQLITE_TEXT: { |
| 1309 | int n2 = sqlite3_column_bytes(pStmt, i); |
| 1310 | const unsigned char *z2 = sqlite3_column_text(pStmt, i); |
| 1311 | hash_step_vformat(&cx,"T%d:",n2); |
| 1312 | SHA3Update(&cx, z2, n2); |
| 1313 | break; |
| 1314 | } |
| 1315 | case SQLITE_BLOB: { |
| 1316 | int n2 = sqlite3_column_bytes(pStmt, i); |
| 1317 | const unsigned char *z2 = sqlite3_column_blob(pStmt, i); |
| 1318 | hash_step_vformat(&cx,"B%d:",n2); |
| 1319 | SHA3Update(&cx, z2, n2); |
| 1320 | break; |
| 1321 | } |
| 1322 | } |
| 1323 | } |
| 1324 | } |
| 1325 | sqlite3_finalize(pStmt); |
| 1326 | } |
| 1327 | sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); |
| 1328 | } |
| 1329 | /* End of SHA3 hashing logic copy/pasted from ../ext/misc/shathree.c |
| 1330 | ********************************************************************************/ |
| 1331 | |
| 1332 | #if defined(SQLITE_ENABLE_SESSION) |
| 1333 | /* |
| 1334 | ** State information for a single open session |
| 1335 | */ |
| @@ -608,17 +1359,14 @@ | |
| 1359 | ** instance of the following structure. |
| 1360 | */ |
| 1361 | typedef struct ShellState ShellState; |
| 1362 | struct ShellState { |
| 1363 | sqlite3 *db; /* The database */ |
| 1364 | int autoExplain; /* Automatically turn on .explain mode */ |
| 1365 | int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
| 1366 | int statsOn; /* True to display memory stats before each finalize */ |
| 1367 | int scanstatsOn; /* True to display scan stats before each finalize */ |
| 1368 | int outCount; /* Revert to stdout when reaching zero */ |
| 1369 | int cnt; /* Number of records displayed so far */ |
| 1370 | FILE *out; /* Write results here */ |
| 1371 | FILE *traceOut; /* Output for sqlite3_trace() */ |
| 1372 | int nErr; /* Number of errors seen */ |
| @@ -653,13 +1401,24 @@ | |
| 1401 | }; |
| 1402 | |
| 1403 | /* |
| 1404 | ** These are the allowed shellFlgs values |
| 1405 | */ |
| 1406 | #define SHFLG_Scratch 0x00000001 /* The --scratch option is used */ |
| 1407 | #define SHFLG_Pagecache 0x00000002 /* The --pagecache option is used */ |
| 1408 | #define SHFLG_Lookaside 0x00000004 /* Lookaside memory is used */ |
| 1409 | #define SHFLG_Backslash 0x00000008 /* The --backslash option is used */ |
| 1410 | #define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */ |
| 1411 | #define SHFLG_CountChanges 0x00000020 /* .changes setting */ |
| 1412 | #define SHFLG_Echo 0x00000040 /* .echo or --echo setting */ |
| 1413 | |
| 1414 | /* |
| 1415 | ** Macros for testing and setting shellFlgs |
| 1416 | */ |
| 1417 | #define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0) |
| 1418 | #define ShellSetFlag(P,X) ((P)->shellFlgs|=(X)) |
| 1419 | #define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X))) |
| 1420 | |
| 1421 | /* |
| 1422 | ** These are the allowed modes. |
| 1423 | */ |
| 1424 | #define MODE_Line 0 /* One column per line. Blank line between records */ |
| @@ -1292,92 +2051,106 @@ | |
| 2051 | */ |
| 2052 | static int callback(void *pArg, int nArg, char **azArg, char **azCol){ |
| 2053 | /* since we don't have type info, call the shell_callback with a NULL value */ |
| 2054 | return shell_callback(pArg, nArg, azArg, azCol, NULL); |
| 2055 | } |
| 2056 | |
| 2057 | /* |
| 2058 | ** This is the callback routine from sqlite3_exec() that appends all |
| 2059 | ** output onto the end of a ShellText object. |
| 2060 | */ |
| 2061 | static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){ |
| 2062 | ShellText *p = (ShellText*)pArg; |
| 2063 | int i; |
| 2064 | if( p->n ) appendText(p, "|", 0); |
| 2065 | for(i=0; i<nArg; i++){ |
| 2066 | if( i ) appendText(p, ",", 0); |
| 2067 | if( azArg[i] ) appendText(p, azArg[i], 0); |
| 2068 | } |
| 2069 | return 0; |
| 2070 | } |
| 2071 | |
| 2072 | /* |
| 2073 | ** Generate an appropriate SELFTEST table in the main database. |
| 2074 | */ |
| 2075 | static void createSelftestTable(ShellState *p){ |
| 2076 | char *zErrMsg = 0; |
| 2077 | sqlite3_exec(p->db, |
| 2078 | "SAVEPOINT selftest_init;\n" |
| 2079 | "CREATE TABLE IF NOT EXISTS selftest(\n" |
| 2080 | " tno INTEGER PRIMARY KEY,\n" /* Test number */ |
| 2081 | " op TEXT,\n" /* Operator: memo run */ |
| 2082 | " cmd TEXT,\n" /* Command text */ |
| 2083 | " ans TEXT\n" /* Desired answer */ |
| 2084 | ");" |
| 2085 | "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n" |
| 2086 | "INSERT INTO [_shell$self](rowid,op,cmd)\n" |
| 2087 | " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n" |
| 2088 | " 'memo','Tests generated by --init');\n" |
| 2089 | "INSERT INTO [_shell$self]\n" |
| 2090 | " SELECT 'run',\n" |
| 2091 | " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql " |
| 2092 | "FROM sqlite_master ORDER BY 2'',224))',\n" |
| 2093 | " hex(sha3_query('SELECT type,name,tbl_name,sql " |
| 2094 | "FROM sqlite_master ORDER BY 2',224));\n" |
| 2095 | "INSERT INTO [_shell$self]\n" |
| 2096 | " SELECT 'run'," |
| 2097 | " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||" |
| 2098 | " printf('%w',name) || '\" NOT INDEXED'',224))',\n" |
| 2099 | " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n" |
| 2100 | " FROM (\n" |
| 2101 | " SELECT name FROM sqlite_master\n" |
| 2102 | " WHERE type='table'\n" |
| 2103 | " AND name<>'selftest'\n" |
| 2104 | " AND coalesce(rootpage,0)>0\n" |
| 2105 | " )\n" |
| 2106 | " ORDER BY name;\n" |
| 2107 | "INSERT INTO [_shell$self]\n" |
| 2108 | " VALUES('run','PRAGMA integrity_check','ok');\n" |
| 2109 | "INSERT INTO selftest(tno,op,cmd,ans)" |
| 2110 | " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" |
| 2111 | "DROP TABLE [_shell$self];" |
| 2112 | ,0,0,&zErrMsg); |
| 2113 | if( zErrMsg ){ |
| 2114 | utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); |
| 2115 | sqlite3_free(zErrMsg); |
| 2116 | } |
| 2117 | sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); |
| 2118 | } |
| 2119 | |
| 2120 | |
| 2121 | /* |
| 2122 | ** Set the destination table field of the ShellState structure to |
| 2123 | ** the name of the table given. Escape any quote characters in the |
| 2124 | ** table name. |
| 2125 | */ |
| 2126 | static void set_table_name(ShellState *p, const char *zName){ |
| 2127 | int i, n; |
| 2128 | int cQuote; |
| 2129 | char *z; |
| 2130 | |
| 2131 | if( p->zDestTable ){ |
| 2132 | free(p->zDestTable); |
| 2133 | p->zDestTable = 0; |
| 2134 | } |
| 2135 | if( zName==0 ) return; |
| 2136 | cQuote = quoteChar(zName); |
| 2137 | n = strlen30(zName); |
| 2138 | if( cQuote ) n += 2; |
| 2139 | z = p->zDestTable = malloc( n+1 ); |
| 2140 | if( z==0 ){ |
| 2141 | raw_printf(stderr,"Error: out of memory\n"); |
| 2142 | exit(1); |
| 2143 | } |
| 2144 | n = 0; |
| 2145 | if( cQuote ) z[n++] = cQuote; |
| 2146 | for(i=0; zName[i]; i++){ |
| 2147 | z[n++] = zName[i]; |
| 2148 | if( zName[i]==cQuote ) z[n++] = cQuote; |
| 2149 | } |
| 2150 | if( cQuote ) z[n++] = cQuote; |
| 2151 | z[n] = 0; |
| 2152 | } |
| 2153 | |
| 2154 | |
| 2155 | /* |
| 2156 | ** Execute a query statement that will generate SQL output. Print |
| @@ -1484,10 +2257,35 @@ | |
| 2257 | } |
| 2258 | fclose(in); |
| 2259 | } |
| 2260 | #endif |
| 2261 | |
| 2262 | /* |
| 2263 | ** Display a single line of status using 64-bit values. |
| 2264 | */ |
| 2265 | static void displayStatLine( |
| 2266 | ShellState *p, /* The shell context */ |
| 2267 | char *zLabel, /* Label for this one line */ |
| 2268 | char *zFormat, /* Format for the result */ |
| 2269 | int iStatusCtrl, /* Which status to display */ |
| 2270 | int bReset /* True to reset the stats */ |
| 2271 | ){ |
| 2272 | sqlite3_int64 iCur = -1; |
| 2273 | sqlite3_int64 iHiwtr = -1; |
| 2274 | int i, nPercent; |
| 2275 | char zLine[200]; |
| 2276 | sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset); |
| 2277 | for(i=0, nPercent=0; zFormat[i]; i++){ |
| 2278 | if( zFormat[i]=='%' ) nPercent++; |
| 2279 | } |
| 2280 | if( nPercent>1 ){ |
| 2281 | sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr); |
| 2282 | }else{ |
| 2283 | sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr); |
| 2284 | } |
| 2285 | raw_printf(p->out, "%-36s %s\n", zLabel, zLine); |
| 2286 | } |
| 2287 | |
| 2288 | /* |
| 2289 | ** Display memory stats. |
| 2290 | */ |
| 2291 | static int display_stats( |
| @@ -1497,61 +2295,35 @@ | |
| 2295 | ){ |
| 2296 | int iCur; |
| 2297 | int iHiwtr; |
| 2298 | |
| 2299 | if( pArg && pArg->out ){ |
| 2300 | displayStatLine(pArg, "Memory Used:", |
| 2301 | "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); |
| 2302 | displayStatLine(pArg, "Number of Outstanding Allocations:", |
| 2303 | "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); |
| 2304 | if( pArg->shellFlgs & SHFLG_Pagecache ){ |
| 2305 | displayStatLine(pArg, "Number of Pcache Pages Used:", |
| 2306 | "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); |
| 2307 | } |
| 2308 | displayStatLine(pArg, "Number of Pcache Overflow Bytes:", |
| 2309 | "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); |
| 2310 | if( pArg->shellFlgs & SHFLG_Scratch ){ |
| 2311 | displayStatLine(pArg, "Number of Scratch Allocations Used:", |
| 2312 | "%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset); |
| 2313 | } |
| 2314 | displayStatLine(pArg, "Number of Scratch Overflow Bytes:", |
| 2315 | "%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset); |
| 2316 | displayStatLine(pArg, "Largest Allocation:", |
| 2317 | "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); |
| 2318 | displayStatLine(pArg, "Largest Pcache Allocation:", |
| 2319 | "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); |
| 2320 | displayStatLine(pArg, "Largest Scratch Allocation:", |
| 2321 | "%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset); |
| 2322 | #ifdef YYTRACKMAXSTACKDEPTH |
| 2323 | displayStatLine(pArg, "Deepest Parser Stack:", |
| 2324 | "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); |
| 2325 | #endif |
| 2326 | } |
| 2327 | |
| 2328 | if( pArg && pArg->out && db ){ |
| 2329 | if( pArg->shellFlgs & SHFLG_Lookaside ){ |
| @@ -1934,11 +2706,11 @@ | |
| 2706 | pArg->pStmt = pStmt; |
| 2707 | pArg->cnt = 0; |
| 2708 | } |
| 2709 | |
| 2710 | /* echo the sql statement if echo on */ |
| 2711 | if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){ |
| 2712 | utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); |
| 2713 | } |
| 2714 | |
| 2715 | /* Show the EXPLAIN QUERY PLAN if .eqp is on */ |
| 2716 | if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){ |
| @@ -2022,10 +2794,142 @@ | |
| 2794 | } /* end while */ |
| 2795 | |
| 2796 | return rc; |
| 2797 | } |
| 2798 | |
| 2799 | /* |
| 2800 | ** Release memory previously allocated by tableColumnList(). |
| 2801 | */ |
| 2802 | static void freeColumnList(char **azCol){ |
| 2803 | int i; |
| 2804 | for(i=1; azCol[i]; i++){ |
| 2805 | sqlite3_free(azCol[i]); |
| 2806 | } |
| 2807 | /* azCol[0] is a static string */ |
| 2808 | sqlite3_free(azCol); |
| 2809 | } |
| 2810 | |
| 2811 | /* |
| 2812 | ** Return a list of pointers to strings which are the names of all |
| 2813 | ** columns in table zTab. The memory to hold the names is dynamically |
| 2814 | ** allocated and must be released by the caller using a subsequent call |
| 2815 | ** to freeColumnList(). |
| 2816 | ** |
| 2817 | ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid |
| 2818 | ** value that needs to be preserved, then azCol[0] is filled in with the |
| 2819 | ** name of the rowid column. |
| 2820 | ** |
| 2821 | ** The first regular column in the table is azCol[1]. The list is terminated |
| 2822 | ** by an entry with azCol[i]==0. |
| 2823 | */ |
| 2824 | static char **tableColumnList(ShellState *p, const char *zTab){ |
| 2825 | char **azCol = 0; |
| 2826 | sqlite3_stmt *pStmt; |
| 2827 | char *zSql; |
| 2828 | int nCol = 0; |
| 2829 | int nAlloc = 0; |
| 2830 | int nPK = 0; /* Number of PRIMARY KEY columns seen */ |
| 2831 | int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */ |
| 2832 | int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid); |
| 2833 | int rc; |
| 2834 | |
| 2835 | zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); |
| 2836 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 2837 | sqlite3_free(zSql); |
| 2838 | if( rc ) return 0; |
| 2839 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 2840 | if( nCol>=nAlloc-2 ){ |
| 2841 | nAlloc = nAlloc*2 + nCol + 10; |
| 2842 | azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); |
| 2843 | if( azCol==0 ){ |
| 2844 | raw_printf(stderr, "Error: out of memory\n"); |
| 2845 | exit(1); |
| 2846 | } |
| 2847 | } |
| 2848 | azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); |
| 2849 | if( sqlite3_column_int(pStmt, 5) ){ |
| 2850 | nPK++; |
| 2851 | if( nPK==1 |
| 2852 | && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), |
| 2853 | "INTEGER")==0 |
| 2854 | ){ |
| 2855 | isIPK = 1; |
| 2856 | }else{ |
| 2857 | isIPK = 0; |
| 2858 | } |
| 2859 | } |
| 2860 | } |
| 2861 | sqlite3_finalize(pStmt); |
| 2862 | azCol[0] = 0; |
| 2863 | azCol[nCol+1] = 0; |
| 2864 | |
| 2865 | /* The decision of whether or not a rowid really needs to be preserved |
| 2866 | ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table |
| 2867 | ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve |
| 2868 | ** rowids on tables where the rowid is inaccessible because there are other |
| 2869 | ** columns in the table named "rowid", "_rowid_", and "oid". |
| 2870 | */ |
| 2871 | if( preserveRowid && isIPK ){ |
| 2872 | /* If a single PRIMARY KEY column with type INTEGER was seen, then it |
| 2873 | ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID |
| 2874 | ** table or a INTEGER PRIMARY KEY DESC column, neither of which are |
| 2875 | ** ROWID aliases. To distinguish these cases, check to see if |
| 2876 | ** there is a "pk" entry in "PRAGMA index_list". There will be |
| 2877 | ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID. |
| 2878 | */ |
| 2879 | zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)" |
| 2880 | " WHERE origin='pk'", zTab); |
| 2881 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 2882 | sqlite3_free(zSql); |
| 2883 | if( rc ){ |
| 2884 | freeColumnList(azCol); |
| 2885 | return 0; |
| 2886 | } |
| 2887 | rc = sqlite3_step(pStmt); |
| 2888 | sqlite3_finalize(pStmt); |
| 2889 | preserveRowid = rc==SQLITE_ROW; |
| 2890 | } |
| 2891 | if( preserveRowid ){ |
| 2892 | /* Only preserve the rowid if we can find a name to use for the |
| 2893 | ** rowid */ |
| 2894 | static char *azRowid[] = { "rowid", "_rowid_", "oid" }; |
| 2895 | int i, j; |
| 2896 | for(j=0; j<3; j++){ |
| 2897 | for(i=1; i<=nCol; i++){ |
| 2898 | if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break; |
| 2899 | } |
| 2900 | if( i>nCol ){ |
| 2901 | /* At this point, we know that azRowid[j] is not the name of any |
| 2902 | ** ordinary column in the table. Verify that azRowid[j] is a valid |
| 2903 | ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID |
| 2904 | ** tables will fail this last check */ |
| 2905 | int rc; |
| 2906 | rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0); |
| 2907 | if( rc==SQLITE_OK ) azCol[0] = azRowid[j]; |
| 2908 | break; |
| 2909 | } |
| 2910 | } |
| 2911 | } |
| 2912 | return azCol; |
| 2913 | } |
| 2914 | |
| 2915 | /* |
| 2916 | ** Toggle the reverse_unordered_selects setting. |
| 2917 | */ |
| 2918 | static void toggleSelectOrder(sqlite3 *db){ |
| 2919 | sqlite3_stmt *pStmt = 0; |
| 2920 | int iSetting = 0; |
| 2921 | char zStmt[100]; |
| 2922 | sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0); |
| 2923 | if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 2924 | iSetting = sqlite3_column_int(pStmt, 0); |
| 2925 | } |
| 2926 | sqlite3_finalize(pStmt); |
| 2927 | sqlite3_snprintf(sizeof(zStmt), zStmt, |
| 2928 | "PRAGMA reverse_unordered_selects(%d)", !iSetting); |
| 2929 | sqlite3_exec(db, zStmt, 0, 0, 0); |
| 2930 | } |
| 2931 | |
| 2932 | /* |
| 2933 | ** This is a different callback routine used for dumping the database. |
| 2934 | ** Each row received by this callback consists of a table name, |
| 2935 | ** the table type ("index" or "table") and SQL to create the table. |
| @@ -2034,21 +2938,20 @@ | |
| 2938 | static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ |
| 2939 | int rc; |
| 2940 | const char *zTable; |
| 2941 | const char *zType; |
| 2942 | const char *zSql; |
| 2943 | ShellState *p = (ShellState *)pArg; |
| 2944 | |
| 2945 | UNUSED_PARAMETER(azCol); |
| 2946 | if( nArg!=3 ) return 1; |
| 2947 | zTable = azArg[0]; |
| 2948 | zType = azArg[1]; |
| 2949 | zSql = azArg[2]; |
| 2950 | |
| 2951 | if( strcmp(zTable, "sqlite_sequence")==0 ){ |
| 2952 | raw_printf(p->out, "DELETE FROM sqlite_sequence;\n"); |
| 2953 | }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ |
| 2954 | raw_printf(p->out, "ANALYZE sqlite_master;\n"); |
| 2955 | }else if( strncmp(zTable, "sqlite_", 7)==0 ){ |
| 2956 | return 0; |
| 2957 | }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ |
| @@ -2067,62 +2970,74 @@ | |
| 2970 | }else{ |
| 2971 | printSchemaLine(p->out, zSql, ";\n"); |
| 2972 | } |
| 2973 | |
| 2974 | if( strcmp(zType, "table")==0 ){ |
| 2975 | ShellText sSelect; |
| 2976 | ShellText sTable; |
| 2977 | char **azCol; |
| 2978 | int i; |
| 2979 | char *savedDestTable; |
| 2980 | int savedMode; |
| 2981 | |
| 2982 | azCol = tableColumnList(p, zTable); |
| 2983 | if( azCol==0 ){ |
| 2984 | p->nErr++; |
| 2985 | return 0; |
| 2986 | } |
| 2987 | |
| 2988 | /* Always quote the table name, even if it appears to be pure ascii, |
| 2989 | ** in case it is a keyword. Ex: INSERT INTO "table" ... */ |
| 2990 | initText(&sTable); |
| 2991 | appendText(&sTable, zTable, quoteChar(zTable)); |
| 2992 | /* If preserving the rowid, add a column list after the table name. |
| 2993 | ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)" |
| 2994 | ** instead of the usual "INSERT INTO tab VALUES(...)". |
| 2995 | */ |
| 2996 | if( azCol[0] ){ |
| 2997 | appendText(&sTable, "(", 0); |
| 2998 | appendText(&sTable, azCol[0], 0); |
| 2999 | for(i=1; azCol[i]; i++){ |
| 3000 | appendText(&sTable, ",", 0); |
| 3001 | appendText(&sTable, azCol[i], quoteChar(azCol[i])); |
| 3002 | } |
| 3003 | appendText(&sTable, ")", 0); |
| 3004 | } |
| 3005 | |
| 3006 | /* Build an appropriate SELECT statement */ |
| 3007 | initText(&sSelect); |
| 3008 | appendText(&sSelect, "SELECT ", 0); |
| 3009 | if( azCol[0] ){ |
| 3010 | appendText(&sSelect, azCol[0], 0); |
| 3011 | appendText(&sSelect, ",", 0); |
| 3012 | } |
| 3013 | for(i=1; azCol[i]; i++){ |
| 3014 | appendText(&sSelect, azCol[i], quoteChar(azCol[i])); |
| 3015 | if( azCol[i+1] ){ |
| 3016 | appendText(&sSelect, ",", 0); |
| 3017 | } |
| 3018 | } |
| 3019 | freeColumnList(azCol); |
| 3020 | appendText(&sSelect, " FROM ", 0); |
| 3021 | appendText(&sSelect, zTable, quoteChar(zTable)); |
| 3022 | |
| 3023 | savedDestTable = p->zDestTable; |
| 3024 | savedMode = p->mode; |
| 3025 | p->zDestTable = sTable.z; |
| 3026 | p->mode = p->cMode = MODE_Insert; |
| 3027 | rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0); |
| 3028 | if( (rc&0xff)==SQLITE_CORRUPT ){ |
| 3029 | raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); |
| 3030 | toggleSelectOrder(p->db); |
| 3031 | shell_exec(p->db, sSelect.z, shell_callback, p, 0); |
| 3032 | toggleSelectOrder(p->db); |
| 3033 | } |
| 3034 | p->zDestTable = savedDestTable; |
| 3035 | p->mode = savedMode; |
| 3036 | freeText(&sTable); |
| 3037 | freeText(&sSelect); |
| 3038 | if( rc ) p->nErr++; |
| 3039 | } |
| 3040 | return 0; |
| 3041 | } |
| 3042 | |
| 3043 | /* |
| @@ -2210,11 +3125,11 @@ | |
| 3125 | " csv Comma-separated values\n" |
| 3126 | " column Left-aligned columns. (See .width)\n" |
| 3127 | " html HTML <table> code\n" |
| 3128 | " insert SQL insert statements for TABLE\n" |
| 3129 | " line One value per line\n" |
| 3130 | " list Values delimited by \"|\"\n" |
| 3131 | " quote Escape answers as for SQL\n" |
| 3132 | " tabs Tab-separated values\n" |
| 3133 | " tcl TCL list elements\n" |
| 3134 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 3135 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| @@ -2233,10 +3148,11 @@ | |
| 3148 | ".separator COL ?ROW? Change the column separator and optionally the row\n" |
| 3149 | " separator for both the output mode and .import\n" |
| 3150 | #if defined(SQLITE_ENABLE_SESSION) |
| 3151 | ".session CMD ... Create or control sessions\n" |
| 3152 | #endif |
| 3153 | ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n" |
| 3154 | ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" |
| 3155 | ".show Show the current values for various settings\n" |
| 3156 | ".stats ?on|off? Show stats or turn stats on or off\n" |
| 3157 | ".system CMD ARGS... Run CMD ARGS... in a system shell\n" |
| 3158 | ".tables ?TABLE? List names of tables\n" |
| @@ -2423,14 +3339,10 @@ | |
| 3339 | static void open_db(ShellState *p, int keepAlive){ |
| 3340 | if( p->db==0 ){ |
| 3341 | sqlite3_initialize(); |
| 3342 | sqlite3_open(p->zDbFilename, &p->db); |
| 3343 | globalDb = p->db; |
| 3344 | if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ |
| 3345 | utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", |
| 3346 | p->zDbFilename, sqlite3_errmsg(p->db)); |
| 3347 | if( keepAlive ) return; |
| 3348 | exit(1); |
| @@ -2440,10 +3352,18 @@ | |
| 3352 | #endif |
| 3353 | sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0, |
| 3354 | readfileFunc, 0, 0); |
| 3355 | sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0, |
| 3356 | writefileFunc, 0, 0); |
| 3357 | sqlite3_create_function(p->db, "sha3", 1, SQLITE_UTF8, 0, |
| 3358 | sha3Func, 0, 0); |
| 3359 | sqlite3_create_function(p->db, "sha3", 2, SQLITE_UTF8, 0, |
| 3360 | sha3Func, 0, 0); |
| 3361 | sqlite3_create_function(p->db, "sha3_query", 1, SQLITE_UTF8, 0, |
| 3362 | sha3QueryFunc, 0, 0); |
| 3363 | sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0, |
| 3364 | sha3QueryFunc, 0, 0); |
| 3365 | } |
| 3366 | } |
| 3367 | |
| 3368 | /* |
| 3369 | ** Do C-language style dequoting. |
| @@ -2564,11 +3484,11 @@ | |
| 3484 | |
| 3485 | /* |
| 3486 | ** Interpret zArg as either an integer or a boolean value. Return 1 or 0 |
| 3487 | ** for TRUE and FALSE. Return the integer value if appropriate. |
| 3488 | */ |
| 3489 | static int booleanValue(const char *zArg){ |
| 3490 | int i; |
| 3491 | if( zArg[0]=='0' && zArg[1]=='x' ){ |
| 3492 | for(i=2; hexDigitValue(zArg[i])>=0; i++){} |
| 3493 | }else{ |
| 3494 | for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} |
| @@ -2582,10 +3502,21 @@ | |
| 3502 | } |
| 3503 | utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", |
| 3504 | zArg); |
| 3505 | return 0; |
| 3506 | } |
| 3507 | |
| 3508 | /* |
| 3509 | ** Set or clear a shell flag according to a boolean value. |
| 3510 | */ |
| 3511 | static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){ |
| 3512 | if( booleanValue(zArg) ){ |
| 3513 | ShellSetFlag(p, mFlag); |
| 3514 | }else{ |
| 3515 | ShellClearFlag(p, mFlag); |
| 3516 | } |
| 3517 | } |
| 3518 | |
| 3519 | /* |
| 3520 | ** Close an output file, assuming it is not stderr or stdout |
| 3521 | */ |
| 3522 | static void output_file_close(FILE *f){ |
| @@ -3656,11 +4587,11 @@ | |
| 4587 | test_breakpoint(); |
| 4588 | }else |
| 4589 | |
| 4590 | if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ |
| 4591 | if( nArg==2 ){ |
| 4592 | setOrClearFlag(p, SHFLG_CountChanges, azArg[1]); |
| 4593 | }else{ |
| 4594 | raw_printf(stderr, "Usage: .changes on|off\n"); |
| 4595 | rc = 1; |
| 4596 | } |
| 4597 | }else |
| @@ -3720,25 +4651,46 @@ | |
| 4651 | if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ |
| 4652 | rc = shell_dbinfo_command(p, nArg, azArg); |
| 4653 | }else |
| 4654 | |
| 4655 | if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ |
| 4656 | const char *zLike = 0; |
| 4657 | int i; |
| 4658 | ShellClearFlag(p, SHFLG_PreserveRowid); |
| 4659 | for(i=1; i<nArg; i++){ |
| 4660 | if( azArg[i][0]=='-' ){ |
| 4661 | const char *z = azArg[i]+1; |
| 4662 | if( z[0]=='-' ) z++; |
| 4663 | if( strcmp(z,"preserve-rowids")==0 ){ |
| 4664 | ShellSetFlag(p, SHFLG_PreserveRowid); |
| 4665 | }else |
| 4666 | { |
| 4667 | raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]); |
| 4668 | rc = 1; |
| 4669 | goto meta_command_exit; |
| 4670 | } |
| 4671 | }else if( zLike ){ |
| 4672 | raw_printf(stderr, "Usage: .dump ?--preserve-rowids? ?LIKE-PATTERN?\n"); |
| 4673 | rc = 1; |
| 4674 | goto meta_command_exit; |
| 4675 | }else{ |
| 4676 | zLike = azArg[i]; |
| 4677 | } |
| 4678 | } |
| 4679 | open_db(p, 0); |
| 4680 | /* When playing back a "dump", the content might appear in an order |
| 4681 | ** which causes immediate foreign key constraints to be violated. |
| 4682 | ** So disable foreign-key constraint enforcement to prevent problems. */ |
| 4683 | raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); |
| 4684 | raw_printf(p->out, "BEGIN TRANSACTION;\n"); |
| 4685 | p->writableSchema = 0; |
| 4686 | /* Set writable_schema=ON since doing so forces SQLite to initialize |
| 4687 | ** as much of the schema as it can even if the sqlite_master table is |
| 4688 | ** corrupt. */ |
| 4689 | sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); |
| 4690 | p->nErr = 0; |
| 4691 | if( zLike==0 ){ |
| 4692 | run_schema_dump_query(p, |
| 4693 | "SELECT name, type, sql FROM sqlite_master " |
| 4694 | "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" |
| 4695 | ); |
| 4696 | run_schema_dump_query(p, |
| @@ -3748,25 +4700,24 @@ | |
| 4700 | run_table_dump_query(p, |
| 4701 | "SELECT sql FROM sqlite_master " |
| 4702 | "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 |
| 4703 | ); |
| 4704 | }else{ |
| 4705 | char *zSql; |
| 4706 | zSql = sqlite3_mprintf( |
| 4707 | "SELECT name, type, sql FROM sqlite_master " |
| 4708 | "WHERE tbl_name LIKE %Q AND type=='table'" |
| 4709 | " AND sql NOT NULL", zLike); |
| 4710 | run_schema_dump_query(p,zSql); |
| 4711 | sqlite3_free(zSql); |
| 4712 | zSql = sqlite3_mprintf( |
| 4713 | "SELECT sql FROM sqlite_master " |
| 4714 | "WHERE sql NOT NULL" |
| 4715 | " AND type IN ('index','trigger','view')" |
| 4716 | " AND tbl_name LIKE %Q", zLike); |
| 4717 | run_table_dump_query(p, zSql, 0); |
| 4718 | sqlite3_free(zSql); |
| 4719 | } |
| 4720 | if( p->writableSchema ){ |
| 4721 | raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); |
| 4722 | p->writableSchema = 0; |
| 4723 | } |
| @@ -3775,11 +4726,11 @@ | |
| 4726 | raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); |
| 4727 | }else |
| 4728 | |
| 4729 | if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ |
| 4730 | if( nArg==2 ){ |
| 4731 | setOrClearFlag(p, SHFLG_Echo, azArg[1]); |
| 4732 | }else{ |
| 4733 | raw_printf(stderr, "Usage: .echo on|off\n"); |
| 4734 | rc = 1; |
| 4735 | } |
| 4736 | }else |
| @@ -4342,10 +5293,11 @@ | |
| 5293 | int newFlag = 0; /* True to delete file before opening */ |
| 5294 | /* Close the existing database */ |
| 5295 | session_close_all(p); |
| 5296 | sqlite3_close(p->db); |
| 5297 | p->db = 0; |
| 5298 | p->zDbFilename = 0; |
| 5299 | sqlite3_free(p->zFreeOnClose); |
| 5300 | p->zFreeOnClose = 0; |
| 5301 | /* Check for command-line arguments */ |
| 5302 | for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){ |
| 5303 | const char *z = azArg[iName]; |
| @@ -4571,21 +5523,21 @@ | |
| 5523 | new_colv[0] = "sql"; |
| 5524 | new_colv[1] = 0; |
| 5525 | callback(&data, 1, new_argv, new_colv); |
| 5526 | rc = SQLITE_OK; |
| 5527 | }else{ |
| 5528 | char *zSql; |
| 5529 | zSql = sqlite3_mprintf( |
| 5530 | "SELECT sql FROM " |
| 5531 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 5532 | " FROM sqlite_master UNION ALL" |
| 5533 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| 5534 | "WHERE lower(tbl_name) LIKE %Q" |
| 5535 | " AND type!='meta' AND sql NOTNULL " |
| 5536 | "ORDER BY rowid", azArg[1]); |
| 5537 | rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg); |
| 5538 | sqlite3_free(zSql); |
| 5539 | } |
| 5540 | }else if( nArg==1 ){ |
| 5541 | rc = sqlite3_exec(p->db, |
| 5542 | "SELECT sql FROM " |
| 5543 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| @@ -4612,11 +5564,11 @@ | |
| 5564 | } |
| 5565 | }else |
| 5566 | |
| 5567 | #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 5568 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ |
| 5569 | sqlite3SelectTrace = (int)integerValue(azArg[1]); |
| 5570 | }else |
| 5571 | #endif |
| 5572 | |
| 5573 | #if defined(SQLITE_ENABLE_SESSION) |
| 5574 | if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ |
| @@ -4834,10 +5786,123 @@ | |
| 5786 | utf8_printf(p->out, "%s", zBuf); |
| 5787 | } |
| 5788 | } |
| 5789 | }else |
| 5790 | #endif |
| 5791 | |
| 5792 | if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ |
| 5793 | int bIsInit = 0; /* True to initialize the SELFTEST table */ |
| 5794 | int bVerbose = 0; /* Verbose output */ |
| 5795 | int bSelftestExists; /* True if SELFTEST already exists */ |
| 5796 | char **azTest = 0; /* Content of the SELFTEST table */ |
| 5797 | int nRow = 0; /* Number of rows in the SELFTEST table */ |
| 5798 | int nCol = 4; /* Number of columns in the SELFTEST table */ |
| 5799 | int i; /* Loop counter */ |
| 5800 | int nTest = 0; /* Number of tests runs */ |
| 5801 | int nErr = 0; /* Number of errors seen */ |
| 5802 | ShellText str; /* Answer for a query */ |
| 5803 | static char *azDefaultTest[] = { |
| 5804 | 0, 0, 0, 0, |
| 5805 | "0", "memo", "Missing SELFTEST table - default checks only", "", |
| 5806 | "1", "run", "PRAGMA integrity_check", "ok" |
| 5807 | }; |
| 5808 | static const int nDefaultRow = 2; |
| 5809 | |
| 5810 | open_db(p,0); |
| 5811 | for(i=1; i<nArg; i++){ |
| 5812 | const char *z = azArg[i]; |
| 5813 | if( z[0]=='-' && z[1]=='-' ) z++; |
| 5814 | if( strcmp(z,"-init")==0 ){ |
| 5815 | bIsInit = 1; |
| 5816 | }else |
| 5817 | if( strcmp(z,"-v")==0 ){ |
| 5818 | bVerbose++; |
| 5819 | }else |
| 5820 | { |
| 5821 | utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", |
| 5822 | azArg[i], azArg[0]); |
| 5823 | raw_printf(stderr, "Should be one of: --init -v\n"); |
| 5824 | rc = 1; |
| 5825 | goto meta_command_exit; |
| 5826 | } |
| 5827 | } |
| 5828 | if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0) |
| 5829 | != SQLITE_OK ){ |
| 5830 | bSelftestExists = 0; |
| 5831 | }else{ |
| 5832 | bSelftestExists = 1; |
| 5833 | } |
| 5834 | if( bIsInit ){ |
| 5835 | createSelftestTable(p); |
| 5836 | bSelftestExists = 1; |
| 5837 | } |
| 5838 | if( bSelftestExists ){ |
| 5839 | rc = sqlite3_get_table(p->db, |
| 5840 | "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", |
| 5841 | &azTest, &nRow, &nCol, 0); |
| 5842 | if( rc ){ |
| 5843 | raw_printf(stderr, "Error querying the selftest table\n"); |
| 5844 | rc = 1; |
| 5845 | sqlite3_free_table(azTest); |
| 5846 | goto meta_command_exit; |
| 5847 | }else if( nRow==0 ){ |
| 5848 | sqlite3_free_table(azTest); |
| 5849 | azTest = azDefaultTest; |
| 5850 | nRow = nDefaultRow; |
| 5851 | } |
| 5852 | }else{ |
| 5853 | azTest = azDefaultTest; |
| 5854 | nRow = nDefaultRow; |
| 5855 | } |
| 5856 | initText(&str); |
| 5857 | appendText(&str, "x", 0); |
| 5858 | for(i=1; i<=nRow; i++){ |
| 5859 | int tno = atoi(azTest[i*nCol]); |
| 5860 | const char *zOp = azTest[i*nCol+1]; |
| 5861 | const char *zSql = azTest[i*nCol+2]; |
| 5862 | const char *zAns = azTest[i*nCol+3]; |
| 5863 | |
| 5864 | if( bVerbose>0 ){ |
| 5865 | char *zQuote = sqlite3_mprintf("%q", zSql); |
| 5866 | printf("%d: %s %s\n", tno, zOp, zSql); |
| 5867 | sqlite3_free(zQuote); |
| 5868 | } |
| 5869 | if( strcmp(zOp,"memo")==0 ){ |
| 5870 | utf8_printf(p->out, "%s\n", zSql); |
| 5871 | }else |
| 5872 | if( strcmp(zOp,"run")==0 ){ |
| 5873 | char *zErrMsg = 0; |
| 5874 | str.n = 0; |
| 5875 | str.z[0] = 0; |
| 5876 | rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); |
| 5877 | nTest++; |
| 5878 | if( bVerbose ){ |
| 5879 | utf8_printf(p->out, "Result: %s\n", str.z); |
| 5880 | } |
| 5881 | if( rc || zErrMsg ){ |
| 5882 | nErr++; |
| 5883 | rc = 1; |
| 5884 | utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); |
| 5885 | sqlite3_free(zErrMsg); |
| 5886 | }else if( strcmp(zAns,str.z)!=0 ){ |
| 5887 | nErr++; |
| 5888 | rc = 1; |
| 5889 | utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); |
| 5890 | utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); |
| 5891 | } |
| 5892 | }else |
| 5893 | { |
| 5894 | utf8_printf(stderr, |
| 5895 | "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); |
| 5896 | rc = 1; |
| 5897 | break; |
| 5898 | } |
| 5899 | } |
| 5900 | freeText(&str); |
| 5901 | if( azTest!=azDefaultTest ) sqlite3_free_table(azTest); |
| 5902 | utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); |
| 5903 | }else |
| 5904 | |
| 5905 | if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ |
| 5906 | if( nArg<2 || nArg>3 ){ |
| 5907 | raw_printf(stderr, "Usage: .separator COL ?ROW?\n"); |
| 5908 | rc = 1; |
| @@ -4849,10 +5914,126 @@ | |
| 5914 | if( nArg>=3 ){ |
| 5915 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, |
| 5916 | "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); |
| 5917 | } |
| 5918 | }else |
| 5919 | |
| 5920 | if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){ |
| 5921 | const char *zLike = 0; /* Which table to checksum. 0 means everything */ |
| 5922 | int i; /* Loop counter */ |
| 5923 | int bSchema = 0; /* Also hash the schema */ |
| 5924 | int bSeparate = 0; /* Hash each table separately */ |
| 5925 | int iSize = 224; /* Hash algorithm to use */ |
| 5926 | int bDebug = 0; /* Only show the query that would have run */ |
| 5927 | sqlite3_stmt *pStmt; /* For querying tables names */ |
| 5928 | char *zSql; /* SQL to be run */ |
| 5929 | char *zSep; /* Separator */ |
| 5930 | ShellText sSql; /* Complete SQL for the query to run the hash */ |
| 5931 | ShellText sQuery; /* Set of queries used to read all content */ |
| 5932 | open_db(p, 0); |
| 5933 | for(i=1; i<nArg; i++){ |
| 5934 | const char *z = azArg[i]; |
| 5935 | if( z[0]=='-' ){ |
| 5936 | z++; |
| 5937 | if( z[0]=='-' ) z++; |
| 5938 | if( strcmp(z,"schema")==0 ){ |
| 5939 | bSchema = 1; |
| 5940 | }else |
| 5941 | if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0 |
| 5942 | || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0 |
| 5943 | ){ |
| 5944 | iSize = atoi(&z[5]); |
| 5945 | }else |
| 5946 | if( strcmp(z,"debug")==0 ){ |
| 5947 | bDebug = 1; |
| 5948 | }else |
| 5949 | { |
| 5950 | utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", |
| 5951 | azArg[i], azArg[0]); |
| 5952 | raw_printf(stderr, "Should be one of: --schema" |
| 5953 | " --sha3-224 --sha3-255 --sha3-384 --sha3-512\n"); |
| 5954 | rc = 1; |
| 5955 | goto meta_command_exit; |
| 5956 | } |
| 5957 | }else if( zLike ){ |
| 5958 | raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); |
| 5959 | rc = 1; |
| 5960 | goto meta_command_exit; |
| 5961 | }else{ |
| 5962 | zLike = z; |
| 5963 | bSeparate = 1; |
| 5964 | if( sqlite3_strlike("sqlite_%", zLike, 0)==0 ) bSchema = 1; |
| 5965 | } |
| 5966 | } |
| 5967 | if( bSchema ){ |
| 5968 | zSql = "SELECT lower(name) FROM sqlite_master" |
| 5969 | " WHERE type='table' AND coalesce(rootpage,0)>1" |
| 5970 | " UNION ALL SELECT 'sqlite_master'" |
| 5971 | " ORDER BY 1 collate nocase"; |
| 5972 | }else{ |
| 5973 | zSql = "SELECT lower(name) FROM sqlite_master" |
| 5974 | " WHERE type='table' AND coalesce(rootpage,0)>1" |
| 5975 | " AND name NOT LIKE 'sqlite_%'" |
| 5976 | " ORDER BY 1 collate nocase"; |
| 5977 | } |
| 5978 | sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 5979 | initText(&sQuery); |
| 5980 | initText(&sSql); |
| 5981 | appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0); |
| 5982 | zSep = "VALUES("; |
| 5983 | while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 5984 | const char *zTab = (const char*)sqlite3_column_text(pStmt,0); |
| 5985 | if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue; |
| 5986 | if( strncmp(zTab, "sqlite_",7)!=0 ){ |
| 5987 | appendText(&sQuery,"SELECT * FROM ", 0); |
| 5988 | appendText(&sQuery,zTab,'"'); |
| 5989 | appendText(&sQuery," NOT INDEXED;", 0); |
| 5990 | }else if( strcmp(zTab, "sqlite_master")==0 ){ |
| 5991 | appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master" |
| 5992 | " ORDER BY name;", 0); |
| 5993 | }else if( strcmp(zTab, "sqlite_sequence")==0 ){ |
| 5994 | appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence" |
| 5995 | " ORDER BY name;", 0); |
| 5996 | }else if( strcmp(zTab, "sqlite_stat1")==0 ){ |
| 5997 | appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1" |
| 5998 | " ORDER BY tbl,idx;", 0); |
| 5999 | }else if( strcmp(zTab, "sqlite_stat3")==0 |
| 6000 | || strcmp(zTab, "sqlite_stat4")==0 ){ |
| 6001 | appendText(&sQuery, "SELECT * FROM ", 0); |
| 6002 | appendText(&sQuery, zTab, 0); |
| 6003 | appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0); |
| 6004 | } |
| 6005 | appendText(&sSql, zSep, 0); |
| 6006 | appendText(&sSql, sQuery.z, '\''); |
| 6007 | sQuery.n = 0; |
| 6008 | appendText(&sSql, ",", 0); |
| 6009 | appendText(&sSql, zTab, '\''); |
| 6010 | zSep = "),("; |
| 6011 | } |
| 6012 | sqlite3_finalize(pStmt); |
| 6013 | if( bSeparate ){ |
| 6014 | zSql = sqlite3_mprintf( |
| 6015 | "%s))" |
| 6016 | " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label" |
| 6017 | " FROM [sha3sum$query]", |
| 6018 | sSql.z, iSize); |
| 6019 | }else{ |
| 6020 | zSql = sqlite3_mprintf( |
| 6021 | "%s))" |
| 6022 | " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash" |
| 6023 | " FROM [sha3sum$query]", |
| 6024 | sSql.z, iSize); |
| 6025 | } |
| 6026 | freeText(&sQuery); |
| 6027 | freeText(&sSql); |
| 6028 | if( bDebug ){ |
| 6029 | utf8_printf(p->out, "%s\n", zSql); |
| 6030 | }else{ |
| 6031 | shell_exec(p->db, zSql, shell_callback, p, 0); |
| 6032 | } |
| 6033 | sqlite3_free(zSql); |
| 6034 | }else |
| 6035 | |
| 6036 | if( c=='s' |
| 6037 | && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) |
| 6038 | ){ |
| 6039 | char *zCmd; |
| @@ -4878,11 +6059,12 @@ | |
| 6059 | if( nArg!=1 ){ |
| 6060 | raw_printf(stderr, "Usage: .show\n"); |
| 6061 | rc = 1; |
| 6062 | goto meta_command_exit; |
| 6063 | } |
| 6064 | utf8_printf(p->out, "%12.12s: %s\n","echo", |
| 6065 | azBool[ShellHasFlag(p, SHFLG_Echo)]); |
| 6066 | utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); |
| 6067 | utf8_printf(p->out, "%12.12s: %s\n","explain", |
| 6068 | p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); |
| 6069 | utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); |
| 6070 | utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); |
| @@ -5190,10 +6372,11 @@ | |
| 6372 | azArg[1]); |
| 6373 | break; |
| 6374 | } |
| 6375 | } |
| 6376 | }else |
| 6377 | #endif /* !defined(SQLITE_UNTESTABLE) */ |
| 6378 | |
| 6379 | if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ |
| 6380 | open_db(p, 0); |
| 6381 | sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); |
| 6382 | }else |
| @@ -5226,11 +6409,10 @@ | |
| 6409 | }else{ |
| 6410 | sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut); |
| 6411 | } |
| 6412 | #endif |
| 6413 | }else |
| 6414 | |
| 6415 | #if SQLITE_USER_AUTHENTICATION |
| 6416 | if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ |
| 6417 | if( nArg<2 ){ |
| 6418 | raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); |
| @@ -5443,11 +6625,11 @@ | |
| 6625 | static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ |
| 6626 | int rc; |
| 6627 | char *zErrMsg = 0; |
| 6628 | |
| 6629 | open_db(p, 0); |
| 6630 | if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); |
| 6631 | BEGIN_TIMER; |
| 6632 | rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); |
| 6633 | END_TIMER; |
| 6634 | if( rc || zErrMsg ){ |
| 6635 | char zPrefix[100]; |
| @@ -5463,11 +6645,11 @@ | |
| 6645 | zErrMsg = 0; |
| 6646 | }else{ |
| 6647 | utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); |
| 6648 | } |
| 6649 | return 1; |
| 6650 | }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ |
| 6651 | raw_printf(p->out, "changes: %3d total_changes: %d\n", |
| 6652 | sqlite3_changes(p->db), sqlite3_total_changes(p->db)); |
| 6653 | } |
| 6654 | return 0; |
| 6655 | } |
| @@ -5506,15 +6688,15 @@ | |
| 6688 | if( in!=0 ) break; |
| 6689 | seenInterrupt = 0; |
| 6690 | } |
| 6691 | lineno++; |
| 6692 | if( nSql==0 && _all_whitespace(zLine) ){ |
| 6693 | if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); |
| 6694 | continue; |
| 6695 | } |
| 6696 | if( zLine && zLine[0]=='.' && nSql==0 ){ |
| 6697 | if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); |
| 6698 | rc = do_meta_command(zLine, p); |
| 6699 | if( rc==2 ){ /* exit requested */ |
| 6700 | break; |
| 6701 | }else if( rc ){ |
| 6702 | errCnt++; |
| @@ -5553,11 +6735,11 @@ | |
| 6735 | if( p->outCount ){ |
| 6736 | output_reset(p); |
| 6737 | p->outCount = 0; |
| 6738 | } |
| 6739 | }else if( nSql && _all_whitespace(zSql) ){ |
| 6740 | if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); |
| 6741 | nSql = 0; |
| 6742 | } |
| 6743 | } |
| 6744 | if( nSql && !_all_whitespace(zSql) ){ |
| 6745 | runOneSqlLine(p, zSql, in, startline); |
| @@ -6022,11 +7204,11 @@ | |
| 7204 | }else if( strcmp(z,"-header")==0 ){ |
| 7205 | data.showHeader = 1; |
| 7206 | }else if( strcmp(z,"-noheader")==0 ){ |
| 7207 | data.showHeader = 0; |
| 7208 | }else if( strcmp(z,"-echo")==0 ){ |
| 7209 | ShellSetFlag(&data, SHFLG_Echo); |
| 7210 | }else if( strcmp(z,"-eqp")==0 ){ |
| 7211 | data.autoEQP = 1; |
| 7212 | }else if( strcmp(z,"-eqpfull")==0 ){ |
| 7213 | data.autoEQP = 2; |
| 7214 | }else if( strcmp(z,"-stats")==0 ){ |
| @@ -6037,11 +7219,11 @@ | |
| 7219 | /* Undocumented command-line option: -backslash |
| 7220 | ** Causes C-style backslash escapes to be evaluated in SQL statements |
| 7221 | ** prior to sending the SQL into SQLite. Useful for injecting |
| 7222 | ** crazy bytes in the middle of SQL statements for testing and debugging. |
| 7223 | */ |
| 7224 | ShellSetFlag(&data, SHFLG_Backslash); |
| 7225 | }else if( strcmp(z,"-bail")==0 ){ |
| 7226 | bail_on_error = 1; |
| 7227 | }else if( strcmp(z,"-version")==0 ){ |
| 7228 | printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); |
| 7229 | return 0; |
| 7230 |
+14
-13
| --- src/shun.c | ||
| +++ src/shun.c | ||
| @@ -26,10 +26,11 @@ | ||
| 26 | 26 | */ |
| 27 | 27 | int uuid_is_shunned(const char *zUuid){ |
| 28 | 28 | static Stmt q; |
| 29 | 29 | int rc; |
| 30 | 30 | if( zUuid==0 || zUuid[0]==0 ) return 0; |
| 31 | + if( g.eHashPolicy==HPOLICY_SHUN_SHA1 && zUuid[HNAME_LEN_SHA1]==0 ) return 1; | |
| 31 | 32 | db_static_prepare(&q, "SELECT 1 FROM shun WHERE uuid=:uuid"); |
| 32 | 33 | db_bind_text(&q, ":uuid", zUuid); |
| 33 | 34 | rc = db_step(&q); |
| 34 | 35 | db_reset(&q); |
| 35 | 36 | return rc==SQLITE_ROW; |
| @@ -36,11 +37,11 @@ | ||
| 36 | 37 | } |
| 37 | 38 | |
| 38 | 39 | /* |
| 39 | 40 | ** WEBPAGE: shun |
| 40 | 41 | ** |
| 41 | -** View the SHA1 hashes of all shunned artifacts. Add new hashes | |
| 42 | +** View the hashes of all shunned artifacts. Add new hashes | |
| 42 | 43 | ** to the shun set. Requires Admin privilege. |
| 43 | 44 | */ |
| 44 | 45 | void shun_page(void){ |
| 45 | 46 | Stmt q; |
| 46 | 47 | int cnt = 0; |
| @@ -84,18 +85,18 @@ | ||
| 84 | 85 | } |
| 85 | 86 | zCanonical[j+1] = zCanonical[j] = 0; |
| 86 | 87 | p = zCanonical; |
| 87 | 88 | while( *p ){ |
| 88 | 89 | int nUuid = strlen(p); |
| 89 | - if( nUuid!=UUID_SIZE || !validate16(p, nUuid) ){ | |
| 90 | + if( !hname_validate(p, nUuid) ){ | |
| 90 | 91 | @ <p class="generalError">Error: Bad artifact IDs.</p> |
| 91 | 92 | fossil_free(zCanonical); |
| 92 | 93 | zCanonical = 0; |
| 93 | 94 | break; |
| 94 | 95 | }else{ |
| 95 | - canonical16(p, UUID_SIZE); | |
| 96 | - p += UUID_SIZE+1; | |
| 96 | + canonical16(p, nUuid); | |
| 97 | + p += nUuid+1; | |
| 97 | 98 | } |
| 98 | 99 | } |
| 99 | 100 | zUuid = zCanonical; |
| 100 | 101 | } |
| 101 | 102 | style_header("Shunned Artifacts"); |
| @@ -107,21 +108,21 @@ | ||
| 107 | 108 | db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p); |
| 108 | 109 | if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){ |
| 109 | 110 | allExist = 0; |
| 110 | 111 | } |
| 111 | 112 | admin_log("Unshunned %Q", p); |
| 112 | - p += UUID_SIZE+1; | |
| 113 | + p += strlen(p)+1; | |
| 113 | 114 | } |
| 114 | 115 | if( allExist ){ |
| 115 | 116 | @ <p class="noMoreShun">Artifact(s)<br /> |
| 116 | - for( p = zUuid ; *p ; p += UUID_SIZE+1 ){ | |
| 117 | + for( p = zUuid ; *p ; p += strlen(p)+1 ){ | |
| 117 | 118 | @ <a href="%R/artifact/%s(p)">%s(p)</a><br /> |
| 118 | 119 | } |
| 119 | 120 | @ are no longer being shunned.</p> |
| 120 | 121 | }else{ |
| 121 | 122 | @ <p class="noMoreShun">Artifact(s)<br /> |
| 122 | - for( p = zUuid ; *p ; p += UUID_SIZE+1 ){ | |
| 123 | + for( p = zUuid ; *p ; p += strlen(p)+1 ){ | |
| 123 | 124 | @ %s(p)<br /> |
| 124 | 125 | } |
| 125 | 126 | @ will no longer be shunned. But they may not exist in the repository. |
| 126 | 127 | @ It may be necessary to rebuild the repository using the |
| 127 | 128 | @ <b>fossil rebuild</b> command-line before the artifact content |
| @@ -146,14 +147,14 @@ | ||
| 146 | 147 | db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p); |
| 147 | 148 | db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid); |
| 148 | 149 | db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid); |
| 149 | 150 | } |
| 150 | 151 | admin_log("Shunned %Q", p); |
| 151 | - p += UUID_SIZE+1; | |
| 152 | + p += strlen(p)+1; | |
| 152 | 153 | } |
| 153 | 154 | @ <p class="shunned">Artifact(s)<br /> |
| 154 | - for( p = zUuid ; *p ; p += UUID_SIZE+1 ){ | |
| 155 | + for( p = zUuid ; *p ; p += strlen(p)+1 ){ | |
| 155 | 156 | @ <a href="%R/artifact/%s(p)">%s(p)</a><br /> |
| 156 | 157 | } |
| 157 | 158 | @ have been shunned. They will no longer be pushed. |
| 158 | 159 | @ They will be removed from the repository the next time the repository |
| 159 | 160 | @ is rebuilt using the <b>fossil rebuild</b> command-line</p> |
| @@ -167,18 +168,18 @@ | ||
| 167 | 168 | @ artifact content will be purged from the repository the next time the |
| 168 | 169 | @ repository is rebuilt. A list of shunned artifacts can be seen at the |
| 169 | 170 | @ bottom of this page.</p> |
| 170 | 171 | @ |
| 171 | 172 | @ <a name="addshun"></a> |
| 172 | - @ <p>To shun artifacts, enter their artifact IDs (the 40-character SHA1 | |
| 173 | - @ hash of the artifacts) in the | |
| 173 | + @ <p>To shun artifacts, enter their artifact hashes (the 40- or | |
| 174 | + @ 64-character lowercase hexadecimal hash of the artifact content) in the | |
| 174 | 175 | @ following box and press the "Shun" button. This will cause the artifacts |
| 175 | 176 | @ to be removed from the repository and will prevent the artifacts from being |
| 176 | 177 | @ readded to the repository by subsequent sync operation.</p> |
| 177 | 178 | @ |
| 178 | - @ <p>Note that you must enter the full 40-character artifact IDs, not | |
| 179 | - @ an abbreviation or a symbolic tag.</p> | |
| 179 | + @ <p>Note that you must enter the full 40- or 64-character artifact hashes, | |
| 180 | + @ not an abbreviation or a symbolic tag.</p> | |
| 180 | 181 | @ |
| 181 | 182 | @ <p>Warning: Shunning should only be used to remove inappropriate content |
| 182 | 183 | @ from the repository. Inappropriate content includes such things as |
| 183 | 184 | @ spam added to Wiki, files that violate copyright or patent agreements, |
| 184 | 185 | @ or artifacts that by design or accident interfere with the processing |
| 185 | 186 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -26,10 +26,11 @@ | |
| 26 | */ |
| 27 | int uuid_is_shunned(const char *zUuid){ |
| 28 | static Stmt q; |
| 29 | int rc; |
| 30 | if( zUuid==0 || zUuid[0]==0 ) return 0; |
| 31 | db_static_prepare(&q, "SELECT 1 FROM shun WHERE uuid=:uuid"); |
| 32 | db_bind_text(&q, ":uuid", zUuid); |
| 33 | rc = db_step(&q); |
| 34 | db_reset(&q); |
| 35 | return rc==SQLITE_ROW; |
| @@ -36,11 +37,11 @@ | |
| 36 | } |
| 37 | |
| 38 | /* |
| 39 | ** WEBPAGE: shun |
| 40 | ** |
| 41 | ** View the SHA1 hashes of all shunned artifacts. Add new hashes |
| 42 | ** to the shun set. Requires Admin privilege. |
| 43 | */ |
| 44 | void shun_page(void){ |
| 45 | Stmt q; |
| 46 | int cnt = 0; |
| @@ -84,18 +85,18 @@ | |
| 84 | } |
| 85 | zCanonical[j+1] = zCanonical[j] = 0; |
| 86 | p = zCanonical; |
| 87 | while( *p ){ |
| 88 | int nUuid = strlen(p); |
| 89 | if( nUuid!=UUID_SIZE || !validate16(p, nUuid) ){ |
| 90 | @ <p class="generalError">Error: Bad artifact IDs.</p> |
| 91 | fossil_free(zCanonical); |
| 92 | zCanonical = 0; |
| 93 | break; |
| 94 | }else{ |
| 95 | canonical16(p, UUID_SIZE); |
| 96 | p += UUID_SIZE+1; |
| 97 | } |
| 98 | } |
| 99 | zUuid = zCanonical; |
| 100 | } |
| 101 | style_header("Shunned Artifacts"); |
| @@ -107,21 +108,21 @@ | |
| 107 | db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p); |
| 108 | if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){ |
| 109 | allExist = 0; |
| 110 | } |
| 111 | admin_log("Unshunned %Q", p); |
| 112 | p += UUID_SIZE+1; |
| 113 | } |
| 114 | if( allExist ){ |
| 115 | @ <p class="noMoreShun">Artifact(s)<br /> |
| 116 | for( p = zUuid ; *p ; p += UUID_SIZE+1 ){ |
| 117 | @ <a href="%R/artifact/%s(p)">%s(p)</a><br /> |
| 118 | } |
| 119 | @ are no longer being shunned.</p> |
| 120 | }else{ |
| 121 | @ <p class="noMoreShun">Artifact(s)<br /> |
| 122 | for( p = zUuid ; *p ; p += UUID_SIZE+1 ){ |
| 123 | @ %s(p)<br /> |
| 124 | } |
| 125 | @ will no longer be shunned. But they may not exist in the repository. |
| 126 | @ It may be necessary to rebuild the repository using the |
| 127 | @ <b>fossil rebuild</b> command-line before the artifact content |
| @@ -146,14 +147,14 @@ | |
| 146 | db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p); |
| 147 | db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid); |
| 148 | db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid); |
| 149 | } |
| 150 | admin_log("Shunned %Q", p); |
| 151 | p += UUID_SIZE+1; |
| 152 | } |
| 153 | @ <p class="shunned">Artifact(s)<br /> |
| 154 | for( p = zUuid ; *p ; p += UUID_SIZE+1 ){ |
| 155 | @ <a href="%R/artifact/%s(p)">%s(p)</a><br /> |
| 156 | } |
| 157 | @ have been shunned. They will no longer be pushed. |
| 158 | @ They will be removed from the repository the next time the repository |
| 159 | @ is rebuilt using the <b>fossil rebuild</b> command-line</p> |
| @@ -167,18 +168,18 @@ | |
| 167 | @ artifact content will be purged from the repository the next time the |
| 168 | @ repository is rebuilt. A list of shunned artifacts can be seen at the |
| 169 | @ bottom of this page.</p> |
| 170 | @ |
| 171 | @ <a name="addshun"></a> |
| 172 | @ <p>To shun artifacts, enter their artifact IDs (the 40-character SHA1 |
| 173 | @ hash of the artifacts) in the |
| 174 | @ following box and press the "Shun" button. This will cause the artifacts |
| 175 | @ to be removed from the repository and will prevent the artifacts from being |
| 176 | @ readded to the repository by subsequent sync operation.</p> |
| 177 | @ |
| 178 | @ <p>Note that you must enter the full 40-character artifact IDs, not |
| 179 | @ an abbreviation or a symbolic tag.</p> |
| 180 | @ |
| 181 | @ <p>Warning: Shunning should only be used to remove inappropriate content |
| 182 | @ from the repository. Inappropriate content includes such things as |
| 183 | @ spam added to Wiki, files that violate copyright or patent agreements, |
| 184 | @ or artifacts that by design or accident interfere with the processing |
| 185 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -26,10 +26,11 @@ | |
| 26 | */ |
| 27 | int uuid_is_shunned(const char *zUuid){ |
| 28 | static Stmt q; |
| 29 | int rc; |
| 30 | if( zUuid==0 || zUuid[0]==0 ) return 0; |
| 31 | if( g.eHashPolicy==HPOLICY_SHUN_SHA1 && zUuid[HNAME_LEN_SHA1]==0 ) return 1; |
| 32 | db_static_prepare(&q, "SELECT 1 FROM shun WHERE uuid=:uuid"); |
| 33 | db_bind_text(&q, ":uuid", zUuid); |
| 34 | rc = db_step(&q); |
| 35 | db_reset(&q); |
| 36 | return rc==SQLITE_ROW; |
| @@ -36,11 +37,11 @@ | |
| 37 | } |
| 38 | |
| 39 | /* |
| 40 | ** WEBPAGE: shun |
| 41 | ** |
| 42 | ** View the hashes of all shunned artifacts. Add new hashes |
| 43 | ** to the shun set. Requires Admin privilege. |
| 44 | */ |
| 45 | void shun_page(void){ |
| 46 | Stmt q; |
| 47 | int cnt = 0; |
| @@ -84,18 +85,18 @@ | |
| 85 | } |
| 86 | zCanonical[j+1] = zCanonical[j] = 0; |
| 87 | p = zCanonical; |
| 88 | while( *p ){ |
| 89 | int nUuid = strlen(p); |
| 90 | if( !hname_validate(p, nUuid) ){ |
| 91 | @ <p class="generalError">Error: Bad artifact IDs.</p> |
| 92 | fossil_free(zCanonical); |
| 93 | zCanonical = 0; |
| 94 | break; |
| 95 | }else{ |
| 96 | canonical16(p, nUuid); |
| 97 | p += nUuid+1; |
| 98 | } |
| 99 | } |
| 100 | zUuid = zCanonical; |
| 101 | } |
| 102 | style_header("Shunned Artifacts"); |
| @@ -107,21 +108,21 @@ | |
| 108 | db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p); |
| 109 | if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){ |
| 110 | allExist = 0; |
| 111 | } |
| 112 | admin_log("Unshunned %Q", p); |
| 113 | p += strlen(p)+1; |
| 114 | } |
| 115 | if( allExist ){ |
| 116 | @ <p class="noMoreShun">Artifact(s)<br /> |
| 117 | for( p = zUuid ; *p ; p += strlen(p)+1 ){ |
| 118 | @ <a href="%R/artifact/%s(p)">%s(p)</a><br /> |
| 119 | } |
| 120 | @ are no longer being shunned.</p> |
| 121 | }else{ |
| 122 | @ <p class="noMoreShun">Artifact(s)<br /> |
| 123 | for( p = zUuid ; *p ; p += strlen(p)+1 ){ |
| 124 | @ %s(p)<br /> |
| 125 | } |
| 126 | @ will no longer be shunned. But they may not exist in the repository. |
| 127 | @ It may be necessary to rebuild the repository using the |
| 128 | @ <b>fossil rebuild</b> command-line before the artifact content |
| @@ -146,14 +147,14 @@ | |
| 147 | db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p); |
| 148 | db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid); |
| 149 | db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid); |
| 150 | } |
| 151 | admin_log("Shunned %Q", p); |
| 152 | p += strlen(p)+1; |
| 153 | } |
| 154 | @ <p class="shunned">Artifact(s)<br /> |
| 155 | for( p = zUuid ; *p ; p += strlen(p)+1 ){ |
| 156 | @ <a href="%R/artifact/%s(p)">%s(p)</a><br /> |
| 157 | } |
| 158 | @ have been shunned. They will no longer be pushed. |
| 159 | @ They will be removed from the repository the next time the repository |
| 160 | @ is rebuilt using the <b>fossil rebuild</b> command-line</p> |
| @@ -167,18 +168,18 @@ | |
| 168 | @ artifact content will be purged from the repository the next time the |
| 169 | @ repository is rebuilt. A list of shunned artifacts can be seen at the |
| 170 | @ bottom of this page.</p> |
| 171 | @ |
| 172 | @ <a name="addshun"></a> |
| 173 | @ <p>To shun artifacts, enter their artifact hashes (the 40- or |
| 174 | @ 64-character lowercase hexadecimal hash of the artifact content) in the |
| 175 | @ following box and press the "Shun" button. This will cause the artifacts |
| 176 | @ to be removed from the repository and will prevent the artifacts from being |
| 177 | @ readded to the repository by subsequent sync operation.</p> |
| 178 | @ |
| 179 | @ <p>Note that you must enter the full 40- or 64-character artifact hashes, |
| 180 | @ not an abbreviation or a symbolic tag.</p> |
| 181 | @ |
| 182 | @ <p>Warning: Shunning should only be used to remove inappropriate content |
| 183 | @ from the repository. Inappropriate content includes such things as |
| 184 | @ spam added to Wiki, files that violate copyright or patent agreements, |
| 185 | @ or artifacts that by design or accident interfere with the processing |
| 186 |
+1
-2
| --- src/sitemap.c | ||
| +++ src/sitemap.c | ||
| @@ -111,12 +111,11 @@ | ||
| 111 | 111 | } |
| 112 | 112 | @ <li>%z(href("%R/login"))Login/Logout/Change Password</a></li> |
| 113 | 113 | if( g.perm.Read ){ |
| 114 | 114 | @ <li>%z(href("%R/stat"))Repository Status</a> |
| 115 | 115 | @ <ul> |
| 116 | - @ <li>%z(href("%R/hash-collisions"))Collisions on SHA1 hash | |
| 117 | - @ prefixes</a></li> | |
| 116 | + @ <li>%z(href("%R/hash-collisions"))Collisions on hash prefixes</a></li> | |
| 118 | 117 | if( g.perm.Admin ){ |
| 119 | 118 | @ <li>%z(href("%R/urllist"))List of URLs used to access |
| 120 | 119 | @ this repository</a></li> |
| 121 | 120 | } |
| 122 | 121 | @ <li>%z(href("%R/bloblist"))List of Artifacts</a></li> |
| 123 | 122 |
| --- src/sitemap.c | |
| +++ src/sitemap.c | |
| @@ -111,12 +111,11 @@ | |
| 111 | } |
| 112 | @ <li>%z(href("%R/login"))Login/Logout/Change Password</a></li> |
| 113 | if( g.perm.Read ){ |
| 114 | @ <li>%z(href("%R/stat"))Repository Status</a> |
| 115 | @ <ul> |
| 116 | @ <li>%z(href("%R/hash-collisions"))Collisions on SHA1 hash |
| 117 | @ prefixes</a></li> |
| 118 | if( g.perm.Admin ){ |
| 119 | @ <li>%z(href("%R/urllist"))List of URLs used to access |
| 120 | @ this repository</a></li> |
| 121 | } |
| 122 | @ <li>%z(href("%R/bloblist"))List of Artifacts</a></li> |
| 123 |
| --- src/sitemap.c | |
| +++ src/sitemap.c | |
| @@ -111,12 +111,11 @@ | |
| 111 | } |
| 112 | @ <li>%z(href("%R/login"))Login/Logout/Change Password</a></li> |
| 113 | if( g.perm.Read ){ |
| 114 | @ <li>%z(href("%R/stat"))Repository Status</a> |
| 115 | @ <ul> |
| 116 | @ <li>%z(href("%R/hash-collisions"))Collisions on hash prefixes</a></li> |
| 117 | if( g.perm.Admin ){ |
| 118 | @ <li>%z(href("%R/urllist"))List of URLs used to access |
| 119 | @ this repository</a></li> |
| 120 | } |
| 121 | @ <li>%z(href("%R/bloblist"))List of Artifacts</a></li> |
| 122 |
+5
-2
| --- src/sqlcmd.c | ||
| +++ src/sqlcmd.c | ||
| @@ -185,12 +185,12 @@ | ||
| 185 | 185 | ** in ways that are unrecoverable. Be sure you know what you are doing before |
| 186 | 186 | ** running any SQL commands that modify the repository database. |
| 187 | 187 | ** |
| 188 | 188 | ** The following extensions to the usual SQLite commands are provided: |
| 189 | 189 | ** |
| 190 | -** content(X) Return the content of artifact X. X can be a | |
| 191 | -** SHA1 hash or prefix or a tag. | |
| 190 | +** content(X) Return the content of artifact X. X can be an | |
| 191 | +** artifact hash or prefix or a tag. | |
| 192 | 192 | ** |
| 193 | 193 | ** compress(X) Compress text X. |
| 194 | 194 | ** |
| 195 | 195 | ** decompress(X) Decompress text X. Undoes the work of |
| 196 | 196 | ** compress(X). |
| @@ -212,10 +212,13 @@ | ||
| 212 | 212 | */ |
| 213 | 213 | void cmd_sqlite3(void){ |
| 214 | 214 | int noRepository; |
| 215 | 215 | const char *zConfigDb; |
| 216 | 216 | extern int sqlite3_shell(int, char**); |
| 217 | +#ifdef FOSSIL_ENABLE_TH1_HOOKS | |
| 218 | + g.fNoThHook = 1; | |
| 219 | +#endif | |
| 217 | 220 | noRepository = find_option("no-repository", 0, 0)!=0; |
| 218 | 221 | if( !noRepository ){ |
| 219 | 222 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 220 | 223 | } |
| 221 | 224 | db_open_config(1,0); |
| 222 | 225 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -185,12 +185,12 @@ | |
| 185 | ** in ways that are unrecoverable. Be sure you know what you are doing before |
| 186 | ** running any SQL commands that modify the repository database. |
| 187 | ** |
| 188 | ** The following extensions to the usual SQLite commands are provided: |
| 189 | ** |
| 190 | ** content(X) Return the content of artifact X. X can be a |
| 191 | ** SHA1 hash or prefix or a tag. |
| 192 | ** |
| 193 | ** compress(X) Compress text X. |
| 194 | ** |
| 195 | ** decompress(X) Decompress text X. Undoes the work of |
| 196 | ** compress(X). |
| @@ -212,10 +212,13 @@ | |
| 212 | */ |
| 213 | void cmd_sqlite3(void){ |
| 214 | int noRepository; |
| 215 | const char *zConfigDb; |
| 216 | extern int sqlite3_shell(int, char**); |
| 217 | noRepository = find_option("no-repository", 0, 0)!=0; |
| 218 | if( !noRepository ){ |
| 219 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 220 | } |
| 221 | db_open_config(1,0); |
| 222 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -185,12 +185,12 @@ | |
| 185 | ** in ways that are unrecoverable. Be sure you know what you are doing before |
| 186 | ** running any SQL commands that modify the repository database. |
| 187 | ** |
| 188 | ** The following extensions to the usual SQLite commands are provided: |
| 189 | ** |
| 190 | ** content(X) Return the content of artifact X. X can be an |
| 191 | ** artifact hash or prefix or a tag. |
| 192 | ** |
| 193 | ** compress(X) Compress text X. |
| 194 | ** |
| 195 | ** decompress(X) Decompress text X. Undoes the work of |
| 196 | ** compress(X). |
| @@ -212,10 +212,13 @@ | |
| 212 | */ |
| 213 | void cmd_sqlite3(void){ |
| 214 | int noRepository; |
| 215 | const char *zConfigDb; |
| 216 | extern int sqlite3_shell(int, char**); |
| 217 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| 218 | g.fNoThHook = 1; |
| 219 | #endif |
| 220 | noRepository = find_option("no-repository", 0, 0)!=0; |
| 221 | if( !noRepository ){ |
| 222 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 223 | } |
| 224 | db_open_config(1,0); |
| 225 |
+1515
-987
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version 3.17.0. By combining all the individual C code files into this | |
| 3 | +** version 3.18.0. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -396,13 +396,13 @@ | ||
| 396 | 396 | ** |
| 397 | 397 | ** See also: [sqlite3_libversion()], |
| 398 | 398 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 399 | 399 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 400 | 400 | */ |
| 401 | -#define SQLITE_VERSION "3.17.0" | |
| 402 | -#define SQLITE_VERSION_NUMBER 3017000 | |
| 403 | -#define SQLITE_SOURCE_ID "2017-02-13 16:02:40 ada05cfa86ad7f5645450ac7a2a21c9aa6e57d2c" | |
| 401 | +#define SQLITE_VERSION "3.18.0" | |
| 402 | +#define SQLITE_VERSION_NUMBER 3018000 | |
| 403 | +#define SQLITE_SOURCE_ID "2017-03-10 17:03:11 f8560c60d10c0365b33342ab05b5a953987b0471" | |
| 404 | 404 | |
| 405 | 405 | /* |
| 406 | 406 | ** CAPI3REF: Run-Time Library Version Numbers |
| 407 | 407 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 408 | 408 | ** |
| @@ -2315,24 +2315,34 @@ | ||
| 2315 | 2315 | ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those |
| 2316 | 2316 | ** names are not also used by explicitly declared columns. ^If |
| 2317 | 2317 | ** the table has a column of type [INTEGER PRIMARY KEY] then that column |
| 2318 | 2318 | ** is another alias for the rowid. |
| 2319 | 2319 | ** |
| 2320 | -** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the | |
| 2321 | -** most recent successful [INSERT] into a rowid table or [virtual table] | |
| 2322 | -** on database connection D. | |
| 2323 | -** ^Inserts into [WITHOUT ROWID] tables are not recorded. | |
| 2324 | -** ^If no successful [INSERT]s into rowid tables | |
| 2325 | -** have ever occurred on the database connection D, | |
| 2326 | -** then sqlite3_last_insert_rowid(D) returns zero. | |
| 2320 | +** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of | |
| 2321 | +** the most recent successful [INSERT] into a rowid table or [virtual table] | |
| 2322 | +** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not | |
| 2323 | +** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred | |
| 2324 | +** on the database connection D, then sqlite3_last_insert_rowid(D) returns | |
| 2325 | +** zero. | |
| 2327 | 2326 | ** |
| 2328 | -** ^(If an [INSERT] occurs within a trigger or within a [virtual table] | |
| 2329 | -** method, then this routine will return the [rowid] of the inserted | |
| 2330 | -** row as long as the trigger or virtual table method is running. | |
| 2331 | -** But once the trigger or virtual table method ends, the value returned | |
| 2332 | -** by this routine reverts to what it was before the trigger or virtual | |
| 2333 | -** table method began.)^ | |
| 2327 | +** As well as being set automatically as rows are inserted into database | |
| 2328 | +** tables, the value returned by this function may be set explicitly by | |
| 2329 | +** [sqlite3_set_last_insert_rowid()] | |
| 2330 | +** | |
| 2331 | +** Some virtual table implementations may INSERT rows into rowid tables as | |
| 2332 | +** part of committing a transaction (e.g. to flush data accumulated in memory | |
| 2333 | +** to disk). In this case subsequent calls to this function return the rowid | |
| 2334 | +** associated with these internal INSERT operations, which leads to | |
| 2335 | +** unintuitive results. Virtual table implementations that do write to rowid | |
| 2336 | +** tables in this way can avoid this problem by restoring the original | |
| 2337 | +** rowid value using [sqlite3_set_last_insert_rowid()] before returning | |
| 2338 | +** control to the user. | |
| 2339 | +** | |
| 2340 | +** ^(If an [INSERT] occurs within a trigger then this routine will | |
| 2341 | +** return the [rowid] of the inserted row as long as the trigger is | |
| 2342 | +** running. Once the trigger program ends, the value returned | |
| 2343 | +** by this routine reverts to what it was before the trigger was fired.)^ | |
| 2334 | 2344 | ** |
| 2335 | 2345 | ** ^An [INSERT] that fails due to a constraint violation is not a |
| 2336 | 2346 | ** successful [INSERT] and does not change the value returned by this |
| 2337 | 2347 | ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, |
| 2338 | 2348 | ** and INSERT OR ABORT make no changes to the return value of this |
| @@ -2355,10 +2365,20 @@ | ||
| 2355 | 2365 | ** unpredictable and might not equal either the old or the new |
| 2356 | 2366 | ** last insert [rowid]. |
| 2357 | 2367 | */ |
| 2358 | 2368 | SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); |
| 2359 | 2369 | |
| 2370 | +/* | |
| 2371 | +** CAPI3REF: Set the Last Insert Rowid value. | |
| 2372 | +** METHOD: sqlite3 | |
| 2373 | +** | |
| 2374 | +** The sqlite3_set_last_insert_rowid(D, R) method allows the application to | |
| 2375 | +** set the value returned by calling sqlite3_last_insert_rowid(D) to R | |
| 2376 | +** without inserting a row into the database. | |
| 2377 | +*/ | |
| 2378 | +SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); | |
| 2379 | + | |
| 2360 | 2380 | /* |
| 2361 | 2381 | ** CAPI3REF: Count The Number Of Rows Modified |
| 2362 | 2382 | ** METHOD: sqlite3 |
| 2363 | 2383 | ** |
| 2364 | 2384 | ** ^This function returns the number of rows modified, inserted or |
| @@ -12457,10 +12477,11 @@ | ||
| 12457 | 12477 | SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); |
| 12458 | 12478 | SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); |
| 12459 | 12479 | |
| 12460 | 12480 | SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); |
| 12461 | 12481 | SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); |
| 12482 | +SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*); | |
| 12462 | 12483 | |
| 12463 | 12484 | #ifndef SQLITE_OMIT_INCRBLOB |
| 12464 | 12485 | SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*); |
| 12465 | 12486 | SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); |
| 12466 | 12487 | SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); |
| @@ -12757,117 +12778,119 @@ | ||
| 12757 | 12778 | #define OP_Divide 50 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ |
| 12758 | 12779 | #define OP_Remainder 51 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ |
| 12759 | 12780 | #define OP_Concat 52 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ |
| 12760 | 12781 | #define OP_Last 53 |
| 12761 | 12782 | #define OP_BitNot 54 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ |
| 12762 | -#define OP_SorterSort 55 | |
| 12763 | -#define OP_Sort 56 | |
| 12764 | -#define OP_Rewind 57 | |
| 12765 | -#define OP_IdxLE 58 /* synopsis: key=r[P3@P4] */ | |
| 12766 | -#define OP_IdxGT 59 /* synopsis: key=r[P3@P4] */ | |
| 12767 | -#define OP_IdxLT 60 /* synopsis: key=r[P3@P4] */ | |
| 12768 | -#define OP_IdxGE 61 /* synopsis: key=r[P3@P4] */ | |
| 12769 | -#define OP_RowSetRead 62 /* synopsis: r[P3]=rowset(P1) */ | |
| 12770 | -#define OP_RowSetTest 63 /* synopsis: if r[P3] in rowset(P1) goto P2 */ | |
| 12771 | -#define OP_Program 64 | |
| 12772 | -#define OP_FkIfZero 65 /* synopsis: if fkctr[P1]==0 goto P2 */ | |
| 12773 | -#define OP_IfPos 66 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ | |
| 12774 | -#define OP_IfNotZero 67 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ | |
| 12775 | -#define OP_DecrJumpZero 68 /* synopsis: if (--r[P1])==0 goto P2 */ | |
| 12776 | -#define OP_IncrVacuum 69 | |
| 12777 | -#define OP_VNext 70 | |
| 12778 | -#define OP_Init 71 /* synopsis: Start at P2 */ | |
| 12779 | -#define OP_Return 72 | |
| 12780 | -#define OP_EndCoroutine 73 | |
| 12781 | -#define OP_HaltIfNull 74 /* synopsis: if r[P3]=null halt */ | |
| 12782 | -#define OP_Halt 75 | |
| 12783 | -#define OP_Integer 76 /* synopsis: r[P2]=P1 */ | |
| 12784 | -#define OP_Int64 77 /* synopsis: r[P2]=P4 */ | |
| 12785 | -#define OP_String 78 /* synopsis: r[P2]='P4' (len=P1) */ | |
| 12786 | -#define OP_Null 79 /* synopsis: r[P2..P3]=NULL */ | |
| 12787 | -#define OP_SoftNull 80 /* synopsis: r[P1]=NULL */ | |
| 12788 | -#define OP_Blob 81 /* synopsis: r[P2]=P4 (len=P1) */ | |
| 12789 | -#define OP_Variable 82 /* synopsis: r[P2]=parameter(P1,P4) */ | |
| 12790 | -#define OP_Move 83 /* synopsis: r[P2@P3]=r[P1@P3] */ | |
| 12791 | -#define OP_Copy 84 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ | |
| 12792 | -#define OP_SCopy 85 /* synopsis: r[P2]=r[P1] */ | |
| 12793 | -#define OP_IntCopy 86 /* synopsis: r[P2]=r[P1] */ | |
| 12794 | -#define OP_ResultRow 87 /* synopsis: output=r[P1@P2] */ | |
| 12795 | -#define OP_CollSeq 88 | |
| 12796 | -#define OP_Function0 89 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 12797 | -#define OP_Function 90 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 12798 | -#define OP_AddImm 91 /* synopsis: r[P1]=r[P1]+P2 */ | |
| 12799 | -#define OP_RealAffinity 92 | |
| 12800 | -#define OP_Cast 93 /* synopsis: affinity(r[P1]) */ | |
| 12801 | -#define OP_Permutation 94 | |
| 12802 | -#define OP_Compare 95 /* synopsis: r[P1@P3] <-> r[P2@P3] */ | |
| 12803 | -#define OP_Column 96 /* synopsis: r[P3]=PX */ | |
| 12783 | +#define OP_IfSmaller 55 | |
| 12784 | +#define OP_SorterSort 56 | |
| 12785 | +#define OP_Sort 57 | |
| 12786 | +#define OP_Rewind 58 | |
| 12787 | +#define OP_IdxLE 59 /* synopsis: key=r[P3@P4] */ | |
| 12788 | +#define OP_IdxGT 60 /* synopsis: key=r[P3@P4] */ | |
| 12789 | +#define OP_IdxLT 61 /* synopsis: key=r[P3@P4] */ | |
| 12790 | +#define OP_IdxGE 62 /* synopsis: key=r[P3@P4] */ | |
| 12791 | +#define OP_RowSetRead 63 /* synopsis: r[P3]=rowset(P1) */ | |
| 12792 | +#define OP_RowSetTest 64 /* synopsis: if r[P3] in rowset(P1) goto P2 */ | |
| 12793 | +#define OP_Program 65 | |
| 12794 | +#define OP_FkIfZero 66 /* synopsis: if fkctr[P1]==0 goto P2 */ | |
| 12795 | +#define OP_IfPos 67 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ | |
| 12796 | +#define OP_IfNotZero 68 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ | |
| 12797 | +#define OP_DecrJumpZero 69 /* synopsis: if (--r[P1])==0 goto P2 */ | |
| 12798 | +#define OP_IncrVacuum 70 | |
| 12799 | +#define OP_VNext 71 | |
| 12800 | +#define OP_Init 72 /* synopsis: Start at P2 */ | |
| 12801 | +#define OP_Return 73 | |
| 12802 | +#define OP_EndCoroutine 74 | |
| 12803 | +#define OP_HaltIfNull 75 /* synopsis: if r[P3]=null halt */ | |
| 12804 | +#define OP_Halt 76 | |
| 12805 | +#define OP_Integer 77 /* synopsis: r[P2]=P1 */ | |
| 12806 | +#define OP_Int64 78 /* synopsis: r[P2]=P4 */ | |
| 12807 | +#define OP_String 79 /* synopsis: r[P2]='P4' (len=P1) */ | |
| 12808 | +#define OP_Null 80 /* synopsis: r[P2..P3]=NULL */ | |
| 12809 | +#define OP_SoftNull 81 /* synopsis: r[P1]=NULL */ | |
| 12810 | +#define OP_Blob 82 /* synopsis: r[P2]=P4 (len=P1) */ | |
| 12811 | +#define OP_Variable 83 /* synopsis: r[P2]=parameter(P1,P4) */ | |
| 12812 | +#define OP_Move 84 /* synopsis: r[P2@P3]=r[P1@P3] */ | |
| 12813 | +#define OP_Copy 85 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ | |
| 12814 | +#define OP_SCopy 86 /* synopsis: r[P2]=r[P1] */ | |
| 12815 | +#define OP_IntCopy 87 /* synopsis: r[P2]=r[P1] */ | |
| 12816 | +#define OP_ResultRow 88 /* synopsis: output=r[P1@P2] */ | |
| 12817 | +#define OP_CollSeq 89 | |
| 12818 | +#define OP_Function0 90 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 12819 | +#define OP_Function 91 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 12820 | +#define OP_AddImm 92 /* synopsis: r[P1]=r[P1]+P2 */ | |
| 12821 | +#define OP_RealAffinity 93 | |
| 12822 | +#define OP_Cast 94 /* synopsis: affinity(r[P1]) */ | |
| 12823 | +#define OP_Permutation 95 | |
| 12824 | +#define OP_Compare 96 /* synopsis: r[P1@P3] <-> r[P2@P3] */ | |
| 12804 | 12825 | #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ |
| 12805 | -#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ | |
| 12806 | -#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ | |
| 12807 | -#define OP_Count 100 /* synopsis: r[P2]=count() */ | |
| 12808 | -#define OP_ReadCookie 101 | |
| 12809 | -#define OP_SetCookie 102 | |
| 12810 | -#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */ | |
| 12811 | -#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */ | |
| 12812 | -#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */ | |
| 12813 | -#define OP_OpenAutoindex 106 /* synopsis: nColumn=P2 */ | |
| 12814 | -#define OP_OpenEphemeral 107 /* synopsis: nColumn=P2 */ | |
| 12815 | -#define OP_SorterOpen 108 | |
| 12816 | -#define OP_SequenceTest 109 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ | |
| 12817 | -#define OP_OpenPseudo 110 /* synopsis: P3 columns in r[P2] */ | |
| 12818 | -#define OP_Close 111 | |
| 12819 | -#define OP_ColumnsUsed 112 | |
| 12820 | -#define OP_Sequence 113 /* synopsis: r[P2]=cursor[P1].ctr++ */ | |
| 12821 | -#define OP_NewRowid 114 /* synopsis: r[P2]=rowid */ | |
| 12822 | -#define OP_Insert 115 /* synopsis: intkey=r[P3] data=r[P2] */ | |
| 12823 | -#define OP_InsertInt 116 /* synopsis: intkey=P3 data=r[P2] */ | |
| 12824 | -#define OP_Delete 117 | |
| 12825 | -#define OP_ResetCount 118 | |
| 12826 | -#define OP_SorterCompare 119 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ | |
| 12827 | -#define OP_SorterData 120 /* synopsis: r[P2]=data */ | |
| 12828 | -#define OP_RowData 121 /* synopsis: r[P2]=data */ | |
| 12829 | -#define OP_Rowid 122 /* synopsis: r[P2]=rowid */ | |
| 12830 | -#define OP_NullRow 123 | |
| 12831 | -#define OP_SorterInsert 124 /* synopsis: key=r[P2] */ | |
| 12832 | -#define OP_IdxInsert 125 /* synopsis: key=r[P2] */ | |
| 12833 | -#define OP_IdxDelete 126 /* synopsis: key=r[P2@P3] */ | |
| 12834 | -#define OP_Seek 127 /* synopsis: Move P3 to P1.rowid */ | |
| 12835 | -#define OP_IdxRowid 128 /* synopsis: r[P2]=rowid */ | |
| 12836 | -#define OP_Destroy 129 | |
| 12837 | -#define OP_Clear 130 | |
| 12838 | -#define OP_ResetSorter 131 | |
| 12826 | +#define OP_Column 98 /* synopsis: r[P3]=PX */ | |
| 12827 | +#define OP_Affinity 99 /* synopsis: affinity(r[P1@P2]) */ | |
| 12828 | +#define OP_MakeRecord 100 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ | |
| 12829 | +#define OP_Count 101 /* synopsis: r[P2]=count() */ | |
| 12830 | +#define OP_ReadCookie 102 | |
| 12831 | +#define OP_SetCookie 103 | |
| 12832 | +#define OP_ReopenIdx 104 /* synopsis: root=P2 iDb=P3 */ | |
| 12833 | +#define OP_OpenRead 105 /* synopsis: root=P2 iDb=P3 */ | |
| 12834 | +#define OP_OpenWrite 106 /* synopsis: root=P2 iDb=P3 */ | |
| 12835 | +#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2 */ | |
| 12836 | +#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2 */ | |
| 12837 | +#define OP_SorterOpen 109 | |
| 12838 | +#define OP_SequenceTest 110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ | |
| 12839 | +#define OP_OpenPseudo 111 /* synopsis: P3 columns in r[P2] */ | |
| 12840 | +#define OP_Close 112 | |
| 12841 | +#define OP_ColumnsUsed 113 | |
| 12842 | +#define OP_Sequence 114 /* synopsis: r[P2]=cursor[P1].ctr++ */ | |
| 12843 | +#define OP_NewRowid 115 /* synopsis: r[P2]=rowid */ | |
| 12844 | +#define OP_Insert 116 /* synopsis: intkey=r[P3] data=r[P2] */ | |
| 12845 | +#define OP_InsertInt 117 /* synopsis: intkey=P3 data=r[P2] */ | |
| 12846 | +#define OP_Delete 118 | |
| 12847 | +#define OP_ResetCount 119 | |
| 12848 | +#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ | |
| 12849 | +#define OP_SorterData 121 /* synopsis: r[P2]=data */ | |
| 12850 | +#define OP_RowData 122 /* synopsis: r[P2]=data */ | |
| 12851 | +#define OP_Rowid 123 /* synopsis: r[P2]=rowid */ | |
| 12852 | +#define OP_NullRow 124 | |
| 12853 | +#define OP_SorterInsert 125 /* synopsis: key=r[P2] */ | |
| 12854 | +#define OP_IdxInsert 126 /* synopsis: key=r[P2] */ | |
| 12855 | +#define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ | |
| 12856 | +#define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ | |
| 12857 | +#define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ | |
| 12858 | +#define OP_Destroy 130 | |
| 12859 | +#define OP_Clear 131 | |
| 12839 | 12860 | #define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 12840 | -#define OP_CreateIndex 133 /* synopsis: r[P2]=root iDb=P1 */ | |
| 12841 | -#define OP_CreateTable 134 /* synopsis: r[P2]=root iDb=P1 */ | |
| 12842 | -#define OP_ParseSchema 135 | |
| 12843 | -#define OP_LoadAnalysis 136 | |
| 12844 | -#define OP_DropTable 137 | |
| 12845 | -#define OP_DropIndex 138 | |
| 12846 | -#define OP_DropTrigger 139 | |
| 12847 | -#define OP_IntegrityCk 140 | |
| 12848 | -#define OP_RowSetAdd 141 /* synopsis: rowset(P1)=r[P2] */ | |
| 12849 | -#define OP_Param 142 | |
| 12850 | -#define OP_FkCounter 143 /* synopsis: fkctr[P1]+=P2 */ | |
| 12851 | -#define OP_MemMax 144 /* synopsis: r[P1]=max(r[P1],r[P2]) */ | |
| 12852 | -#define OP_OffsetLimit 145 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ | |
| 12853 | -#define OP_AggStep0 146 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 12854 | -#define OP_AggStep 147 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 12855 | -#define OP_AggFinal 148 /* synopsis: accum=r[P1] N=P2 */ | |
| 12856 | -#define OP_Expire 149 | |
| 12857 | -#define OP_TableLock 150 /* synopsis: iDb=P1 root=P2 write=P3 */ | |
| 12858 | -#define OP_VBegin 151 | |
| 12859 | -#define OP_VCreate 152 | |
| 12860 | -#define OP_VDestroy 153 | |
| 12861 | -#define OP_VOpen 154 | |
| 12862 | -#define OP_VColumn 155 /* synopsis: r[P3]=vcolumn(P2) */ | |
| 12863 | -#define OP_VRename 156 | |
| 12864 | -#define OP_Pagecount 157 | |
| 12865 | -#define OP_MaxPgcnt 158 | |
| 12866 | -#define OP_CursorHint 159 | |
| 12867 | -#define OP_Noop 160 | |
| 12868 | -#define OP_Explain 161 | |
| 12861 | +#define OP_ResetSorter 133 | |
| 12862 | +#define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */ | |
| 12863 | +#define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */ | |
| 12864 | +#define OP_SqlExec 136 | |
| 12865 | +#define OP_ParseSchema 137 | |
| 12866 | +#define OP_LoadAnalysis 138 | |
| 12867 | +#define OP_DropTable 139 | |
| 12868 | +#define OP_DropIndex 140 | |
| 12869 | +#define OP_DropTrigger 141 | |
| 12870 | +#define OP_IntegrityCk 142 | |
| 12871 | +#define OP_RowSetAdd 143 /* synopsis: rowset(P1)=r[P2] */ | |
| 12872 | +#define OP_Param 144 | |
| 12873 | +#define OP_FkCounter 145 /* synopsis: fkctr[P1]+=P2 */ | |
| 12874 | +#define OP_MemMax 146 /* synopsis: r[P1]=max(r[P1],r[P2]) */ | |
| 12875 | +#define OP_OffsetLimit 147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ | |
| 12876 | +#define OP_AggStep0 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 12877 | +#define OP_AggStep 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 12878 | +#define OP_AggFinal 150 /* synopsis: accum=r[P1] N=P2 */ | |
| 12879 | +#define OP_Expire 151 | |
| 12880 | +#define OP_TableLock 152 /* synopsis: iDb=P1 root=P2 write=P3 */ | |
| 12881 | +#define OP_VBegin 153 | |
| 12882 | +#define OP_VCreate 154 | |
| 12883 | +#define OP_VDestroy 155 | |
| 12884 | +#define OP_VOpen 156 | |
| 12885 | +#define OP_VColumn 157 /* synopsis: r[P3]=vcolumn(P2) */ | |
| 12886 | +#define OP_VRename 158 | |
| 12887 | +#define OP_Pagecount 159 | |
| 12888 | +#define OP_MaxPgcnt 160 | |
| 12889 | +#define OP_CursorHint 161 | |
| 12890 | +#define OP_Noop 162 | |
| 12891 | +#define OP_Explain 163 | |
| 12869 | 12892 | |
| 12870 | 12893 | /* Properties such as "out2" or "jump" that are specified in |
| 12871 | 12894 | ** comments following the "case" for each opcode in the vdbe.c |
| 12872 | 12895 | ** are encoded into bitvectors as follows: |
| 12873 | 12896 | */ |
| @@ -12883,32 +12906,32 @@ | ||
| 12883 | 12906 | /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x09,\ |
| 12884 | 12907 | /* 24 */ 0x09, 0x09, 0x09, 0x26, 0x26, 0x09, 0x09, 0x09,\ |
| 12885 | 12908 | /* 32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ |
| 12886 | 12909 | /* 40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\ |
| 12887 | 12910 | /* 48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\ |
| 12888 | -/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0b,\ | |
| 12889 | -/* 64 */ 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01,\ | |
| 12890 | -/* 72 */ 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10,\ | |
| 12891 | -/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,\ | |
| 12892 | -/* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ | |
| 12893 | -/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ | |
| 12911 | +/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23,\ | |
| 12912 | +/* 64 */ 0x0b, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01,\ | |
| 12913 | +/* 72 */ 0x01, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\ | |
| 12914 | +/* 80 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\ | |
| 12915 | +/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,\ | |
| 12916 | +/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ | |
| 12894 | 12917 | /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12895 | -/* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ | |
| 12896 | -/* 120 */ 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00, 0x00,\ | |
| 12897 | -/* 128 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\ | |
| 12898 | -/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\ | |
| 12899 | -/* 144 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ | |
| 12900 | -/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ | |
| 12901 | -/* 160 */ 0x00, 0x00,} | |
| 12918 | +/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ | |
| 12919 | +/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\ | |
| 12920 | +/* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\ | |
| 12921 | +/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\ | |
| 12922 | +/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\ | |
| 12923 | +/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ | |
| 12924 | +/* 160 */ 0x10, 0x00, 0x00, 0x00,} | |
| 12902 | 12925 | |
| 12903 | 12926 | /* The sqlite3P2Values() routine is able to run faster if it knows |
| 12904 | 12927 | ** the value of the largest JUMP opcode. The smaller the maximum |
| 12905 | 12928 | ** JUMP opcode the better, so the mkopcodeh.tcl script that |
| 12906 | 12929 | ** generated this include file strives to group all JUMP opcodes |
| 12907 | 12930 | ** together near the beginning of the list. |
| 12908 | 12931 | */ |
| 12909 | -#define SQLITE_MX_JUMP_OPCODE 71 /* Maximum JUMP opcode */ | |
| 12932 | +#define SQLITE_MX_JUMP_OPCODE 72 /* Maximum JUMP opcode */ | |
| 12910 | 12933 | |
| 12911 | 12934 | /************** End of opcodes.h *********************************************/ |
| 12912 | 12935 | /************** Continuing where we left off in vdbe.h ***********************/ |
| 12913 | 12936 | |
| 12914 | 12937 | /* |
| @@ -14074,10 +14097,11 @@ | ||
| 14074 | 14097 | u8 suppressErr; /* Do not issue error messages if true */ |
| 14075 | 14098 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
| 14076 | 14099 | u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ |
| 14077 | 14100 | u8 mTrace; /* zero or more SQLITE_TRACE flags */ |
| 14078 | 14101 | u8 skipBtreeMutex; /* True if no shared-cache backends */ |
| 14102 | + u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ | |
| 14079 | 14103 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 14080 | 14104 | u32 magic; /* Magic number for detect library misuse */ |
| 14081 | 14105 | int nChange; /* Value returned by sqlite3_changes() */ |
| 14082 | 14106 | int nTotalChange; /* Value returned by sqlite3_total_changes() */ |
| 14083 | 14107 | int aLimit[SQLITE_N_LIMIT]; /* Limits */ |
| @@ -14589,18 +14613,18 @@ | ||
| 14589 | 14613 | char *zColAff; /* String defining the affinity of each column */ |
| 14590 | 14614 | ExprList *pCheck; /* All CHECK constraints */ |
| 14591 | 14615 | /* ... also used as column name list in a VIEW */ |
| 14592 | 14616 | int tnum; /* Root BTree page for this table */ |
| 14593 | 14617 | u32 nTabRef; /* Number of pointers to this Table */ |
| 14618 | + u32 tabFlags; /* Mask of TF_* values */ | |
| 14594 | 14619 | i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ |
| 14595 | 14620 | i16 nCol; /* Number of columns in this table */ |
| 14596 | 14621 | LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ |
| 14597 | 14622 | LogEst szTabRow; /* Estimated size of each table row in bytes */ |
| 14598 | 14623 | #ifdef SQLITE_ENABLE_COSTMULT |
| 14599 | 14624 | LogEst costMult; /* Cost multiplier for using this table */ |
| 14600 | 14625 | #endif |
| 14601 | - u8 tabFlags; /* Mask of TF_* values */ | |
| 14602 | 14626 | u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ |
| 14603 | 14627 | #ifndef SQLITE_OMIT_ALTERTABLE |
| 14604 | 14628 | int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ |
| 14605 | 14629 | #endif |
| 14606 | 14630 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| @@ -14620,27 +14644,29 @@ | ||
| 14620 | 14644 | ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING |
| 14621 | 14645 | ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, |
| 14622 | 14646 | ** the TF_OOOHidden attribute would apply in this case. Such tables require |
| 14623 | 14647 | ** special handling during INSERT processing. |
| 14624 | 14648 | */ |
| 14625 | -#define TF_Readonly 0x01 /* Read-only system table */ | |
| 14626 | -#define TF_Ephemeral 0x02 /* An ephemeral table */ | |
| 14627 | -#define TF_HasPrimaryKey 0x04 /* Table has a primary key */ | |
| 14628 | -#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ | |
| 14629 | -#define TF_Virtual 0x10 /* Is a virtual table */ | |
| 14630 | -#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */ | |
| 14631 | -#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */ | |
| 14632 | -#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */ | |
| 14633 | - | |
| 14649 | +#define TF_Readonly 0x0001 /* Read-only system table */ | |
| 14650 | +#define TF_Ephemeral 0x0002 /* An ephemeral table */ | |
| 14651 | +#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */ | |
| 14652 | +#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */ | |
| 14653 | +#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ | |
| 14654 | +#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */ | |
| 14655 | +#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */ | |
| 14656 | +#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */ | |
| 14657 | +#define TF_StatsUsed 0x0100 /* Query planner decisions affected by | |
| 14658 | + ** Index.aiRowLogEst[] values */ | |
| 14659 | +#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ | |
| 14634 | 14660 | |
| 14635 | 14661 | /* |
| 14636 | 14662 | ** Test to see whether or not a table is a virtual table. This is |
| 14637 | 14663 | ** done as a macro so that it will be optimized out when virtual |
| 14638 | 14664 | ** table support is omitted from the build. |
| 14639 | 14665 | */ |
| 14640 | 14666 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 14641 | -# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) | |
| 14667 | +# define IsVirtual(X) ((X)->nModuleArg) | |
| 14642 | 14668 | #else |
| 14643 | 14669 | # define IsVirtual(X) 0 |
| 14644 | 14670 | #endif |
| 14645 | 14671 | |
| 14646 | 14672 | /* |
| @@ -14871,10 +14897,11 @@ | ||
| 14871 | 14897 | unsigned bUnordered:1; /* Use this index for == or IN queries only */ |
| 14872 | 14898 | unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ |
| 14873 | 14899 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ |
| 14874 | 14900 | unsigned isCovering:1; /* True if this is a covering index */ |
| 14875 | 14901 | unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ |
| 14902 | + unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ | |
| 14876 | 14903 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 14877 | 14904 | int nSample; /* Number of elements in aSample[] */ |
| 14878 | 14905 | int nSampleCol; /* Size of IndexSample.anEq[] and so on */ |
| 14879 | 14906 | tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ |
| 14880 | 14907 | IndexSample *aSample; /* Samples of the left-most key */ |
| @@ -15181,11 +15208,11 @@ | ||
| 15181 | 15208 | ** form is used for name resolution with nested FROM clauses. |
| 15182 | 15209 | */ |
| 15183 | 15210 | struct ExprList { |
| 15184 | 15211 | int nExpr; /* Number of expressions on the list */ |
| 15185 | 15212 | struct ExprList_item { /* For each expression in the list */ |
| 15186 | - Expr *pExpr; /* The list of expressions */ | |
| 15213 | + Expr *pExpr; /* The parse tree for this expression */ | |
| 15187 | 15214 | char *zName; /* Token associated with this expression */ |
| 15188 | 15215 | char *zSpan; /* Original text of the expression */ |
| 15189 | 15216 | u8 sortOrder; /* 1 for DESC or 0 for ASC */ |
| 15190 | 15217 | unsigned done :1; /* A flag to indicate when processing is finished */ |
| 15191 | 15218 | unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ |
| @@ -16504,10 +16531,11 @@ | ||
| 16504 | 16531 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); |
| 16505 | 16532 | SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*); |
| 16506 | 16533 | SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int); |
| 16507 | 16534 | SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); |
| 16508 | 16535 | SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int); |
| 16536 | +SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); | |
| 16509 | 16537 | SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); |
| 16510 | 16538 | SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int); |
| 16511 | 16539 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); |
| 16512 | 16540 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); |
| 16513 | 16541 | SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); |
| @@ -17450,11 +17478,11 @@ | ||
| 17450 | 17478 | "COMPILER=gcc-" __VERSION__, |
| 17451 | 17479 | #endif |
| 17452 | 17480 | #if SQLITE_COVERAGE_TEST |
| 17453 | 17481 | "COVERAGE_TEST", |
| 17454 | 17482 | #endif |
| 17455 | -#if SQLITE_DEBUG | |
| 17483 | +#ifdef SQLITE_DEBUG | |
| 17456 | 17484 | "DEBUG", |
| 17457 | 17485 | #endif |
| 17458 | 17486 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17459 | 17487 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17460 | 17488 | #endif |
| @@ -19505,22 +19533,23 @@ | ||
| 19505 | 19533 | ** |
| 19506 | 19534 | ** Move the date backwards to the beginning of the current day, |
| 19507 | 19535 | ** or month or year. |
| 19508 | 19536 | */ |
| 19509 | 19537 | if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break; |
| 19538 | + if( !p->validJD && !p->validYMD && !p->validHMS ) break; | |
| 19510 | 19539 | z += 9; |
| 19511 | 19540 | computeYMD(p); |
| 19512 | 19541 | p->validHMS = 1; |
| 19513 | 19542 | p->h = p->m = 0; |
| 19514 | 19543 | p->s = 0.0; |
| 19544 | + p->rawS = 0; | |
| 19515 | 19545 | p->validTZ = 0; |
| 19516 | 19546 | p->validJD = 0; |
| 19517 | 19547 | if( sqlite3_stricmp(z,"month")==0 ){ |
| 19518 | 19548 | p->D = 1; |
| 19519 | 19549 | rc = 0; |
| 19520 | 19550 | }else if( sqlite3_stricmp(z,"year")==0 ){ |
| 19521 | - computeYMD(p); | |
| 19522 | 19551 | p->M = 1; |
| 19523 | 19552 | p->D = 1; |
| 19524 | 19553 | rc = 0; |
| 19525 | 19554 | }else if( sqlite3_stricmp(z,"day")==0 ){ |
| 19526 | 19555 | rc = 0; |
| @@ -24050,12 +24079,12 @@ | ||
| 24050 | 24079 | #ifdef SQLITE_DEBUG |
| 24051 | 24080 | assert( p->nRef>0 || p->owner==0 ); |
| 24052 | 24081 | p->owner = tid; |
| 24053 | 24082 | p->nRef++; |
| 24054 | 24083 | if( p->trace ){ |
| 24055 | - OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", | |
| 24056 | - tid, p, p->trace, p->nRef)); | |
| 24084 | + OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", | |
| 24085 | + tid, p->id, p, p->trace, p->nRef)); | |
| 24057 | 24086 | } |
| 24058 | 24087 | #endif |
| 24059 | 24088 | } |
| 24060 | 24089 | |
| 24061 | 24090 | static int winMutexTry(sqlite3_mutex *p){ |
| @@ -24093,12 +24122,12 @@ | ||
| 24093 | 24122 | #else |
| 24094 | 24123 | UNUSED_PARAMETER(p); |
| 24095 | 24124 | #endif |
| 24096 | 24125 | #ifdef SQLITE_DEBUG |
| 24097 | 24126 | if( p->trace ){ |
| 24098 | - OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n", | |
| 24099 | - tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); | |
| 24127 | + OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n", | |
| 24128 | + tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); | |
| 24100 | 24129 | } |
| 24101 | 24130 | #endif |
| 24102 | 24131 | return rc; |
| 24103 | 24132 | } |
| 24104 | 24133 | |
| @@ -24122,12 +24151,12 @@ | ||
| 24122 | 24151 | #endif |
| 24123 | 24152 | assert( winMutex_isInit==1 ); |
| 24124 | 24153 | LeaveCriticalSection(&p->mutex); |
| 24125 | 24154 | #ifdef SQLITE_DEBUG |
| 24126 | 24155 | if( p->trace ){ |
| 24127 | - OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", | |
| 24128 | - tid, p, p->trace, p->nRef)); | |
| 24156 | + OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", | |
| 24157 | + tid, p->id, p, p->trace, p->nRef)); | |
| 24129 | 24158 | } |
| 24130 | 24159 | #endif |
| 24131 | 24160 | } |
| 24132 | 24161 | |
| 24133 | 24162 | SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ |
| @@ -24383,10 +24412,17 @@ | ||
| 24383 | 24412 | ** implementation of malloc_good_size(), which must be called in debug |
| 24384 | 24413 | ** mode and specifically when the DMD "Dark Matter Detector" is enabled |
| 24385 | 24414 | ** or else a crash results. Hence, do not attempt to optimize out the |
| 24386 | 24415 | ** following xRoundup() call. */ |
| 24387 | 24416 | nFull = sqlite3GlobalConfig.m.xRoundup(n); |
| 24417 | + | |
| 24418 | +#ifdef SQLITE_MAX_MEMORY | |
| 24419 | + if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){ | |
| 24420 | + *pp = 0; | |
| 24421 | + return; | |
| 24422 | + } | |
| 24423 | +#endif | |
| 24388 | 24424 | |
| 24389 | 24425 | sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); |
| 24390 | 24426 | if( mem0.alarmThreshold>0 ){ |
| 24391 | 24427 | sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); |
| 24392 | 24428 | if( nUsed >= mem0.alarmThreshold - nFull ){ |
| @@ -24572,11 +24608,11 @@ | ||
| 24572 | 24608 | return sqlite3GlobalConfig.m.xSize(p); |
| 24573 | 24609 | } |
| 24574 | 24610 | SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ |
| 24575 | 24611 | assert( p!=0 ); |
| 24576 | 24612 | if( db==0 || !isLookaside(db,p) ){ |
| 24577 | -#if SQLITE_DEBUG | |
| 24613 | +#ifdef SQLITE_DEBUG | |
| 24578 | 24614 | if( db==0 ){ |
| 24579 | 24615 | assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); |
| 24580 | 24616 | assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); |
| 24581 | 24617 | }else{ |
| 24582 | 24618 | assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| @@ -24633,11 +24669,11 @@ | ||
| 24633 | 24669 | measureAllocationSize(db, p); |
| 24634 | 24670 | return; |
| 24635 | 24671 | } |
| 24636 | 24672 | if( isLookaside(db, p) ){ |
| 24637 | 24673 | LookasideSlot *pBuf = (LookasideSlot*)p; |
| 24638 | -#if SQLITE_DEBUG | |
| 24674 | +#ifdef SQLITE_DEBUG | |
| 24639 | 24675 | /* Trash all content in the buffer being freed */ |
| 24640 | 24676 | memset(p, 0xaa, db->lookaside.sz); |
| 24641 | 24677 | #endif |
| 24642 | 24678 | pBuf->pNext = db->lookaside.pFree; |
| 24643 | 24679 | db->lookaside.pFree = pBuf; |
| @@ -25002,11 +25038,11 @@ | ||
| 25002 | 25038 | |
| 25003 | 25039 | /* |
| 25004 | 25040 | ** Conversion types fall into various categories as defined by the |
| 25005 | 25041 | ** following enumeration. |
| 25006 | 25042 | */ |
| 25007 | -#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */ | |
| 25043 | +#define etRADIX 0 /* non-decimal integer types. %x %o */ | |
| 25008 | 25044 | #define etFLOAT 1 /* Floating point. %f */ |
| 25009 | 25045 | #define etEXP 2 /* Exponentional notation. %e and %E */ |
| 25010 | 25046 | #define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ |
| 25011 | 25047 | #define etSIZE 4 /* Return number of characters processed so far. %n */ |
| 25012 | 25048 | #define etSTRING 5 /* Strings. %s */ |
| @@ -25020,12 +25056,13 @@ | ||
| 25020 | 25056 | #define etTOKEN 11 /* a pointer to a Token structure */ |
| 25021 | 25057 | #define etSRCLIST 12 /* a pointer to a SrcList */ |
| 25022 | 25058 | #define etPOINTER 13 /* The %p conversion */ |
| 25023 | 25059 | #define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ |
| 25024 | 25060 | #define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ |
| 25061 | +#define etDECIMAL 16 /* %d or %u, but not %x, %o */ | |
| 25025 | 25062 | |
| 25026 | -#define etINVALID 16 /* Any unrecognized conversion type */ | |
| 25063 | +#define etINVALID 17 /* Any unrecognized conversion type */ | |
| 25027 | 25064 | |
| 25028 | 25065 | |
| 25029 | 25066 | /* |
| 25030 | 25067 | ** An "etByte" is an 8-bit unsigned value. |
| 25031 | 25068 | */ |
| @@ -25045,40 +25082,40 @@ | ||
| 25045 | 25082 | } et_info; |
| 25046 | 25083 | |
| 25047 | 25084 | /* |
| 25048 | 25085 | ** Allowed values for et_info.flags |
| 25049 | 25086 | */ |
| 25050 | -#define FLAG_SIGNED 1 /* True if the value to convert is signed */ | |
| 25051 | -#define FLAG_STRING 4 /* Allow infinity precision */ | |
| 25087 | +#define FLAG_SIGNED 1 /* True if the value to convert is signed */ | |
| 25088 | +#define FLAG_STRING 4 /* Allow infinite precision */ | |
| 25052 | 25089 | |
| 25053 | 25090 | |
| 25054 | 25091 | /* |
| 25055 | 25092 | ** The following table is searched linearly, so it is good to put the |
| 25056 | 25093 | ** most frequently used conversion types first. |
| 25057 | 25094 | */ |
| 25058 | 25095 | static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; |
| 25059 | 25096 | static const char aPrefix[] = "-x0\000X0"; |
| 25060 | 25097 | static const et_info fmtinfo[] = { |
| 25061 | - { 'd', 10, 1, etRADIX, 0, 0 }, | |
| 25098 | + { 'd', 10, 1, etDECIMAL, 0, 0 }, | |
| 25062 | 25099 | { 's', 0, 4, etSTRING, 0, 0 }, |
| 25063 | 25100 | { 'g', 0, 1, etGENERIC, 30, 0 }, |
| 25064 | 25101 | { 'z', 0, 4, etDYNSTRING, 0, 0 }, |
| 25065 | 25102 | { 'q', 0, 4, etSQLESCAPE, 0, 0 }, |
| 25066 | 25103 | { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, |
| 25067 | 25104 | { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, |
| 25068 | 25105 | { 'c', 0, 0, etCHARX, 0, 0 }, |
| 25069 | 25106 | { 'o', 8, 0, etRADIX, 0, 2 }, |
| 25070 | - { 'u', 10, 0, etRADIX, 0, 0 }, | |
| 25107 | + { 'u', 10, 0, etDECIMAL, 0, 0 }, | |
| 25071 | 25108 | { 'x', 16, 0, etRADIX, 16, 1 }, |
| 25072 | 25109 | { 'X', 16, 0, etRADIX, 0, 4 }, |
| 25073 | 25110 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 25074 | 25111 | { 'f', 0, 1, etFLOAT, 0, 0 }, |
| 25075 | 25112 | { 'e', 0, 1, etEXP, 30, 0 }, |
| 25076 | 25113 | { 'E', 0, 1, etEXP, 14, 0 }, |
| 25077 | 25114 | { 'G', 0, 1, etGENERIC, 14, 0 }, |
| 25078 | 25115 | #endif |
| 25079 | - { 'i', 10, 1, etRADIX, 0, 0 }, | |
| 25116 | + { 'i', 10, 1, etDECIMAL, 0, 0 }, | |
| 25080 | 25117 | { 'n', 0, 0, etSIZE, 0, 0 }, |
| 25081 | 25118 | { '%', 0, 0, etPERCENT, 0, 0 }, |
| 25082 | 25119 | { 'p', 16, 0, etPOINTER, 0, 1 }, |
| 25083 | 25120 | |
| 25084 | 25121 | /* All the rest are undocumented and are for internal use only */ |
| @@ -25166,18 +25203,17 @@ | ||
| 25166 | 25203 | int precision; /* Precision of the current field */ |
| 25167 | 25204 | int length; /* Length of the field */ |
| 25168 | 25205 | int idx; /* A general purpose loop counter */ |
| 25169 | 25206 | int width; /* Width of the current field */ |
| 25170 | 25207 | etByte flag_leftjustify; /* True if "-" flag is present */ |
| 25171 | - etByte flag_plussign; /* True if "+" flag is present */ | |
| 25172 | - etByte flag_blanksign; /* True if " " flag is present */ | |
| 25208 | + etByte flag_prefix; /* '+' or ' ' or 0 for prefix */ | |
| 25173 | 25209 | etByte flag_alternateform; /* True if "#" flag is present */ |
| 25174 | 25210 | etByte flag_altform2; /* True if "!" flag is present */ |
| 25175 | 25211 | etByte flag_zeropad; /* True if field width constant starts with zero */ |
| 25176 | - etByte flag_long; /* True if "l" flag is present */ | |
| 25177 | - etByte flag_longlong; /* True if the "ll" flag is present */ | |
| 25212 | + etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */ | |
| 25178 | 25213 | etByte done; /* Loop termination flag */ |
| 25214 | + etByte cThousand; /* Thousands separator for %d and %u */ | |
| 25179 | 25215 | etByte xtype = etINVALID; /* Conversion paradigm */ |
| 25180 | 25216 | u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ |
| 25181 | 25217 | char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ |
| 25182 | 25218 | sqlite_uint64 longvalue; /* Value for integer types */ |
| 25183 | 25219 | LONGDOUBLE_TYPE realvalue; /* Value for real types */ |
| @@ -25216,21 +25252,22 @@ | ||
| 25216 | 25252 | if( (c=(*++fmt))==0 ){ |
| 25217 | 25253 | sqlite3StrAccumAppend(pAccum, "%", 1); |
| 25218 | 25254 | break; |
| 25219 | 25255 | } |
| 25220 | 25256 | /* Find out what flags are present */ |
| 25221 | - flag_leftjustify = flag_plussign = flag_blanksign = | |
| 25257 | + flag_leftjustify = flag_prefix = cThousand = | |
| 25222 | 25258 | flag_alternateform = flag_altform2 = flag_zeropad = 0; |
| 25223 | 25259 | done = 0; |
| 25224 | 25260 | do{ |
| 25225 | 25261 | switch( c ){ |
| 25226 | 25262 | case '-': flag_leftjustify = 1; break; |
| 25227 | - case '+': flag_plussign = 1; break; | |
| 25228 | - case ' ': flag_blanksign = 1; break; | |
| 25263 | + case '+': flag_prefix = '+'; break; | |
| 25264 | + case ' ': flag_prefix = ' '; break; | |
| 25229 | 25265 | case '#': flag_alternateform = 1; break; |
| 25230 | 25266 | case '!': flag_altform2 = 1; break; |
| 25231 | 25267 | case '0': flag_zeropad = 1; break; |
| 25268 | + case ',': cThousand = ','; break; | |
| 25232 | 25269 | default: done = 1; break; |
| 25233 | 25270 | } |
| 25234 | 25271 | }while( !done && (c=(*++fmt))!=0 ); |
| 25235 | 25272 | /* Get the field width */ |
| 25236 | 25273 | if( c=='*' ){ |
| @@ -25296,17 +25333,15 @@ | ||
| 25296 | 25333 | /* Get the conversion type modifier */ |
| 25297 | 25334 | if( c=='l' ){ |
| 25298 | 25335 | flag_long = 1; |
| 25299 | 25336 | c = *++fmt; |
| 25300 | 25337 | if( c=='l' ){ |
| 25301 | - flag_longlong = 1; | |
| 25338 | + flag_long = 2; | |
| 25302 | 25339 | c = *++fmt; |
| 25303 | - }else{ | |
| 25304 | - flag_longlong = 0; | |
| 25305 | 25340 | } |
| 25306 | 25341 | }else{ |
| 25307 | - flag_long = flag_longlong = 0; | |
| 25342 | + flag_long = 0; | |
| 25308 | 25343 | } |
| 25309 | 25344 | /* Fetch the info entry for the field */ |
| 25310 | 25345 | infop = &fmtinfo[0]; |
| 25311 | 25346 | xtype = etINVALID; |
| 25312 | 25347 | for(idx=0; idx<ArraySize(fmtinfo); idx++){ |
| @@ -25320,41 +25355,42 @@ | ||
| 25320 | 25355 | /* |
| 25321 | 25356 | ** At this point, variables are initialized as follows: |
| 25322 | 25357 | ** |
| 25323 | 25358 | ** flag_alternateform TRUE if a '#' is present. |
| 25324 | 25359 | ** flag_altform2 TRUE if a '!' is present. |
| 25325 | - ** flag_plussign TRUE if a '+' is present. | |
| 25360 | + ** flag_prefix '+' or ' ' or zero | |
| 25326 | 25361 | ** flag_leftjustify TRUE if a '-' is present or if the |
| 25327 | 25362 | ** field width was negative. |
| 25328 | 25363 | ** flag_zeropad TRUE if the width began with 0. |
| 25329 | - ** flag_long TRUE if the letter 'l' (ell) prefixed | |
| 25330 | - ** the conversion character. | |
| 25331 | - ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed | |
| 25332 | - ** the conversion character. | |
| 25333 | - ** flag_blanksign TRUE if a ' ' is present. | |
| 25364 | + ** flag_long 1 for "l", 2 for "ll" | |
| 25334 | 25365 | ** width The specified field width. This is |
| 25335 | 25366 | ** always non-negative. Zero is the default. |
| 25336 | 25367 | ** precision The specified precision. The default |
| 25337 | 25368 | ** is -1. |
| 25338 | 25369 | ** xtype The class of the conversion. |
| 25339 | 25370 | ** infop Pointer to the appropriate info struct. |
| 25340 | 25371 | */ |
| 25341 | 25372 | switch( xtype ){ |
| 25342 | 25373 | case etPOINTER: |
| 25343 | - flag_longlong = sizeof(char*)==sizeof(i64); | |
| 25344 | - flag_long = sizeof(char*)==sizeof(long int); | |
| 25374 | + flag_long = sizeof(char*)==sizeof(i64) ? 2 : | |
| 25375 | + sizeof(char*)==sizeof(long int) ? 1 : 0; | |
| 25345 | 25376 | /* Fall through into the next case */ |
| 25346 | 25377 | case etORDINAL: |
| 25347 | - case etRADIX: | |
| 25378 | + case etRADIX: | |
| 25379 | + cThousand = 0; | |
| 25380 | + /* Fall through into the next case */ | |
| 25381 | + case etDECIMAL: | |
| 25348 | 25382 | if( infop->flags & FLAG_SIGNED ){ |
| 25349 | 25383 | i64 v; |
| 25350 | 25384 | if( bArgList ){ |
| 25351 | 25385 | v = getIntArg(pArgList); |
| 25352 | - }else if( flag_longlong ){ | |
| 25353 | - v = va_arg(ap,i64); | |
| 25354 | 25386 | }else if( flag_long ){ |
| 25355 | - v = va_arg(ap,long int); | |
| 25387 | + if( flag_long==2 ){ | |
| 25388 | + v = va_arg(ap,i64) ; | |
| 25389 | + }else{ | |
| 25390 | + v = va_arg(ap,long int); | |
| 25391 | + } | |
| 25356 | 25392 | }else{ |
| 25357 | 25393 | v = va_arg(ap,int); |
| 25358 | 25394 | } |
| 25359 | 25395 | if( v<0 ){ |
| 25360 | 25396 | if( v==SMALLEST_INT64 ){ |
| @@ -25363,35 +25399,35 @@ | ||
| 25363 | 25399 | longvalue = -v; |
| 25364 | 25400 | } |
| 25365 | 25401 | prefix = '-'; |
| 25366 | 25402 | }else{ |
| 25367 | 25403 | longvalue = v; |
| 25368 | - if( flag_plussign ) prefix = '+'; | |
| 25369 | - else if( flag_blanksign ) prefix = ' '; | |
| 25370 | - else prefix = 0; | |
| 25404 | + prefix = flag_prefix; | |
| 25371 | 25405 | } |
| 25372 | 25406 | }else{ |
| 25373 | 25407 | if( bArgList ){ |
| 25374 | 25408 | longvalue = (u64)getIntArg(pArgList); |
| 25375 | - }else if( flag_longlong ){ | |
| 25376 | - longvalue = va_arg(ap,u64); | |
| 25377 | 25409 | }else if( flag_long ){ |
| 25378 | - longvalue = va_arg(ap,unsigned long int); | |
| 25410 | + if( flag_long==2 ){ | |
| 25411 | + longvalue = va_arg(ap,u64); | |
| 25412 | + }else{ | |
| 25413 | + longvalue = va_arg(ap,unsigned long int); | |
| 25414 | + } | |
| 25379 | 25415 | }else{ |
| 25380 | 25416 | longvalue = va_arg(ap,unsigned int); |
| 25381 | 25417 | } |
| 25382 | 25418 | prefix = 0; |
| 25383 | 25419 | } |
| 25384 | 25420 | if( longvalue==0 ) flag_alternateform = 0; |
| 25385 | 25421 | if( flag_zeropad && precision<width-(prefix!=0) ){ |
| 25386 | 25422 | precision = width-(prefix!=0); |
| 25387 | 25423 | } |
| 25388 | - if( precision<etBUFSIZE-10 ){ | |
| 25424 | + if( precision<etBUFSIZE-10-etBUFSIZE/3 ){ | |
| 25389 | 25425 | nOut = etBUFSIZE; |
| 25390 | 25426 | zOut = buf; |
| 25391 | 25427 | }else{ |
| 25392 | - nOut = precision + 10; | |
| 25428 | + nOut = precision + 10 + precision/3; | |
| 25393 | 25429 | zOut = zExtra = sqlite3Malloc( nOut ); |
| 25394 | 25430 | if( zOut==0 ){ |
| 25395 | 25431 | setStrAccumError(pAccum, STRACCUM_NOMEM); |
| 25396 | 25432 | return; |
| 25397 | 25433 | } |
| @@ -25413,12 +25449,27 @@ | ||
| 25413 | 25449 | *(--bufpt) = cset[longvalue%base]; |
| 25414 | 25450 | longvalue = longvalue/base; |
| 25415 | 25451 | }while( longvalue>0 ); |
| 25416 | 25452 | } |
| 25417 | 25453 | length = (int)(&zOut[nOut-1]-bufpt); |
| 25418 | - for(idx=precision-length; idx>0; idx--){ | |
| 25454 | + while( precision>length ){ | |
| 25419 | 25455 | *(--bufpt) = '0'; /* Zero pad */ |
| 25456 | + length++; | |
| 25457 | + } | |
| 25458 | + if( cThousand ){ | |
| 25459 | + int nn = (length - 1)/3; /* Number of "," to insert */ | |
| 25460 | + int ix = (length - 1)%3 + 1; | |
| 25461 | + bufpt -= nn; | |
| 25462 | + for(idx=0; nn>0; idx++){ | |
| 25463 | + bufpt[idx] = bufpt[idx+nn]; | |
| 25464 | + ix--; | |
| 25465 | + if( ix==0 ){ | |
| 25466 | + bufpt[++idx] = cThousand; | |
| 25467 | + nn--; | |
| 25468 | + ix = 3; | |
| 25469 | + } | |
| 25470 | + } | |
| 25420 | 25471 | } |
| 25421 | 25472 | if( prefix ) *(--bufpt) = prefix; /* Add sign */ |
| 25422 | 25473 | if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ |
| 25423 | 25474 | const char *pre; |
| 25424 | 25475 | char x; |
| @@ -25441,13 +25492,11 @@ | ||
| 25441 | 25492 | if( precision<0 ) precision = 6; /* Set default precision */ |
| 25442 | 25493 | if( realvalue<0.0 ){ |
| 25443 | 25494 | realvalue = -realvalue; |
| 25444 | 25495 | prefix = '-'; |
| 25445 | 25496 | }else{ |
| 25446 | - if( flag_plussign ) prefix = '+'; | |
| 25447 | - else if( flag_blanksign ) prefix = ' '; | |
| 25448 | - else prefix = 0; | |
| 25497 | + prefix = flag_prefix; | |
| 25449 | 25498 | } |
| 25450 | 25499 | if( xtype==etGENERIC && precision>0 ) precision--; |
| 25451 | 25500 | testcase( precision>0xfff ); |
| 25452 | 25501 | for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} |
| 25453 | 25502 | if( xtype==etFLOAT ) realvalue += rounder; |
| @@ -29464,117 +29513,119 @@ | ||
| 29464 | 29513 | /* 50 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), |
| 29465 | 29514 | /* 51 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), |
| 29466 | 29515 | /* 52 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), |
| 29467 | 29516 | /* 53 */ "Last" OpHelp(""), |
| 29468 | 29517 | /* 54 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), |
| 29469 | - /* 55 */ "SorterSort" OpHelp(""), | |
| 29470 | - /* 56 */ "Sort" OpHelp(""), | |
| 29471 | - /* 57 */ "Rewind" OpHelp(""), | |
| 29472 | - /* 58 */ "IdxLE" OpHelp("key=r[P3@P4]"), | |
| 29473 | - /* 59 */ "IdxGT" OpHelp("key=r[P3@P4]"), | |
| 29474 | - /* 60 */ "IdxLT" OpHelp("key=r[P3@P4]"), | |
| 29475 | - /* 61 */ "IdxGE" OpHelp("key=r[P3@P4]"), | |
| 29476 | - /* 62 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), | |
| 29477 | - /* 63 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), | |
| 29478 | - /* 64 */ "Program" OpHelp(""), | |
| 29479 | - /* 65 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), | |
| 29480 | - /* 66 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), | |
| 29481 | - /* 67 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), | |
| 29482 | - /* 68 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), | |
| 29483 | - /* 69 */ "IncrVacuum" OpHelp(""), | |
| 29484 | - /* 70 */ "VNext" OpHelp(""), | |
| 29485 | - /* 71 */ "Init" OpHelp("Start at P2"), | |
| 29486 | - /* 72 */ "Return" OpHelp(""), | |
| 29487 | - /* 73 */ "EndCoroutine" OpHelp(""), | |
| 29488 | - /* 74 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), | |
| 29489 | - /* 75 */ "Halt" OpHelp(""), | |
| 29490 | - /* 76 */ "Integer" OpHelp("r[P2]=P1"), | |
| 29491 | - /* 77 */ "Int64" OpHelp("r[P2]=P4"), | |
| 29492 | - /* 78 */ "String" OpHelp("r[P2]='P4' (len=P1)"), | |
| 29493 | - /* 79 */ "Null" OpHelp("r[P2..P3]=NULL"), | |
| 29494 | - /* 80 */ "SoftNull" OpHelp("r[P1]=NULL"), | |
| 29495 | - /* 81 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), | |
| 29496 | - /* 82 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), | |
| 29497 | - /* 83 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), | |
| 29498 | - /* 84 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), | |
| 29499 | - /* 85 */ "SCopy" OpHelp("r[P2]=r[P1]"), | |
| 29500 | - /* 86 */ "IntCopy" OpHelp("r[P2]=r[P1]"), | |
| 29501 | - /* 87 */ "ResultRow" OpHelp("output=r[P1@P2]"), | |
| 29502 | - /* 88 */ "CollSeq" OpHelp(""), | |
| 29503 | - /* 89 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 29504 | - /* 90 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 29505 | - /* 91 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), | |
| 29506 | - /* 92 */ "RealAffinity" OpHelp(""), | |
| 29507 | - /* 93 */ "Cast" OpHelp("affinity(r[P1])"), | |
| 29508 | - /* 94 */ "Permutation" OpHelp(""), | |
| 29509 | - /* 95 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), | |
| 29510 | - /* 96 */ "Column" OpHelp("r[P3]=PX"), | |
| 29518 | + /* 55 */ "IfSmaller" OpHelp(""), | |
| 29519 | + /* 56 */ "SorterSort" OpHelp(""), | |
| 29520 | + /* 57 */ "Sort" OpHelp(""), | |
| 29521 | + /* 58 */ "Rewind" OpHelp(""), | |
| 29522 | + /* 59 */ "IdxLE" OpHelp("key=r[P3@P4]"), | |
| 29523 | + /* 60 */ "IdxGT" OpHelp("key=r[P3@P4]"), | |
| 29524 | + /* 61 */ "IdxLT" OpHelp("key=r[P3@P4]"), | |
| 29525 | + /* 62 */ "IdxGE" OpHelp("key=r[P3@P4]"), | |
| 29526 | + /* 63 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), | |
| 29527 | + /* 64 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), | |
| 29528 | + /* 65 */ "Program" OpHelp(""), | |
| 29529 | + /* 66 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), | |
| 29530 | + /* 67 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), | |
| 29531 | + /* 68 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), | |
| 29532 | + /* 69 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), | |
| 29533 | + /* 70 */ "IncrVacuum" OpHelp(""), | |
| 29534 | + /* 71 */ "VNext" OpHelp(""), | |
| 29535 | + /* 72 */ "Init" OpHelp("Start at P2"), | |
| 29536 | + /* 73 */ "Return" OpHelp(""), | |
| 29537 | + /* 74 */ "EndCoroutine" OpHelp(""), | |
| 29538 | + /* 75 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), | |
| 29539 | + /* 76 */ "Halt" OpHelp(""), | |
| 29540 | + /* 77 */ "Integer" OpHelp("r[P2]=P1"), | |
| 29541 | + /* 78 */ "Int64" OpHelp("r[P2]=P4"), | |
| 29542 | + /* 79 */ "String" OpHelp("r[P2]='P4' (len=P1)"), | |
| 29543 | + /* 80 */ "Null" OpHelp("r[P2..P3]=NULL"), | |
| 29544 | + /* 81 */ "SoftNull" OpHelp("r[P1]=NULL"), | |
| 29545 | + /* 82 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), | |
| 29546 | + /* 83 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), | |
| 29547 | + /* 84 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), | |
| 29548 | + /* 85 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), | |
| 29549 | + /* 86 */ "SCopy" OpHelp("r[P2]=r[P1]"), | |
| 29550 | + /* 87 */ "IntCopy" OpHelp("r[P2]=r[P1]"), | |
| 29551 | + /* 88 */ "ResultRow" OpHelp("output=r[P1@P2]"), | |
| 29552 | + /* 89 */ "CollSeq" OpHelp(""), | |
| 29553 | + /* 90 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 29554 | + /* 91 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 29555 | + /* 92 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), | |
| 29556 | + /* 93 */ "RealAffinity" OpHelp(""), | |
| 29557 | + /* 94 */ "Cast" OpHelp("affinity(r[P1])"), | |
| 29558 | + /* 95 */ "Permutation" OpHelp(""), | |
| 29559 | + /* 96 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), | |
| 29511 | 29560 | /* 97 */ "String8" OpHelp("r[P2]='P4'"), |
| 29512 | - /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), | |
| 29513 | - /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), | |
| 29514 | - /* 100 */ "Count" OpHelp("r[P2]=count()"), | |
| 29515 | - /* 101 */ "ReadCookie" OpHelp(""), | |
| 29516 | - /* 102 */ "SetCookie" OpHelp(""), | |
| 29517 | - /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), | |
| 29518 | - /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"), | |
| 29519 | - /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), | |
| 29520 | - /* 106 */ "OpenAutoindex" OpHelp("nColumn=P2"), | |
| 29521 | - /* 107 */ "OpenEphemeral" OpHelp("nColumn=P2"), | |
| 29522 | - /* 108 */ "SorterOpen" OpHelp(""), | |
| 29523 | - /* 109 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), | |
| 29524 | - /* 110 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), | |
| 29525 | - /* 111 */ "Close" OpHelp(""), | |
| 29526 | - /* 112 */ "ColumnsUsed" OpHelp(""), | |
| 29527 | - /* 113 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), | |
| 29528 | - /* 114 */ "NewRowid" OpHelp("r[P2]=rowid"), | |
| 29529 | - /* 115 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), | |
| 29530 | - /* 116 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), | |
| 29531 | - /* 117 */ "Delete" OpHelp(""), | |
| 29532 | - /* 118 */ "ResetCount" OpHelp(""), | |
| 29533 | - /* 119 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), | |
| 29534 | - /* 120 */ "SorterData" OpHelp("r[P2]=data"), | |
| 29535 | - /* 121 */ "RowData" OpHelp("r[P2]=data"), | |
| 29536 | - /* 122 */ "Rowid" OpHelp("r[P2]=rowid"), | |
| 29537 | - /* 123 */ "NullRow" OpHelp(""), | |
| 29538 | - /* 124 */ "SorterInsert" OpHelp("key=r[P2]"), | |
| 29539 | - /* 125 */ "IdxInsert" OpHelp("key=r[P2]"), | |
| 29540 | - /* 126 */ "IdxDelete" OpHelp("key=r[P2@P3]"), | |
| 29541 | - /* 127 */ "Seek" OpHelp("Move P3 to P1.rowid"), | |
| 29542 | - /* 128 */ "IdxRowid" OpHelp("r[P2]=rowid"), | |
| 29543 | - /* 129 */ "Destroy" OpHelp(""), | |
| 29544 | - /* 130 */ "Clear" OpHelp(""), | |
| 29545 | - /* 131 */ "ResetSorter" OpHelp(""), | |
| 29561 | + /* 98 */ "Column" OpHelp("r[P3]=PX"), | |
| 29562 | + /* 99 */ "Affinity" OpHelp("affinity(r[P1@P2])"), | |
| 29563 | + /* 100 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), | |
| 29564 | + /* 101 */ "Count" OpHelp("r[P2]=count()"), | |
| 29565 | + /* 102 */ "ReadCookie" OpHelp(""), | |
| 29566 | + /* 103 */ "SetCookie" OpHelp(""), | |
| 29567 | + /* 104 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), | |
| 29568 | + /* 105 */ "OpenRead" OpHelp("root=P2 iDb=P3"), | |
| 29569 | + /* 106 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), | |
| 29570 | + /* 107 */ "OpenAutoindex" OpHelp("nColumn=P2"), | |
| 29571 | + /* 108 */ "OpenEphemeral" OpHelp("nColumn=P2"), | |
| 29572 | + /* 109 */ "SorterOpen" OpHelp(""), | |
| 29573 | + /* 110 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), | |
| 29574 | + /* 111 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), | |
| 29575 | + /* 112 */ "Close" OpHelp(""), | |
| 29576 | + /* 113 */ "ColumnsUsed" OpHelp(""), | |
| 29577 | + /* 114 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), | |
| 29578 | + /* 115 */ "NewRowid" OpHelp("r[P2]=rowid"), | |
| 29579 | + /* 116 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), | |
| 29580 | + /* 117 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), | |
| 29581 | + /* 118 */ "Delete" OpHelp(""), | |
| 29582 | + /* 119 */ "ResetCount" OpHelp(""), | |
| 29583 | + /* 120 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), | |
| 29584 | + /* 121 */ "SorterData" OpHelp("r[P2]=data"), | |
| 29585 | + /* 122 */ "RowData" OpHelp("r[P2]=data"), | |
| 29586 | + /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), | |
| 29587 | + /* 124 */ "NullRow" OpHelp(""), | |
| 29588 | + /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), | |
| 29589 | + /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), | |
| 29590 | + /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), | |
| 29591 | + /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), | |
| 29592 | + /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), | |
| 29593 | + /* 130 */ "Destroy" OpHelp(""), | |
| 29594 | + /* 131 */ "Clear" OpHelp(""), | |
| 29546 | 29595 | /* 132 */ "Real" OpHelp("r[P2]=P4"), |
| 29547 | - /* 133 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), | |
| 29548 | - /* 134 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), | |
| 29549 | - /* 135 */ "ParseSchema" OpHelp(""), | |
| 29550 | - /* 136 */ "LoadAnalysis" OpHelp(""), | |
| 29551 | - /* 137 */ "DropTable" OpHelp(""), | |
| 29552 | - /* 138 */ "DropIndex" OpHelp(""), | |
| 29553 | - /* 139 */ "DropTrigger" OpHelp(""), | |
| 29554 | - /* 140 */ "IntegrityCk" OpHelp(""), | |
| 29555 | - /* 141 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), | |
| 29556 | - /* 142 */ "Param" OpHelp(""), | |
| 29557 | - /* 143 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), | |
| 29558 | - /* 144 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), | |
| 29559 | - /* 145 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), | |
| 29560 | - /* 146 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 29561 | - /* 147 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 29562 | - /* 148 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), | |
| 29563 | - /* 149 */ "Expire" OpHelp(""), | |
| 29564 | - /* 150 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), | |
| 29565 | - /* 151 */ "VBegin" OpHelp(""), | |
| 29566 | - /* 152 */ "VCreate" OpHelp(""), | |
| 29567 | - /* 153 */ "VDestroy" OpHelp(""), | |
| 29568 | - /* 154 */ "VOpen" OpHelp(""), | |
| 29569 | - /* 155 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), | |
| 29570 | - /* 156 */ "VRename" OpHelp(""), | |
| 29571 | - /* 157 */ "Pagecount" OpHelp(""), | |
| 29572 | - /* 158 */ "MaxPgcnt" OpHelp(""), | |
| 29573 | - /* 159 */ "CursorHint" OpHelp(""), | |
| 29574 | - /* 160 */ "Noop" OpHelp(""), | |
| 29575 | - /* 161 */ "Explain" OpHelp(""), | |
| 29596 | + /* 133 */ "ResetSorter" OpHelp(""), | |
| 29597 | + /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), | |
| 29598 | + /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), | |
| 29599 | + /* 136 */ "SqlExec" OpHelp(""), | |
| 29600 | + /* 137 */ "ParseSchema" OpHelp(""), | |
| 29601 | + /* 138 */ "LoadAnalysis" OpHelp(""), | |
| 29602 | + /* 139 */ "DropTable" OpHelp(""), | |
| 29603 | + /* 140 */ "DropIndex" OpHelp(""), | |
| 29604 | + /* 141 */ "DropTrigger" OpHelp(""), | |
| 29605 | + /* 142 */ "IntegrityCk" OpHelp(""), | |
| 29606 | + /* 143 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), | |
| 29607 | + /* 144 */ "Param" OpHelp(""), | |
| 29608 | + /* 145 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), | |
| 29609 | + /* 146 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), | |
| 29610 | + /* 147 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), | |
| 29611 | + /* 148 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 29612 | + /* 149 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 29613 | + /* 150 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), | |
| 29614 | + /* 151 */ "Expire" OpHelp(""), | |
| 29615 | + /* 152 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), | |
| 29616 | + /* 153 */ "VBegin" OpHelp(""), | |
| 29617 | + /* 154 */ "VCreate" OpHelp(""), | |
| 29618 | + /* 155 */ "VDestroy" OpHelp(""), | |
| 29619 | + /* 156 */ "VOpen" OpHelp(""), | |
| 29620 | + /* 157 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), | |
| 29621 | + /* 158 */ "VRename" OpHelp(""), | |
| 29622 | + /* 159 */ "Pagecount" OpHelp(""), | |
| 29623 | + /* 160 */ "MaxPgcnt" OpHelp(""), | |
| 29624 | + /* 161 */ "CursorHint" OpHelp(""), | |
| 29625 | + /* 162 */ "Noop" OpHelp(""), | |
| 29626 | + /* 163 */ "Explain" OpHelp(""), | |
| 29576 | 29627 | }; |
| 29577 | 29628 | return azName[i]; |
| 29578 | 29629 | } |
| 29579 | 29630 | #endif |
| 29580 | 29631 | |
| @@ -37952,46 +38003,84 @@ | ||
| 37952 | 38003 | * be freed immediately and any attempt to access any of that freed |
| 37953 | 38004 | * data will almost certainly result in an immediate access violation. |
| 37954 | 38005 | ****************************************************************************** |
| 37955 | 38006 | */ |
| 37956 | 38007 | #ifndef SQLITE_WIN32_HEAP_CREATE |
| 37957 | -# define SQLITE_WIN32_HEAP_CREATE (TRUE) | |
| 38008 | +# define SQLITE_WIN32_HEAP_CREATE (TRUE) | |
| 38009 | +#endif | |
| 38010 | + | |
| 38011 | +/* | |
| 38012 | + * This is the maximum possible initial size of the Win32-specific heap, in | |
| 38013 | + * bytes. | |
| 38014 | + */ | |
| 38015 | +#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE | |
| 38016 | +# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U) | |
| 38017 | +#endif | |
| 38018 | + | |
| 38019 | +/* | |
| 38020 | + * This is the extra space for the initial size of the Win32-specific heap, | |
| 38021 | + * in bytes. This value may be zero. | |
| 38022 | + */ | |
| 38023 | +#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA | |
| 38024 | +# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304) | |
| 38025 | +#endif | |
| 38026 | + | |
| 38027 | +/* | |
| 38028 | + * Calculate the maximum legal cache size, in pages, based on the maximum | |
| 38029 | + * possible initial heap size and the default page size, setting aside the | |
| 38030 | + * needed extra space. | |
| 38031 | + */ | |
| 38032 | +#ifndef SQLITE_WIN32_MAX_CACHE_SIZE | |
| 38033 | +# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \ | |
| 38034 | + (SQLITE_WIN32_HEAP_INIT_EXTRA)) / \ | |
| 38035 | + (SQLITE_DEFAULT_PAGE_SIZE)) | |
| 37958 | 38036 | #endif |
| 37959 | 38037 | |
| 37960 | 38038 | /* |
| 37961 | 38039 | * This is cache size used in the calculation of the initial size of the |
| 37962 | 38040 | * Win32-specific heap. It cannot be negative. |
| 37963 | 38041 | */ |
| 37964 | 38042 | #ifndef SQLITE_WIN32_CACHE_SIZE |
| 37965 | 38043 | # if SQLITE_DEFAULT_CACHE_SIZE>=0 |
| 37966 | -# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) | |
| 38044 | +# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) | |
| 37967 | 38045 | # else |
| 37968 | -# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) | |
| 38046 | +# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) | |
| 37969 | 38047 | # endif |
| 37970 | 38048 | #endif |
| 37971 | 38049 | |
| 38050 | +/* | |
| 38051 | + * Make sure that the calculated cache size, in pages, cannot cause the | |
| 38052 | + * initial size of the Win32-specific heap to exceed the maximum amount | |
| 38053 | + * of memory that can be specified in the call to HeapCreate. | |
| 38054 | + */ | |
| 38055 | +#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE | |
| 38056 | +# undef SQLITE_WIN32_CACHE_SIZE | |
| 38057 | +# define SQLITE_WIN32_CACHE_SIZE (2000) | |
| 38058 | +#endif | |
| 38059 | + | |
| 37972 | 38060 | /* |
| 37973 | 38061 | * The initial size of the Win32-specific heap. This value may be zero. |
| 37974 | 38062 | */ |
| 37975 | 38063 | #ifndef SQLITE_WIN32_HEAP_INIT_SIZE |
| 37976 | -# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ | |
| 37977 | - (SQLITE_DEFAULT_PAGE_SIZE) + 4194304) | |
| 38064 | +# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ | |
| 38065 | + (SQLITE_DEFAULT_PAGE_SIZE) + \ | |
| 38066 | + (SQLITE_WIN32_HEAP_INIT_EXTRA)) | |
| 37978 | 38067 | #endif |
| 37979 | 38068 | |
| 37980 | 38069 | /* |
| 37981 | 38070 | * The maximum size of the Win32-specific heap. This value may be zero. |
| 37982 | 38071 | */ |
| 37983 | 38072 | #ifndef SQLITE_WIN32_HEAP_MAX_SIZE |
| 37984 | -# define SQLITE_WIN32_HEAP_MAX_SIZE (0) | |
| 38073 | +# define SQLITE_WIN32_HEAP_MAX_SIZE (0) | |
| 37985 | 38074 | #endif |
| 37986 | 38075 | |
| 37987 | 38076 | /* |
| 37988 | 38077 | * The extra flags to use in calls to the Win32 heap APIs. This value may be |
| 37989 | 38078 | * zero for the default behavior. |
| 37990 | 38079 | */ |
| 37991 | 38080 | #ifndef SQLITE_WIN32_HEAP_FLAGS |
| 37992 | -# define SQLITE_WIN32_HEAP_FLAGS (0) | |
| 38081 | +# define SQLITE_WIN32_HEAP_FLAGS (0) | |
| 37993 | 38082 | #endif |
| 37994 | 38083 | |
| 37995 | 38084 | |
| 37996 | 38085 | /* |
| 37997 | 38086 | ** The winMemData structure stores information required by the Win32-specific |
| @@ -44084,11 +44173,11 @@ | ||
| 44084 | 44173 | ** This routine is for use inside of assert() statements only. For |
| 44085 | 44174 | ** example: |
| 44086 | 44175 | ** |
| 44087 | 44176 | ** assert( sqlite3PcachePageSanity(pPg) ); |
| 44088 | 44177 | */ |
| 44089 | -#if SQLITE_DEBUG | |
| 44178 | +#ifdef SQLITE_DEBUG | |
| 44090 | 44179 | SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ |
| 44091 | 44180 | PCache *pCache; |
| 44092 | 44181 | assert( pPg!=0 ); |
| 44093 | 44182 | assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */ |
| 44094 | 44183 | pCache = pPg->pCache; |
| @@ -60177,21 +60266,22 @@ | ||
| 60177 | 60266 | } |
| 60178 | 60267 | #endif |
| 60179 | 60268 | |
| 60180 | 60269 | |
| 60181 | 60270 | /* |
| 60182 | -** Defragment the page given. All Cells are moved to the | |
| 60183 | -** end of the page and all free space is collected into one | |
| 60184 | -** big FreeBlk that occurs in between the header and cell | |
| 60185 | -** pointer array and the cell content area. | |
| 60271 | +** Defragment the page given. This routine reorganizes cells within the | |
| 60272 | +** page so that there are no free-blocks on the free-block list. | |
| 60273 | +** | |
| 60274 | +** Parameter nMaxFrag is the maximum amount of fragmented space that may be | |
| 60275 | +** present in the page after this routine returns. | |
| 60186 | 60276 | ** |
| 60187 | 60277 | ** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a |
| 60188 | 60278 | ** b-tree page so that there are no freeblocks or fragment bytes, all |
| 60189 | 60279 | ** unused bytes are contained in the unallocated space region, and all |
| 60190 | 60280 | ** cells are packed tightly at the end of the page. |
| 60191 | 60281 | */ |
| 60192 | -static int defragmentPage(MemPage *pPage){ | |
| 60282 | +static int defragmentPage(MemPage *pPage, int nMaxFrag){ | |
| 60193 | 60283 | int i; /* Loop counter */ |
| 60194 | 60284 | int pc; /* Address of the i-th cell */ |
| 60195 | 60285 | int hdr; /* Offset to the page header */ |
| 60196 | 60286 | int size; /* Size of a cell */ |
| 60197 | 60287 | int usableSize; /* Number of usable bytes on a page */ |
| @@ -60202,11 +60292,10 @@ | ||
| 60202 | 60292 | unsigned char *temp; /* Temp area for cell content */ |
| 60203 | 60293 | unsigned char *src; /* Source of content */ |
| 60204 | 60294 | int iCellFirst; /* First allowable cell index */ |
| 60205 | 60295 | int iCellLast; /* Last possible cell index */ |
| 60206 | 60296 | |
| 60207 | - | |
| 60208 | 60297 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 60209 | 60298 | assert( pPage->pBt!=0 ); |
| 60210 | 60299 | assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); |
| 60211 | 60300 | assert( pPage->nOverflow==0 ); |
| 60212 | 60301 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| @@ -60214,13 +60303,60 @@ | ||
| 60214 | 60303 | src = data = pPage->aData; |
| 60215 | 60304 | hdr = pPage->hdrOffset; |
| 60216 | 60305 | cellOffset = pPage->cellOffset; |
| 60217 | 60306 | nCell = pPage->nCell; |
| 60218 | 60307 | assert( nCell==get2byte(&data[hdr+3]) ); |
| 60308 | + iCellFirst = cellOffset + 2*nCell; | |
| 60219 | 60309 | usableSize = pPage->pBt->usableSize; |
| 60310 | + | |
| 60311 | + /* This block handles pages with two or fewer free blocks and nMaxFrag | |
| 60312 | + ** or fewer fragmented bytes. In this case it is faster to move the | |
| 60313 | + ** two (or one) blocks of cells using memmove() and add the required | |
| 60314 | + ** offsets to each pointer in the cell-pointer array than it is to | |
| 60315 | + ** reconstruct the entire page. */ | |
| 60316 | + if( (int)data[hdr+7]<=nMaxFrag ){ | |
| 60317 | + int iFree = get2byte(&data[hdr+1]); | |
| 60318 | + if( iFree ){ | |
| 60319 | + int iFree2 = get2byte(&data[iFree]); | |
| 60320 | + | |
| 60321 | + /* pageFindSlot() has already verified that free blocks are sorted | |
| 60322 | + ** in order of offset within the page, and that no block extends | |
| 60323 | + ** past the end of the page. Provided the two free slots do not | |
| 60324 | + ** overlap, this guarantees that the memmove() calls below will not | |
| 60325 | + ** overwrite the usableSize byte buffer, even if the database page | |
| 60326 | + ** is corrupt. */ | |
| 60327 | + assert( iFree2==0 || iFree2>iFree ); | |
| 60328 | + assert( iFree+get2byte(&data[iFree+2]) <= usableSize ); | |
| 60329 | + assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize ); | |
| 60330 | + | |
| 60331 | + if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){ | |
| 60332 | + u8 *pEnd = &data[cellOffset + nCell*2]; | |
| 60333 | + u8 *pAddr; | |
| 60334 | + int sz2 = 0; | |
| 60335 | + int sz = get2byte(&data[iFree+2]); | |
| 60336 | + int top = get2byte(&data[hdr+5]); | |
| 60337 | + if( iFree2 ){ | |
| 60338 | + if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT; | |
| 60339 | + sz2 = get2byte(&data[iFree2+2]); | |
| 60340 | + assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); | |
| 60341 | + memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); | |
| 60342 | + sz += sz2; | |
| 60343 | + } | |
| 60344 | + cbrk = top+sz; | |
| 60345 | + assert( cbrk+(iFree-top) <= usableSize ); | |
| 60346 | + memmove(&data[cbrk], &data[top], iFree-top); | |
| 60347 | + for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){ | |
| 60348 | + pc = get2byte(pAddr); | |
| 60349 | + if( pc<iFree ){ put2byte(pAddr, pc+sz); } | |
| 60350 | + else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); } | |
| 60351 | + } | |
| 60352 | + goto defragment_out; | |
| 60353 | + } | |
| 60354 | + } | |
| 60355 | + } | |
| 60356 | + | |
| 60220 | 60357 | cbrk = usableSize; |
| 60221 | - iCellFirst = cellOffset + 2*nCell; | |
| 60222 | 60358 | iCellLast = usableSize - 4; |
| 60223 | 60359 | for(i=0; i<nCell; i++){ |
| 60224 | 60360 | u8 *pAddr; /* The i-th cell pointer */ |
| 60225 | 60361 | pAddr = &data[cellOffset + i*2]; |
| 60226 | 60362 | pc = get2byte(pAddr); |
| @@ -60250,20 +60386,22 @@ | ||
| 60250 | 60386 | memcpy(&temp[x], &data[x], (cbrk+size) - x); |
| 60251 | 60387 | src = temp; |
| 60252 | 60388 | } |
| 60253 | 60389 | memcpy(&data[cbrk], &src[pc], size); |
| 60254 | 60390 | } |
| 60391 | + data[hdr+7] = 0; | |
| 60392 | + | |
| 60393 | + defragment_out: | |
| 60394 | + if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ | |
| 60395 | + return SQLITE_CORRUPT_BKPT; | |
| 60396 | + } | |
| 60255 | 60397 | assert( cbrk>=iCellFirst ); |
| 60256 | 60398 | put2byte(&data[hdr+5], cbrk); |
| 60257 | 60399 | data[hdr+1] = 0; |
| 60258 | 60400 | data[hdr+2] = 0; |
| 60259 | - data[hdr+7] = 0; | |
| 60260 | 60401 | memset(&data[iCellFirst], 0, cbrk-iCellFirst); |
| 60261 | 60402 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 60262 | - if( cbrk-iCellFirst!=pPage->nFree ){ | |
| 60263 | - return SQLITE_CORRUPT_BKPT; | |
| 60264 | - } | |
| 60265 | 60403 | return SQLITE_OK; |
| 60266 | 60404 | } |
| 60267 | 60405 | |
| 60268 | 60406 | /* |
| 60269 | 60407 | ** Search the free-list on page pPg for space to store a cell nByte bytes in |
| @@ -60397,14 +60535,14 @@ | ||
| 60397 | 60535 | ** to see if defragmentation is necessary. |
| 60398 | 60536 | */ |
| 60399 | 60537 | testcase( gap+2+nByte==top ); |
| 60400 | 60538 | if( gap+2+nByte>top ){ |
| 60401 | 60539 | assert( pPage->nCell>0 || CORRUPT_DB ); |
| 60402 | - rc = defragmentPage(pPage); | |
| 60540 | + rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte))); | |
| 60403 | 60541 | if( rc ) return rc; |
| 60404 | 60542 | top = get2byteNotZero(&data[hdr+5]); |
| 60405 | - assert( gap+nByte<=top ); | |
| 60543 | + assert( gap+2+nByte<=top ); | |
| 60406 | 60544 | } |
| 60407 | 60545 | |
| 60408 | 60546 | |
| 60409 | 60547 | /* Allocate memory from the gap in between the cell pointer array |
| 60410 | 60548 | ** and the cell content area. The btreeInitPage() call has already |
| @@ -63636,11 +63774,11 @@ | ||
| 63636 | 63774 | pCur->aiIdx[pCur->iPage] = 0; |
| 63637 | 63775 | return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], |
| 63638 | 63776 | pCur, pCur->curPagerFlags); |
| 63639 | 63777 | } |
| 63640 | 63778 | |
| 63641 | -#if SQLITE_DEBUG | |
| 63779 | +#ifdef SQLITE_DEBUG | |
| 63642 | 63780 | /* |
| 63643 | 63781 | ** Page pParent is an internal (non-leaf) tree page. This function |
| 63644 | 63782 | ** asserts that page number iChild is the left-child if the iIdx'th |
| 63645 | 63783 | ** cell in page pParent. Or, if iIdx is equal to the total number of |
| 63646 | 63784 | ** cells in pParent, that page number iChild is the right-child of |
| @@ -64178,10 +64316,34 @@ | ||
| 64178 | 64316 | ** have been deleted? This API will need to change to return an error code |
| 64179 | 64317 | ** as well as the boolean result value. |
| 64180 | 64318 | */ |
| 64181 | 64319 | return (CURSOR_VALID!=pCur->eState); |
| 64182 | 64320 | } |
| 64321 | + | |
| 64322 | +/* | |
| 64323 | +** Return an estimate for the number of rows in the table that pCur is | |
| 64324 | +** pointing to. Return a negative number if no estimate is currently | |
| 64325 | +** available. | |
| 64326 | +*/ | |
| 64327 | +SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ | |
| 64328 | + i64 n; | |
| 64329 | + u8 i; | |
| 64330 | + | |
| 64331 | + assert( cursorOwnsBtShared(pCur) ); | |
| 64332 | + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); | |
| 64333 | + | |
| 64334 | + /* Currently this interface is only called by the OP_IfSmaller | |
| 64335 | + ** opcode, and it that case the cursor will always be valid and | |
| 64336 | + ** will always point to a leaf node. */ | |
| 64337 | + if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1; | |
| 64338 | + if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1; | |
| 64339 | + | |
| 64340 | + for(n=1, i=0; i<=pCur->iPage; i++){ | |
| 64341 | + n *= pCur->apPage[i]->nCell; | |
| 64342 | + } | |
| 64343 | + return n; | |
| 64344 | +} | |
| 64183 | 64345 | |
| 64184 | 64346 | /* |
| 64185 | 64347 | ** Advance the cursor to the next entry in the database. If |
| 64186 | 64348 | ** successful then set *pRes=0. If the cursor |
| 64187 | 64349 | ** was already pointing to the last entry in the database before |
| @@ -65023,11 +65185,11 @@ | ||
| 65023 | 65185 | ** pPrior Where to write the pgno of the first overflow page |
| 65024 | 65186 | ** |
| 65025 | 65187 | ** Use a call to btreeParseCellPtr() to verify that the values above |
| 65026 | 65188 | ** were computed correctly. |
| 65027 | 65189 | */ |
| 65028 | -#if SQLITE_DEBUG | |
| 65190 | +#ifdef SQLITE_DEBUG | |
| 65029 | 65191 | { |
| 65030 | 65192 | CellInfo info; |
| 65031 | 65193 | pPage->xParseCell(pPage, pCell, &info); |
| 65032 | 65194 | assert( nHeader==(int)(info.pPayload - pCell) ); |
| 65033 | 65195 | assert( info.nKey==pX->nKey ); |
| @@ -66549,11 +66711,11 @@ | ||
| 66549 | 66711 | ** copied into the parent, because if the parent is page 1 then it will |
| 66550 | 66712 | ** by smaller than the child due to the database header, and so all the |
| 66551 | 66713 | ** free space needs to be up front. |
| 66552 | 66714 | */ |
| 66553 | 66715 | assert( nNew==1 || CORRUPT_DB ); |
| 66554 | - rc = defragmentPage(apNew[0]); | |
| 66716 | + rc = defragmentPage(apNew[0], -1); | |
| 66555 | 66717 | testcase( rc!=SQLITE_OK ); |
| 66556 | 66718 | assert( apNew[0]->nFree == |
| 66557 | 66719 | (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) |
| 66558 | 66720 | || rc!=SQLITE_OK |
| 66559 | 66721 | ); |
| @@ -71201,10 +71363,11 @@ | ||
| 71201 | 71363 | ** Remember the SQL string for a prepared statement. |
| 71202 | 71364 | */ |
| 71203 | 71365 | SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ |
| 71204 | 71366 | assert( isPrepareV2==1 || isPrepareV2==0 ); |
| 71205 | 71367 | if( p==0 ) return; |
| 71368 | + if( !isPrepareV2 ) p->expmask = 0; | |
| 71206 | 71369 | #if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) |
| 71207 | 71370 | if( !isPrepareV2 ) return; |
| 71208 | 71371 | #endif |
| 71209 | 71372 | assert( p->zSql==0 ); |
| 71210 | 71373 | p->zSql = sqlite3DbStrNDup(p->db, z, n); |
| @@ -71229,10 +71392,11 @@ | ||
| 71229 | 71392 | pB->pPrev = pTmp; |
| 71230 | 71393 | zTmp = pA->zSql; |
| 71231 | 71394 | pA->zSql = pB->zSql; |
| 71232 | 71395 | pB->zSql = zTmp; |
| 71233 | 71396 | pB->isPrepareV2 = pA->isPrepareV2; |
| 71397 | + pB->expmask = pA->expmask; | |
| 71234 | 71398 | } |
| 71235 | 71399 | |
| 71236 | 71400 | /* |
| 71237 | 71401 | ** Resize the Vdbe.aOp array so that it is at least nOp elements larger |
| 71238 | 71402 | ** than its current size. nOp is guaranteed to be less than or equal |
| @@ -73753,17 +73917,17 @@ | ||
| 73753 | 73917 | ** Then the internal cache might have been left in an inconsistent |
| 73754 | 73918 | ** state. We need to rollback the statement transaction, if there is |
| 73755 | 73919 | ** one, or the complete transaction if there is no statement transaction. |
| 73756 | 73920 | */ |
| 73757 | 73921 | |
| 73922 | + if( p->magic!=VDBE_MAGIC_RUN ){ | |
| 73923 | + return SQLITE_OK; | |
| 73924 | + } | |
| 73758 | 73925 | if( db->mallocFailed ){ |
| 73759 | 73926 | p->rc = SQLITE_NOMEM_BKPT; |
| 73760 | 73927 | } |
| 73761 | 73928 | closeAllCursors(p); |
| 73762 | - if( p->magic!=VDBE_MAGIC_RUN ){ | |
| 73763 | - return SQLITE_OK; | |
| 73764 | - } | |
| 73765 | 73929 | checkActiveVdbeCnt(db); |
| 73766 | 73930 | |
| 73767 | 73931 | /* No commit or rollback needed if the program never started or if the |
| 73768 | 73932 | ** SQL statement does not read or write a database file. */ |
| 73769 | 73933 | if( p->pc>=0 && p->bIsReader ){ |
| @@ -74706,11 +74870,11 @@ | ||
| 74706 | 74870 | } |
| 74707 | 74871 | assert( u<=pKeyInfo->nField + 1 ); |
| 74708 | 74872 | p->nField = u; |
| 74709 | 74873 | } |
| 74710 | 74874 | |
| 74711 | -#if SQLITE_DEBUG | |
| 74875 | +#ifdef SQLITE_DEBUG | |
| 74712 | 74876 | /* |
| 74713 | 74877 | ** This function compares two index or table record keys in the same way |
| 74714 | 74878 | ** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), |
| 74715 | 74879 | ** this function deserializes and compares values using the |
| 74716 | 74880 | ** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used |
| @@ -74811,11 +74975,11 @@ | ||
| 74811 | 74975 | if( pKeyInfo->db->mallocFailed ) return 1; |
| 74812 | 74976 | return 0; |
| 74813 | 74977 | } |
| 74814 | 74978 | #endif |
| 74815 | 74979 | |
| 74816 | -#if SQLITE_DEBUG | |
| 74980 | +#ifdef SQLITE_DEBUG | |
| 74817 | 74981 | /* |
| 74818 | 74982 | ** Count the number of fields (a.k.a. columns) in the record given by |
| 74819 | 74983 | ** pKey,nKey. The verify that this count is less than or equal to the |
| 74820 | 74984 | ** limit given by pKeyInfo->nField + pKeyInfo->nXField. |
| 74821 | 74985 | ** |
| @@ -75694,12 +75858,12 @@ | ||
| 75694 | 75858 | ** to sqlite3_reoptimize() that re-preparing the statement may result |
| 75695 | 75859 | ** in a better query plan. |
| 75696 | 75860 | */ |
| 75697 | 75861 | SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ |
| 75698 | 75862 | assert( iVar>0 ); |
| 75699 | - if( iVar>32 ){ | |
| 75700 | - v->expmask = 0xffffffff; | |
| 75863 | + if( iVar>=32 ){ | |
| 75864 | + v->expmask |= 0x80000000; | |
| 75701 | 75865 | }else{ |
| 75702 | 75866 | v->expmask |= ((u32)1 << (iVar-1)); |
| 75703 | 75867 | } |
| 75704 | 75868 | } |
| 75705 | 75869 | |
| @@ -75965,11 +76129,12 @@ | ||
| 75965 | 76129 | sqlite3_mutex_enter(mutex); |
| 75966 | 76130 | for(i=0; i<p->nVar; i++){ |
| 75967 | 76131 | sqlite3VdbeMemRelease(&p->aVar[i]); |
| 75968 | 76132 | p->aVar[i].flags = MEM_Null; |
| 75969 | 76133 | } |
| 75970 | - if( p->isPrepareV2 && p->expmask ){ | |
| 76134 | + assert( p->isPrepareV2 || p->expmask==0 ); | |
| 76135 | + if( p->expmask ){ | |
| 75971 | 76136 | p->expired = 1; |
| 75972 | 76137 | } |
| 75973 | 76138 | sqlite3_mutex_leave(mutex); |
| 75974 | 76139 | return rc; |
| 75975 | 76140 | } |
| @@ -77069,13 +77234,12 @@ | ||
| 77069 | 77234 | ** parameter in the WHERE clause might influence the choice of query plan |
| 77070 | 77235 | ** for a statement, then the statement will be automatically recompiled, |
| 77071 | 77236 | ** as if there had been a schema change, on the first sqlite3_step() call |
| 77072 | 77237 | ** following any change to the bindings of that parameter. |
| 77073 | 77238 | */ |
| 77074 | - if( p->isPrepareV2 && | |
| 77075 | - ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) | |
| 77076 | - ){ | |
| 77239 | + assert( p->isPrepareV2 || p->expmask==0 ); | |
| 77240 | + if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){ | |
| 77077 | 77241 | p->expired = 1; |
| 77078 | 77242 | } |
| 77079 | 77243 | return SQLITE_OK; |
| 77080 | 77244 | } |
| 77081 | 77245 | |
| @@ -77334,14 +77498,16 @@ | ||
| 77334 | 77498 | Vdbe *pFrom = (Vdbe*)pFromStmt; |
| 77335 | 77499 | Vdbe *pTo = (Vdbe*)pToStmt; |
| 77336 | 77500 | if( pFrom->nVar!=pTo->nVar ){ |
| 77337 | 77501 | return SQLITE_ERROR; |
| 77338 | 77502 | } |
| 77339 | - if( pTo->isPrepareV2 && pTo->expmask ){ | |
| 77503 | + assert( pTo->isPrepareV2 || pTo->expmask==0 ); | |
| 77504 | + if( pTo->expmask ){ | |
| 77340 | 77505 | pTo->expired = 1; |
| 77341 | 77506 | } |
| 77342 | - if( pFrom->isPrepareV2 && pFrom->expmask ){ | |
| 77507 | + assert( pFrom->isPrepareV2 || pFrom->expmask==0 ); | |
| 77508 | + if( pFrom->expmask ){ | |
| 77343 | 77509 | pFrom->expired = 1; |
| 77344 | 77510 | } |
| 77345 | 77511 | return sqlite3TransferBindings(pFromStmt, pToStmt); |
| 77346 | 77512 | } |
| 77347 | 77513 | #endif |
| @@ -79658,39 +79824,39 @@ | ||
| 79658 | 79824 | if( pCtx->pOut != pOut ){ |
| 79659 | 79825 | pCtx->pOut = pOut; |
| 79660 | 79826 | for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; |
| 79661 | 79827 | } |
| 79662 | 79828 | |
| 79663 | - memAboutToChange(p, pCtx->pOut); | |
| 79829 | + memAboutToChange(p, pOut); | |
| 79664 | 79830 | #ifdef SQLITE_DEBUG |
| 79665 | 79831 | for(i=0; i<pCtx->argc; i++){ |
| 79666 | 79832 | assert( memIsValid(pCtx->argv[i]) ); |
| 79667 | 79833 | REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); |
| 79668 | 79834 | } |
| 79669 | 79835 | #endif |
| 79670 | - MemSetTypeFlag(pCtx->pOut, MEM_Null); | |
| 79836 | + MemSetTypeFlag(pOut, MEM_Null); | |
| 79671 | 79837 | pCtx->fErrorOrAux = 0; |
| 79672 | 79838 | (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ |
| 79673 | 79839 | |
| 79674 | 79840 | /* If the function returned an error, throw an exception */ |
| 79675 | 79841 | if( pCtx->fErrorOrAux ){ |
| 79676 | 79842 | if( pCtx->isError ){ |
| 79677 | - sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); | |
| 79843 | + sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); | |
| 79678 | 79844 | rc = pCtx->isError; |
| 79679 | 79845 | } |
| 79680 | 79846 | sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); |
| 79681 | 79847 | if( rc ) goto abort_due_to_error; |
| 79682 | 79848 | } |
| 79683 | 79849 | |
| 79684 | 79850 | /* Copy the result of the function into register P3 */ |
| 79685 | 79851 | if( pOut->flags & (MEM_Str|MEM_Blob) ){ |
| 79686 | - sqlite3VdbeChangeEncoding(pCtx->pOut, encoding); | |
| 79687 | - if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big; | |
| 79852 | + sqlite3VdbeChangeEncoding(pOut, encoding); | |
| 79853 | + if( sqlite3VdbeMemTooBig(pOut) ) goto too_big; | |
| 79688 | 79854 | } |
| 79689 | 79855 | |
| 79690 | - REGISTER_TRACE(pOp->p3, pCtx->pOut); | |
| 79691 | - UPDATE_MAX_BLOBSIZE(pCtx->pOut); | |
| 79856 | + REGISTER_TRACE(pOp->p3, pOut); | |
| 79857 | + UPDATE_MAX_BLOBSIZE(pOut); | |
| 79692 | 79858 | break; |
| 79693 | 79859 | } |
| 79694 | 79860 | |
| 79695 | 79861 | /* Opcode: BitAnd P1 P2 P3 * * |
| 79696 | 79862 | ** Synopsis: r[P3]=r[P1]&r[P2] |
| @@ -80187,11 +80353,11 @@ | ||
| 80187 | 80353 | pKeyInfo = pOp->p4.pKeyInfo; |
| 80188 | 80354 | assert( n>0 ); |
| 80189 | 80355 | assert( pKeyInfo!=0 ); |
| 80190 | 80356 | p1 = pOp->p1; |
| 80191 | 80357 | p2 = pOp->p2; |
| 80192 | -#if SQLITE_DEBUG | |
| 80358 | +#ifdef SQLITE_DEBUG | |
| 80193 | 80359 | if( aPermute ){ |
| 80194 | 80360 | int k, mx = 0; |
| 80195 | 80361 | for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k]; |
| 80196 | 80362 | assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); |
| 80197 | 80363 | assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 ); |
| @@ -82836,10 +83002,37 @@ | ||
| 82836 | 83002 | assert( pOp->p2==0 ); |
| 82837 | 83003 | } |
| 82838 | 83004 | break; |
| 82839 | 83005 | } |
| 82840 | 83006 | |
| 83007 | +/* Opcode: IfSmaller P1 P2 P3 * * | |
| 83008 | +** | |
| 83009 | +** Estimate the number of rows in the table P1. Jump to P2 if that | |
| 83010 | +** estimate is less than approximately 2**(0.1*P3). | |
| 83011 | +*/ | |
| 83012 | +case OP_IfSmaller: { /* jump */ | |
| 83013 | + VdbeCursor *pC; | |
| 83014 | + BtCursor *pCrsr; | |
| 83015 | + int res; | |
| 83016 | + i64 sz; | |
| 83017 | + | |
| 83018 | + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); | |
| 83019 | + pC = p->apCsr[pOp->p1]; | |
| 83020 | + assert( pC!=0 ); | |
| 83021 | + pCrsr = pC->uc.pCursor; | |
| 83022 | + assert( pCrsr ); | |
| 83023 | + rc = sqlite3BtreeFirst(pCrsr, &res); | |
| 83024 | + if( rc ) goto abort_due_to_error; | |
| 83025 | + if( res==0 ){ | |
| 83026 | + sz = sqlite3BtreeRowCountEst(pCrsr); | |
| 83027 | + if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)<pOp->p3 ) res = 1; | |
| 83028 | + } | |
| 83029 | + VdbeBranchTaken(res!=0,2); | |
| 83030 | + if( res ) goto jump_to_p2; | |
| 83031 | + break; | |
| 83032 | +} | |
| 83033 | + | |
| 82841 | 83034 | |
| 82842 | 83035 | /* Opcode: SorterSort P1 P2 * * * |
| 82843 | 83036 | ** |
| 82844 | 83037 | ** After all records have been inserted into the Sorter object |
| 82845 | 83038 | ** identified by P1, invoke this opcode to actually do the sorting. |
| @@ -83479,10 +83672,22 @@ | ||
| 83479 | 83672 | rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); |
| 83480 | 83673 | if( rc ) goto abort_due_to_error; |
| 83481 | 83674 | pOut->u.i = pgno; |
| 83482 | 83675 | break; |
| 83483 | 83676 | } |
| 83677 | + | |
| 83678 | +/* Opcode: SqlExec * * * P4 * | |
| 83679 | +** | |
| 83680 | +** Run the SQL statement or statements specified in the P4 string. | |
| 83681 | +*/ | |
| 83682 | +case OP_SqlExec: { | |
| 83683 | + db->nSqlExec++; | |
| 83684 | + rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); | |
| 83685 | + db->nSqlExec--; | |
| 83686 | + if( rc ) goto abort_due_to_error; | |
| 83687 | + break; | |
| 83688 | +} | |
| 83484 | 83689 | |
| 83485 | 83690 | /* Opcode: ParseSchema P1 * * P4 * |
| 83486 | 83691 | ** |
| 83487 | 83692 | ** Read and parse all entries from the SQLITE_MASTER table of database P1 |
| 83488 | 83693 | ** that match the WHERE clause P4. |
| @@ -83600,11 +83805,11 @@ | ||
| 83600 | 83805 | ** |
| 83601 | 83806 | ** Do an analysis of the currently open database. Store in |
| 83602 | 83807 | ** register P1 the text of an error message describing any problems. |
| 83603 | 83808 | ** If no problems are found, store a NULL in register P1. |
| 83604 | 83809 | ** |
| 83605 | -** The register P3 contains the maximum number of allowed errors. | |
| 83810 | +** The register P3 contains one less than the maximum number of allowed errors. | |
| 83606 | 83811 | ** At most reg(P3) errors will be reported. |
| 83607 | 83812 | ** In other words, the analysis stops as soon as reg(P1) errors are |
| 83608 | 83813 | ** seen. Reg(P1) is updated with the number of errors remaining. |
| 83609 | 83814 | ** |
| 83610 | 83815 | ** The root page numbers of all tables in the database are integers |
| @@ -83633,18 +83838,18 @@ | ||
| 83633 | 83838 | assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); |
| 83634 | 83839 | pIn1 = &aMem[pOp->p1]; |
| 83635 | 83840 | assert( pOp->p5<db->nDb ); |
| 83636 | 83841 | assert( DbMaskTest(p->btreeMask, pOp->p5) ); |
| 83637 | 83842 | z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, |
| 83638 | - (int)pnErr->u.i, &nErr); | |
| 83639 | - pnErr->u.i -= nErr; | |
| 83843 | + (int)pnErr->u.i+1, &nErr); | |
| 83640 | 83844 | sqlite3VdbeMemSetNull(pIn1); |
| 83641 | 83845 | if( nErr==0 ){ |
| 83642 | 83846 | assert( z==0 ); |
| 83643 | 83847 | }else if( z==0 ){ |
| 83644 | 83848 | goto no_mem; |
| 83645 | 83849 | }else{ |
| 83850 | + pnErr->u.i -= nErr-1; | |
| 83646 | 83851 | sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); |
| 83647 | 83852 | } |
| 83648 | 83853 | UPDATE_MAX_BLOBSIZE(pIn1); |
| 83649 | 83854 | sqlite3VdbeChangeEncoding(pIn1, encoding); |
| 83650 | 83855 | break; |
| @@ -88787,15 +88992,15 @@ | ||
| 88787 | 88992 | ** The return value from the callback should be one of the WRC_* |
| 88788 | 88993 | ** constants to specify how to proceed with the walk. |
| 88789 | 88994 | ** |
| 88790 | 88995 | ** WRC_Continue Continue descending down the tree. |
| 88791 | 88996 | ** |
| 88792 | -** WRC_Prune Do not descend into child nodes. But allow | |
| 88997 | +** WRC_Prune Do not descend into child nodes, but allow | |
| 88793 | 88998 | ** the walk to continue with sibling nodes. |
| 88794 | 88999 | ** |
| 88795 | 89000 | ** WRC_Abort Do no more callbacks. Unwind the stack and |
| 88796 | -** return the top-level walk call. | |
| 89001 | +** return from the top-level walk call. | |
| 88797 | 89002 | ** |
| 88798 | 89003 | ** The return value from this routine is WRC_Abort to abandon the tree walk |
| 88799 | 89004 | ** and WRC_Continue to continue. |
| 88800 | 89005 | */ |
| 88801 | 89006 | static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ |
| @@ -89153,11 +89358,12 @@ | ||
| 89153 | 89358 | } |
| 89154 | 89359 | } |
| 89155 | 89360 | } |
| 89156 | 89361 | |
| 89157 | 89362 | /* Start at the inner-most context and move outward until a match is found */ |
| 89158 | - while( pNC && cnt==0 ){ | |
| 89363 | + assert( pNC && cnt==0 ); | |
| 89364 | + do{ | |
| 89159 | 89365 | ExprList *pEList; |
| 89160 | 89366 | SrcList *pSrcList = pNC->pSrcList; |
| 89161 | 89367 | |
| 89162 | 89368 | if( pSrcList ){ |
| 89163 | 89369 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| @@ -89338,15 +89544,15 @@ | ||
| 89338 | 89544 | } |
| 89339 | 89545 | |
| 89340 | 89546 | /* Advance to the next name context. The loop will exit when either |
| 89341 | 89547 | ** we have a match (cnt>0) or when we run out of name contexts. |
| 89342 | 89548 | */ |
| 89343 | - if( cnt==0 ){ | |
| 89344 | - pNC = pNC->pNext; | |
| 89345 | - nSubquery++; | |
| 89346 | - } | |
| 89347 | - } | |
| 89549 | + if( cnt ) break; | |
| 89550 | + pNC = pNC->pNext; | |
| 89551 | + nSubquery++; | |
| 89552 | + }while( pNC ); | |
| 89553 | + | |
| 89348 | 89554 | |
| 89349 | 89555 | /* |
| 89350 | 89556 | ** If X and Y are NULL (in other words if only the column name Z is |
| 89351 | 89557 | ** supplied) and the value of Z is enclosed in double-quotes, then |
| 89352 | 89558 | ** Z is a string literal if it doesn't match any column names. In that |
| @@ -89532,37 +89738,42 @@ | ||
| 89532 | 89738 | break; |
| 89533 | 89739 | } |
| 89534 | 89740 | #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) |
| 89535 | 89741 | && !defined(SQLITE_OMIT_SUBQUERY) */ |
| 89536 | 89742 | |
| 89537 | - /* A lone identifier is the name of a column. | |
| 89538 | - */ | |
| 89539 | - case TK_ID: { | |
| 89540 | - return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); | |
| 89541 | - } | |
| 89542 | - | |
| 89543 | - /* A table name and column name: ID.ID | |
| 89743 | + /* A column name: ID | |
| 89744 | + ** Or table name and column name: ID.ID | |
| 89544 | 89745 | ** Or a database, table and column: ID.ID.ID |
| 89746 | + ** | |
| 89747 | + ** The TK_ID and TK_OUT cases are combined so that there will only | |
| 89748 | + ** be one call to lookupName(). Then the compiler will in-line | |
| 89749 | + ** lookupName() for a size reduction and performance increase. | |
| 89545 | 89750 | */ |
| 89751 | + case TK_ID: | |
| 89546 | 89752 | case TK_DOT: { |
| 89547 | 89753 | const char *zColumn; |
| 89548 | 89754 | const char *zTable; |
| 89549 | 89755 | const char *zDb; |
| 89550 | 89756 | Expr *pRight; |
| 89551 | 89757 | |
| 89552 | - /* if( pSrcList==0 ) break; */ | |
| 89553 | - notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); | |
| 89554 | - pRight = pExpr->pRight; | |
| 89555 | - if( pRight->op==TK_ID ){ | |
| 89758 | + if( pExpr->op==TK_ID ){ | |
| 89556 | 89759 | zDb = 0; |
| 89557 | - zTable = pExpr->pLeft->u.zToken; | |
| 89558 | - zColumn = pRight->u.zToken; | |
| 89760 | + zTable = 0; | |
| 89761 | + zColumn = pExpr->u.zToken; | |
| 89559 | 89762 | }else{ |
| 89560 | - assert( pRight->op==TK_DOT ); | |
| 89561 | - zDb = pExpr->pLeft->u.zToken; | |
| 89562 | - zTable = pRight->pLeft->u.zToken; | |
| 89563 | - zColumn = pRight->pRight->u.zToken; | |
| 89763 | + notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); | |
| 89764 | + pRight = pExpr->pRight; | |
| 89765 | + if( pRight->op==TK_ID ){ | |
| 89766 | + zDb = 0; | |
| 89767 | + zTable = pExpr->pLeft->u.zToken; | |
| 89768 | + zColumn = pRight->u.zToken; | |
| 89769 | + }else{ | |
| 89770 | + assert( pRight->op==TK_DOT ); | |
| 89771 | + zDb = pExpr->pLeft->u.zToken; | |
| 89772 | + zTable = pRight->pLeft->u.zToken; | |
| 89773 | + zColumn = pRight->pRight->u.zToken; | |
| 89774 | + } | |
| 89564 | 89775 | } |
| 89565 | 89776 | return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); |
| 89566 | 89777 | } |
| 89567 | 89778 | |
| 89568 | 89779 | /* Resolve function names |
| @@ -92833,11 +93044,11 @@ | ||
| 92833 | 93044 | int nVal = sqlite3ExprVectorSize(pLeft); |
| 92834 | 93045 | Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; |
| 92835 | 93046 | char *zRet; |
| 92836 | 93047 | |
| 92837 | 93048 | assert( pExpr->op==TK_IN ); |
| 92838 | - zRet = sqlite3DbMallocZero(pParse->db, nVal+1); | |
| 93049 | + zRet = sqlite3DbMallocRaw(pParse->db, nVal+1); | |
| 92839 | 93050 | if( zRet ){ |
| 92840 | 93051 | int i; |
| 92841 | 93052 | for(i=0; i<nVal; i++){ |
| 92842 | 93053 | Expr *pA = sqlite3VectorFieldSubexpr(pLeft, i); |
| 92843 | 93054 | char a = sqlite3ExprAffinity(pA); |
| @@ -93738,11 +93949,11 @@ | ||
| 93738 | 93949 | ** Clear all column cache entries. |
| 93739 | 93950 | */ |
| 93740 | 93951 | SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ |
| 93741 | 93952 | int i; |
| 93742 | 93953 | |
| 93743 | -#if SQLITE_DEBUG | |
| 93954 | +#ifdef SQLITE_DEBUG | |
| 93744 | 93955 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 93745 | 93956 | printf("CLEAR\n"); |
| 93746 | 93957 | } |
| 93747 | 93958 | #endif |
| 93748 | 93959 | for(i=0; i<pParse->nColCache; i++){ |
| @@ -95145,10 +95356,21 @@ | ||
| 95145 | 95356 | if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; |
| 95146 | 95357 | if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1; |
| 95147 | 95358 | } |
| 95148 | 95359 | return 0; |
| 95149 | 95360 | } |
| 95361 | + | |
| 95362 | +/* | |
| 95363 | +** Like sqlite3ExprCompare() except COLLATE operators at the top-level | |
| 95364 | +** are ignored. | |
| 95365 | +*/ | |
| 95366 | +SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ | |
| 95367 | + return sqlite3ExprCompare( | |
| 95368 | + sqlite3ExprSkipCollate(pA), | |
| 95369 | + sqlite3ExprSkipCollate(pB), | |
| 95370 | + iTab); | |
| 95371 | +} | |
| 95150 | 95372 | |
| 95151 | 95373 | /* |
| 95152 | 95374 | ** Return true if we can prove the pE2 will always be true if pE1 is |
| 95153 | 95375 | ** true. Return false if we cannot complete the proof or if pE2 might |
| 95154 | 95376 | ** be false. Examples: |
| @@ -96698,10 +96920,11 @@ | ||
| 96698 | 96920 | Stat4Sample current; /* Current row as a Stat4Sample */ |
| 96699 | 96921 | u32 iPrn; /* Pseudo-random number used for sampling */ |
| 96700 | 96922 | Stat4Sample *aBest; /* Array of nCol best samples */ |
| 96701 | 96923 | int iMin; /* Index in a[] of entry with minimum score */ |
| 96702 | 96924 | int nSample; /* Current number of samples */ |
| 96925 | + int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */ | |
| 96703 | 96926 | int iGet; /* Index of current sample accessed by stat_get() */ |
| 96704 | 96927 | Stat4Sample *a; /* Array of mxSample Stat4Sample objects */ |
| 96705 | 96928 | sqlite3 *db; /* Database connection, for malloc() */ |
| 96706 | 96929 | }; |
| 96707 | 96930 | |
| @@ -96962,10 +97185,17 @@ | ||
| 96962 | 97185 | int i; |
| 96963 | 97186 | |
| 96964 | 97187 | assert( IsStat4 || nEqZero==0 ); |
| 96965 | 97188 | |
| 96966 | 97189 | #ifdef SQLITE_ENABLE_STAT4 |
| 97190 | + /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0 | |
| 97191 | + ** values in the anEq[] array of any sample in Stat4Accum.a[]. In | |
| 97192 | + ** other words, if nMaxEqZero is n, then it is guaranteed that there | |
| 97193 | + ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */ | |
| 97194 | + if( nEqZero>p->nMaxEqZero ){ | |
| 97195 | + p->nMaxEqZero = nEqZero; | |
| 97196 | + } | |
| 96967 | 97197 | if( pNew->isPSample==0 ){ |
| 96968 | 97198 | Stat4Sample *pUpgrade = 0; |
| 96969 | 97199 | assert( pNew->anEq[pNew->iCol]>0 ); |
| 96970 | 97200 | |
| 96971 | 97201 | /* This sample is being added because the prefix that ends in column |
| @@ -97059,16 +97289,26 @@ | ||
| 97059 | 97289 | if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ |
| 97060 | 97290 | sampleInsert(p, pBest, i); |
| 97061 | 97291 | } |
| 97062 | 97292 | } |
| 97063 | 97293 | |
| 97064 | - /* Update the anEq[] fields of any samples already collected. */ | |
| 97294 | + /* Check that no sample contains an anEq[] entry with an index of | |
| 97295 | + ** p->nMaxEqZero or greater set to zero. */ | |
| 97065 | 97296 | for(i=p->nSample-1; i>=0; i--){ |
| 97066 | 97297 | int j; |
| 97067 | - for(j=iChng; j<p->nCol; j++){ | |
| 97068 | - if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; | |
| 97298 | + for(j=p->nMaxEqZero; j<p->nCol; j++) assert( p->a[i].anEq[j]>0 ); | |
| 97299 | + } | |
| 97300 | + | |
| 97301 | + /* Update the anEq[] fields of any samples already collected. */ | |
| 97302 | + if( iChng<p->nMaxEqZero ){ | |
| 97303 | + for(i=p->nSample-1; i>=0; i--){ | |
| 97304 | + int j; | |
| 97305 | + for(j=iChng; j<p->nCol; j++){ | |
| 97306 | + if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; | |
| 97307 | + } | |
| 97069 | 97308 | } |
| 97309 | + p->nMaxEqZero = iChng; | |
| 97070 | 97310 | } |
| 97071 | 97311 | #endif |
| 97072 | 97312 | |
| 97073 | 97313 | #if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) |
| 97074 | 97314 | if( iChng==0 ){ |
| @@ -97778,44 +98018,32 @@ | ||
| 97778 | 98018 | /* Form 1: Analyze everything */ |
| 97779 | 98019 | for(i=0; i<db->nDb; i++){ |
| 97780 | 98020 | if( i==1 ) continue; /* Do not analyze the TEMP database */ |
| 97781 | 98021 | analyzeDatabase(pParse, i); |
| 97782 | 98022 | } |
| 97783 | - }else if( pName2->n==0 ){ | |
| 97784 | - /* Form 2: Analyze the database or table named */ | |
| 97785 | - iDb = sqlite3FindDb(db, pName1); | |
| 97786 | - if( iDb>=0 ){ | |
| 97787 | - analyzeDatabase(pParse, iDb); | |
| 97788 | - }else{ | |
| 97789 | - z = sqlite3NameFromToken(db, pName1); | |
| 97790 | - if( z ){ | |
| 97791 | - if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){ | |
| 97792 | - analyzeTable(pParse, pIdx->pTable, pIdx); | |
| 97793 | - }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){ | |
| 97794 | - analyzeTable(pParse, pTab, 0); | |
| 97795 | - } | |
| 97796 | - sqlite3DbFree(db, z); | |
| 97797 | - } | |
| 97798 | - } | |
| 97799 | - }else{ | |
| 97800 | - /* Form 3: Analyze the fully qualified table name */ | |
| 98023 | + }else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){ | |
| 98024 | + /* Analyze the schema named as the argument */ | |
| 98025 | + analyzeDatabase(pParse, iDb); | |
| 98026 | + }else{ | |
| 98027 | + /* Form 3: Analyze the table or index named as an argument */ | |
| 97801 | 98028 | iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); |
| 97802 | 98029 | if( iDb>=0 ){ |
| 97803 | - zDb = db->aDb[iDb].zDbSName; | |
| 98030 | + zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; | |
| 97804 | 98031 | z = sqlite3NameFromToken(db, pTableName); |
| 97805 | 98032 | if( z ){ |
| 97806 | 98033 | if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ |
| 97807 | 98034 | analyzeTable(pParse, pIdx->pTable, pIdx); |
| 97808 | 98035 | }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ |
| 97809 | 98036 | analyzeTable(pParse, pTab, 0); |
| 97810 | 98037 | } |
| 97811 | 98038 | sqlite3DbFree(db, z); |
| 97812 | 98039 | } |
| 97813 | - } | |
| 98040 | + } | |
| 97814 | 98041 | } |
| 97815 | - v = sqlite3GetVdbe(pParse); | |
| 97816 | - if( v ) sqlite3VdbeAddOp0(v, OP_Expire); | |
| 98042 | + if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){ | |
| 98043 | + sqlite3VdbeAddOp0(v, OP_Expire); | |
| 98044 | + } | |
| 97817 | 98045 | } |
| 97818 | 98046 | |
| 97819 | 98047 | /* |
| 97820 | 98048 | ** Used to pass information from the analyzer reader through to the |
| 97821 | 98049 | ** callback routine. |
| @@ -97940,19 +98168,24 @@ | ||
| 97940 | 98168 | } |
| 97941 | 98169 | aiRowEst = pIndex->aiRowEst; |
| 97942 | 98170 | #endif |
| 97943 | 98171 | pIndex->bUnordered = 0; |
| 97944 | 98172 | decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); |
| 97945 | - if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0]; | |
| 98173 | + pIndex->hasStat1 = 1; | |
| 98174 | + if( pIndex->pPartIdxWhere==0 ){ | |
| 98175 | + pTable->nRowLogEst = pIndex->aiRowLogEst[0]; | |
| 98176 | + pTable->tabFlags |= TF_HasStat1; | |
| 98177 | + } | |
| 97946 | 98178 | }else{ |
| 97947 | 98179 | Index fakeIdx; |
| 97948 | 98180 | fakeIdx.szIdxRow = pTable->szTabRow; |
| 97949 | 98181 | #ifdef SQLITE_ENABLE_COSTMULT |
| 97950 | 98182 | fakeIdx.pTable = pTable; |
| 97951 | 98183 | #endif |
| 97952 | 98184 | decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); |
| 97953 | 98185 | pTable->szTabRow = fakeIdx.szIdxRow; |
| 98186 | + pTable->tabFlags |= TF_HasStat1; | |
| 97954 | 98187 | } |
| 97955 | 98188 | |
| 97956 | 98189 | return 0; |
| 97957 | 98190 | } |
| 97958 | 98191 | |
| @@ -98243,19 +98476,24 @@ | ||
| 98243 | 98476 | SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ |
| 98244 | 98477 | analysisInfo sInfo; |
| 98245 | 98478 | HashElem *i; |
| 98246 | 98479 | char *zSql; |
| 98247 | 98480 | int rc = SQLITE_OK; |
| 98481 | + Schema *pSchema = db->aDb[iDb].pSchema; | |
| 98248 | 98482 | |
| 98249 | 98483 | assert( iDb>=0 && iDb<db->nDb ); |
| 98250 | 98484 | assert( db->aDb[iDb].pBt!=0 ); |
| 98251 | 98485 | |
| 98252 | 98486 | /* Clear any prior statistics */ |
| 98253 | 98487 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 98254 | - for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ | |
| 98488 | + for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){ | |
| 98489 | + Table *pTab = sqliteHashData(i); | |
| 98490 | + pTab->tabFlags &= ~TF_HasStat1; | |
| 98491 | + } | |
| 98492 | + for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ | |
| 98255 | 98493 | Index *pIdx = sqliteHashData(i); |
| 98256 | - pIdx->aiRowLogEst[0] = 0; | |
| 98494 | + pIdx->hasStat1 = 0; | |
| 98257 | 98495 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 98258 | 98496 | sqlite3DeleteIndexSamples(db, pIdx); |
| 98259 | 98497 | pIdx->aSample = 0; |
| 98260 | 98498 | #endif |
| 98261 | 98499 | } |
| @@ -98274,23 +98512,23 @@ | ||
| 98274 | 98512 | } |
| 98275 | 98513 | } |
| 98276 | 98514 | |
| 98277 | 98515 | /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */ |
| 98278 | 98516 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 98279 | - for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ | |
| 98517 | + for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ | |
| 98280 | 98518 | Index *pIdx = sqliteHashData(i); |
| 98281 | - if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx); | |
| 98519 | + if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx); | |
| 98282 | 98520 | } |
| 98283 | 98521 | |
| 98284 | 98522 | /* Load the statistics from the sqlite_stat4 table. */ |
| 98285 | 98523 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 98286 | 98524 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 98287 | 98525 | db->lookaside.bDisable++; |
| 98288 | 98526 | rc = loadStat4(db, sInfo.zDatabase); |
| 98289 | 98527 | db->lookaside.bDisable--; |
| 98290 | 98528 | } |
| 98291 | - for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ | |
| 98529 | + for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ | |
| 98292 | 98530 | Index *pIdx = sqliteHashData(i); |
| 98293 | 98531 | sqlite3_free(pIdx->aiRowEst); |
| 98294 | 98532 | pIdx->aiRowEst = 0; |
| 98295 | 98533 | } |
| 98296 | 98534 | #endif |
| @@ -100271,10 +100509,11 @@ | ||
| 100271 | 100509 | SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ |
| 100272 | 100510 | Table *p; |
| 100273 | 100511 | p = pParse->pNewTable; |
| 100274 | 100512 | if( p==0 || NEVER(p->nCol<1) ) return; |
| 100275 | 100513 | p->aCol[p->nCol-1].notNull = (u8)onError; |
| 100514 | + p->tabFlags |= TF_HasNotNull; | |
| 100276 | 100515 | } |
| 100277 | 100516 | |
| 100278 | 100517 | /* |
| 100279 | 100518 | ** Scan the column type name zType (length nType) and return the |
| 100280 | 100519 | ** associated affinity type. |
| @@ -102609,10 +102848,13 @@ | ||
| 102609 | 102848 | /* 10, 9, 8, 7, 6 */ |
| 102610 | 102849 | LogEst aVal[] = { 33, 32, 30, 28, 26 }; |
| 102611 | 102850 | LogEst *a = pIdx->aiRowLogEst; |
| 102612 | 102851 | int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol); |
| 102613 | 102852 | int i; |
| 102853 | + | |
| 102854 | + /* Indexes with default row estimates should not have stat1 data */ | |
| 102855 | + assert( !pIdx->hasStat1 ); | |
| 102614 | 102856 | |
| 102615 | 102857 | /* Set the first entry (number of rows in the index) to the estimated |
| 102616 | 102858 | ** number of rows in the table, or half the number of rows in the table |
| 102617 | 102859 | ** for a partial index. But do not let the estimate drop below 10. */ |
| 102618 | 102860 | a[0] = pIdx->pTable->nRowLogEst; |
| @@ -109798,10 +110040,13 @@ | ||
| 109798 | 110040 | VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); |
| 109799 | 110041 | } |
| 109800 | 110042 | } |
| 109801 | 110043 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); |
| 109802 | 110044 | VdbeComment((v, "for %s", pIdx->zName)); |
| 110045 | +#ifdef SQLITE_ENABLE_NULL_TRIM | |
| 110046 | + if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable); | |
| 110047 | +#endif | |
| 109803 | 110048 | |
| 109804 | 110049 | /* In an UPDATE operation, if this index is the PRIMARY KEY index |
| 109805 | 110050 | ** of a WITHOUT ROWID table and there has been no change the |
| 109806 | 110051 | ** primary key, then no collision is possible. The collision detection |
| 109807 | 110052 | ** logic below can all be skipped. */ |
| @@ -109953,12 +110198,15 @@ | ||
| 109953 | 110198 | |
| 109954 | 110199 | /* Records with omitted columns are only allowed for schema format |
| 109955 | 110200 | ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ |
| 109956 | 110201 | if( pTab->pSchema->file_format<2 ) return; |
| 109957 | 110202 | |
| 109958 | - for(i=pTab->nCol; i>1 && pTab->aCol[i-1].pDflt==0; i--){} | |
| 109959 | - sqlite3VdbeChangeP5(v, i); | |
| 110203 | + for(i=pTab->nCol-1; i>0; i--){ | |
| 110204 | + if( pTab->aCol[i].pDflt!=0 ) break; | |
| 110205 | + if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; | |
| 110206 | + } | |
| 110207 | + sqlite3VdbeChangeP5(v, i+1); | |
| 109960 | 110208 | } |
| 109961 | 110209 | #endif |
| 109962 | 110210 | |
| 109963 | 110211 | /* |
| 109964 | 110212 | ** This routine generates code to finish the INSERT or UPDATE operation |
| @@ -110244,11 +110492,11 @@ | ||
| 110244 | 110492 | } |
| 110245 | 110493 | if( sqlite3TriggerList(pParse, pDest) ){ |
| 110246 | 110494 | return 0; /* tab1 must not have triggers */ |
| 110247 | 110495 | } |
| 110248 | 110496 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 110249 | - if( pDest->tabFlags & TF_Virtual ){ | |
| 110497 | + if( IsVirtual(pDest) ){ | |
| 110250 | 110498 | return 0; /* tab1 must not be a virtual table */ |
| 110251 | 110499 | } |
| 110252 | 110500 | #endif |
| 110253 | 110501 | if( onError==OE_Default ){ |
| 110254 | 110502 | if( pDest->iPKey>=0 ) onError = pDest->keyConf; |
| @@ -110306,11 +110554,11 @@ | ||
| 110306 | 110554 | } |
| 110307 | 110555 | if( HasRowid(pDest)!=HasRowid(pSrc) ){ |
| 110308 | 110556 | return 0; /* source and destination must both be WITHOUT ROWID or not */ |
| 110309 | 110557 | } |
| 110310 | 110558 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 110311 | - if( pSrc->tabFlags & TF_Virtual ){ | |
| 110559 | + if( IsVirtual(pSrc) ){ | |
| 110312 | 110560 | return 0; /* tab2 must not be a virtual table */ |
| 110313 | 110561 | } |
| 110314 | 110562 | #endif |
| 110315 | 110563 | if( pSrc->pSelect ){ |
| 110316 | 110564 | return 0; /* tab2 may not be a view */ |
| @@ -110603,11 +110851,11 @@ | ||
| 110603 | 110851 | /* Invoke the callback function if required */ |
| 110604 | 110852 | if( xCallback && (SQLITE_ROW==rc || |
| 110605 | 110853 | (SQLITE_DONE==rc && !callbackIsInit |
| 110606 | 110854 | && db->flags&SQLITE_NullCallback)) ){ |
| 110607 | 110855 | if( !callbackIsInit ){ |
| 110608 | - azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); | |
| 110856 | + azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*)); | |
| 110609 | 110857 | if( azCols==0 ){ |
| 110610 | 110858 | goto exec_out; |
| 110611 | 110859 | } |
| 110612 | 110860 | for(i=0; i<nCol; i++){ |
| 110613 | 110861 | azCols[i] = (char *)sqlite3_column_name(pStmt, i); |
| @@ -110624,10 +110872,11 @@ | ||
| 110624 | 110872 | if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 110625 | 110873 | sqlite3OomFault(db); |
| 110626 | 110874 | goto exec_out; |
| 110627 | 110875 | } |
| 110628 | 110876 | } |
| 110877 | + azVals[i] = 0; | |
| 110629 | 110878 | } |
| 110630 | 110879 | if( xCallback(pArg, nCol, azVals, azCols) ){ |
| 110631 | 110880 | /* EVIDENCE-OF: R-38229-40159 If the callback function to |
| 110632 | 110881 | ** sqlite3_exec() returns non-zero, then sqlite3_exec() will |
| 110633 | 110882 | ** return SQLITE_ABORT. */ |
| @@ -112094,15 +112343,15 @@ | ||
| 112094 | 112343 | #define PragTyp_JOURNAL_SIZE_LIMIT 20 |
| 112095 | 112344 | #define PragTyp_LOCK_PROXY_FILE 21 |
| 112096 | 112345 | #define PragTyp_LOCKING_MODE 22 |
| 112097 | 112346 | #define PragTyp_PAGE_COUNT 23 |
| 112098 | 112347 | #define PragTyp_MMAP_SIZE 24 |
| 112099 | -#define PragTyp_PAGE_SIZE 25 | |
| 112100 | -#define PragTyp_SECURE_DELETE 26 | |
| 112101 | -#define PragTyp_SHRINK_MEMORY 27 | |
| 112102 | -#define PragTyp_SOFT_HEAP_LIMIT 28 | |
| 112103 | -#define PragTyp_STATS 29 | |
| 112348 | +#define PragTyp_OPTIMIZE 25 | |
| 112349 | +#define PragTyp_PAGE_SIZE 26 | |
| 112350 | +#define PragTyp_SECURE_DELETE 27 | |
| 112351 | +#define PragTyp_SHRINK_MEMORY 28 | |
| 112352 | +#define PragTyp_SOFT_HEAP_LIMIT 29 | |
| 112104 | 112353 | #define PragTyp_SYNCHRONOUS 30 |
| 112105 | 112354 | #define PragTyp_TABLE_INFO 31 |
| 112106 | 112355 | #define PragTyp_TEMP_STORE 32 |
| 112107 | 112356 | #define PragTyp_TEMP_STORE_DIRECTORY 33 |
| 112108 | 112357 | #define PragTyp_THREADS 34 |
| @@ -112112,10 +112361,11 @@ | ||
| 112112 | 112361 | #define PragTyp_HEXKEY 38 |
| 112113 | 112362 | #define PragTyp_KEY 39 |
| 112114 | 112363 | #define PragTyp_REKEY 40 |
| 112115 | 112364 | #define PragTyp_LOCK_STATUS 41 |
| 112116 | 112365 | #define PragTyp_PARSER_TRACE 42 |
| 112366 | +#define PragTyp_STATS 43 | |
| 112117 | 112367 | |
| 112118 | 112368 | /* Property flags associated with various pragma. */ |
| 112119 | 112369 | #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ |
| 112120 | 112370 | #define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ |
| 112121 | 112371 | #define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ |
| @@ -112135,51 +112385,52 @@ | ||
| 112135 | 112385 | /* 2 */ "name", |
| 112136 | 112386 | /* 3 */ "type", |
| 112137 | 112387 | /* 4 */ "notnull", |
| 112138 | 112388 | /* 5 */ "dflt_value", |
| 112139 | 112389 | /* 6 */ "pk", |
| 112140 | - /* 7 */ "table", /* Used by: stats */ | |
| 112141 | - /* 8 */ "index", | |
| 112142 | - /* 9 */ "width", | |
| 112143 | - /* 10 */ "height", | |
| 112144 | - /* 11 */ "seqno", /* Used by: index_info */ | |
| 112145 | - /* 12 */ "cid", | |
| 112146 | - /* 13 */ "name", | |
| 112147 | - /* 14 */ "seqno", /* Used by: index_xinfo */ | |
| 112148 | - /* 15 */ "cid", | |
| 112149 | - /* 16 */ "name", | |
| 112150 | - /* 17 */ "desc", | |
| 112151 | - /* 18 */ "coll", | |
| 112152 | - /* 19 */ "key", | |
| 112153 | - /* 20 */ "seq", /* Used by: index_list */ | |
| 112154 | - /* 21 */ "name", | |
| 112155 | - /* 22 */ "unique", | |
| 112156 | - /* 23 */ "origin", | |
| 112157 | - /* 24 */ "partial", | |
| 112158 | - /* 25 */ "seq", /* Used by: database_list */ | |
| 112159 | - /* 26 */ "name", | |
| 112160 | - /* 27 */ "file", | |
| 112161 | - /* 28 */ "seq", /* Used by: collation_list */ | |
| 112162 | - /* 29 */ "name", | |
| 112163 | - /* 30 */ "id", /* Used by: foreign_key_list */ | |
| 112164 | - /* 31 */ "seq", | |
| 112165 | - /* 32 */ "table", | |
| 112166 | - /* 33 */ "from", | |
| 112167 | - /* 34 */ "to", | |
| 112168 | - /* 35 */ "on_update", | |
| 112169 | - /* 36 */ "on_delete", | |
| 112170 | - /* 37 */ "match", | |
| 112171 | - /* 38 */ "table", /* Used by: foreign_key_check */ | |
| 112172 | - /* 39 */ "rowid", | |
| 112173 | - /* 40 */ "parent", | |
| 112174 | - /* 41 */ "fkid", | |
| 112175 | - /* 42 */ "busy", /* Used by: wal_checkpoint */ | |
| 112176 | - /* 43 */ "log", | |
| 112177 | - /* 44 */ "checkpointed", | |
| 112178 | - /* 45 */ "timeout", /* Used by: busy_timeout */ | |
| 112179 | - /* 46 */ "database", /* Used by: lock_status */ | |
| 112180 | - /* 47 */ "status", | |
| 112390 | + /* 7 */ "tbl", /* Used by: stats */ | |
| 112391 | + /* 8 */ "idx", | |
| 112392 | + /* 9 */ "wdth", | |
| 112393 | + /* 10 */ "hght", | |
| 112394 | + /* 11 */ "flgs", | |
| 112395 | + /* 12 */ "seqno", /* Used by: index_info */ | |
| 112396 | + /* 13 */ "cid", | |
| 112397 | + /* 14 */ "name", | |
| 112398 | + /* 15 */ "seqno", /* Used by: index_xinfo */ | |
| 112399 | + /* 16 */ "cid", | |
| 112400 | + /* 17 */ "name", | |
| 112401 | + /* 18 */ "desc", | |
| 112402 | + /* 19 */ "coll", | |
| 112403 | + /* 20 */ "key", | |
| 112404 | + /* 21 */ "seq", /* Used by: index_list */ | |
| 112405 | + /* 22 */ "name", | |
| 112406 | + /* 23 */ "unique", | |
| 112407 | + /* 24 */ "origin", | |
| 112408 | + /* 25 */ "partial", | |
| 112409 | + /* 26 */ "seq", /* Used by: database_list */ | |
| 112410 | + /* 27 */ "name", | |
| 112411 | + /* 28 */ "file", | |
| 112412 | + /* 29 */ "seq", /* Used by: collation_list */ | |
| 112413 | + /* 30 */ "name", | |
| 112414 | + /* 31 */ "id", /* Used by: foreign_key_list */ | |
| 112415 | + /* 32 */ "seq", | |
| 112416 | + /* 33 */ "table", | |
| 112417 | + /* 34 */ "from", | |
| 112418 | + /* 35 */ "to", | |
| 112419 | + /* 36 */ "on_update", | |
| 112420 | + /* 37 */ "on_delete", | |
| 112421 | + /* 38 */ "match", | |
| 112422 | + /* 39 */ "table", /* Used by: foreign_key_check */ | |
| 112423 | + /* 40 */ "rowid", | |
| 112424 | + /* 41 */ "parent", | |
| 112425 | + /* 42 */ "fkid", | |
| 112426 | + /* 43 */ "busy", /* Used by: wal_checkpoint */ | |
| 112427 | + /* 44 */ "log", | |
| 112428 | + /* 45 */ "checkpointed", | |
| 112429 | + /* 46 */ "timeout", /* Used by: busy_timeout */ | |
| 112430 | + /* 47 */ "database", /* Used by: lock_status */ | |
| 112431 | + /* 48 */ "status", | |
| 112181 | 112432 | }; |
| 112182 | 112433 | |
| 112183 | 112434 | /* Definitions of all built-in pragmas */ |
| 112184 | 112435 | typedef struct PragmaName { |
| 112185 | 112436 | const char *const zName; /* Name of pragma */ |
| @@ -112221,11 +112472,11 @@ | ||
| 112221 | 112472 | #endif |
| 112222 | 112473 | #endif |
| 112223 | 112474 | {/* zName: */ "busy_timeout", |
| 112224 | 112475 | /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, |
| 112225 | 112476 | /* ePragFlg: */ PragFlg_Result0, |
| 112226 | - /* ColNames: */ 45, 1, | |
| 112477 | + /* ColNames: */ 46, 1, | |
| 112227 | 112478 | /* iArg: */ 0 }, |
| 112228 | 112479 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112229 | 112480 | {/* zName: */ "cache_size", |
| 112230 | 112481 | /* ePragTyp: */ PragTyp_CACHE_SIZE, |
| 112231 | 112482 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
| @@ -112258,11 +112509,11 @@ | ||
| 112258 | 112509 | #endif |
| 112259 | 112510 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112260 | 112511 | {/* zName: */ "collation_list", |
| 112261 | 112512 | /* ePragTyp: */ PragTyp_COLLATION_LIST, |
| 112262 | 112513 | /* ePragFlg: */ PragFlg_Result0, |
| 112263 | - /* ColNames: */ 28, 2, | |
| 112514 | + /* ColNames: */ 29, 2, | |
| 112264 | 112515 | /* iArg: */ 0 }, |
| 112265 | 112516 | #endif |
| 112266 | 112517 | #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) |
| 112267 | 112518 | {/* zName: */ "compile_options", |
| 112268 | 112519 | /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, |
| @@ -112293,11 +112544,11 @@ | ||
| 112293 | 112544 | #endif |
| 112294 | 112545 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112295 | 112546 | {/* zName: */ "database_list", |
| 112296 | 112547 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 112297 | 112548 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, |
| 112298 | - /* ColNames: */ 25, 3, | |
| 112549 | + /* ColNames: */ 26, 3, | |
| 112299 | 112550 | /* iArg: */ 0 }, |
| 112300 | 112551 | #endif |
| 112301 | 112552 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
| 112302 | 112553 | {/* zName: */ "default_cache_size", |
| 112303 | 112554 | /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, |
| @@ -112330,18 +112581,18 @@ | ||
| 112330 | 112581 | #endif |
| 112331 | 112582 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 112332 | 112583 | {/* zName: */ "foreign_key_check", |
| 112333 | 112584 | /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, |
| 112334 | 112585 | /* ePragFlg: */ PragFlg_NeedSchema, |
| 112335 | - /* ColNames: */ 38, 4, | |
| 112586 | + /* ColNames: */ 39, 4, | |
| 112336 | 112587 | /* iArg: */ 0 }, |
| 112337 | 112588 | #endif |
| 112338 | 112589 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) |
| 112339 | 112590 | {/* zName: */ "foreign_key_list", |
| 112340 | 112591 | /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, |
| 112341 | 112592 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112342 | - /* ColNames: */ 30, 8, | |
| 112593 | + /* ColNames: */ 31, 8, | |
| 112343 | 112594 | /* iArg: */ 0 }, |
| 112344 | 112595 | #endif |
| 112345 | 112596 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 112346 | 112597 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 112347 | 112598 | {/* zName: */ "foreign_keys", |
| @@ -112400,21 +112651,21 @@ | ||
| 112400 | 112651 | #endif |
| 112401 | 112652 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112402 | 112653 | {/* zName: */ "index_info", |
| 112403 | 112654 | /* ePragTyp: */ PragTyp_INDEX_INFO, |
| 112404 | 112655 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112405 | - /* ColNames: */ 11, 3, | |
| 112656 | + /* ColNames: */ 12, 3, | |
| 112406 | 112657 | /* iArg: */ 0 }, |
| 112407 | 112658 | {/* zName: */ "index_list", |
| 112408 | 112659 | /* ePragTyp: */ PragTyp_INDEX_LIST, |
| 112409 | 112660 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112410 | - /* ColNames: */ 20, 5, | |
| 112661 | + /* ColNames: */ 21, 5, | |
| 112411 | 112662 | /* iArg: */ 0 }, |
| 112412 | 112663 | {/* zName: */ "index_xinfo", |
| 112413 | 112664 | /* ePragTyp: */ PragTyp_INDEX_INFO, |
| 112414 | 112665 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112415 | - /* ColNames: */ 14, 6, | |
| 112666 | + /* ColNames: */ 15, 6, | |
| 112416 | 112667 | /* iArg: */ 1 }, |
| 112417 | 112668 | #endif |
| 112418 | 112669 | #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) |
| 112419 | 112670 | {/* zName: */ "integrity_check", |
| 112420 | 112671 | /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, |
| @@ -112457,11 +112708,11 @@ | ||
| 112457 | 112708 | #endif |
| 112458 | 112709 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| 112459 | 112710 | {/* zName: */ "lock_status", |
| 112460 | 112711 | /* ePragTyp: */ PragTyp_LOCK_STATUS, |
| 112461 | 112712 | /* ePragFlg: */ PragFlg_Result0, |
| 112462 | - /* ColNames: */ 46, 2, | |
| 112713 | + /* ColNames: */ 47, 2, | |
| 112463 | 112714 | /* iArg: */ 0 }, |
| 112464 | 112715 | #endif |
| 112465 | 112716 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112466 | 112717 | {/* zName: */ "locking_mode", |
| 112467 | 112718 | /* ePragTyp: */ PragTyp_LOCKING_MODE, |
| @@ -112476,10 +112727,17 @@ | ||
| 112476 | 112727 | {/* zName: */ "mmap_size", |
| 112477 | 112728 | /* ePragTyp: */ PragTyp_MMAP_SIZE, |
| 112478 | 112729 | /* ePragFlg: */ 0, |
| 112479 | 112730 | /* ColNames: */ 0, 0, |
| 112480 | 112731 | /* iArg: */ 0 }, |
| 112732 | +#endif | |
| 112733 | + {/* zName: */ "optimize", | |
| 112734 | + /* ePragTyp: */ PragTyp_OPTIMIZE, | |
| 112735 | + /* ePragFlg: */ PragFlg_Result1, | |
| 112736 | + /* ColNames: */ 0, 0, | |
| 112737 | + /* iArg: */ 0 }, | |
| 112738 | +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) | |
| 112481 | 112739 | {/* zName: */ "page_count", |
| 112482 | 112740 | /* ePragTyp: */ PragTyp_PAGE_COUNT, |
| 112483 | 112741 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
| 112484 | 112742 | /* ColNames: */ 0, 0, |
| 112485 | 112743 | /* iArg: */ 0 }, |
| @@ -112574,15 +112832,15 @@ | ||
| 112574 | 112832 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
| 112575 | 112833 | /* ColNames: */ 0, 0, |
| 112576 | 112834 | /* iArg: */ SQLITE_SqlTrace }, |
| 112577 | 112835 | #endif |
| 112578 | 112836 | #endif |
| 112579 | -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) | |
| 112837 | +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG) | |
| 112580 | 112838 | {/* zName: */ "stats", |
| 112581 | 112839 | /* ePragTyp: */ PragTyp_STATS, |
| 112582 | 112840 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
| 112583 | - /* ColNames: */ 7, 4, | |
| 112841 | + /* ColNames: */ 7, 5, | |
| 112584 | 112842 | /* iArg: */ 0 }, |
| 112585 | 112843 | #endif |
| 112586 | 112844 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112587 | 112845 | {/* zName: */ "synchronous", |
| 112588 | 112846 | /* ePragTyp: */ PragTyp_SYNCHRONOUS, |
| @@ -112657,11 +112915,11 @@ | ||
| 112657 | 112915 | /* ColNames: */ 0, 0, |
| 112658 | 112916 | /* iArg: */ 0 }, |
| 112659 | 112917 | {/* zName: */ "wal_checkpoint", |
| 112660 | 112918 | /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, |
| 112661 | 112919 | /* ePragFlg: */ PragFlg_NeedSchema, |
| 112662 | - /* ColNames: */ 42, 3, | |
| 112920 | + /* ColNames: */ 43, 3, | |
| 112663 | 112921 | /* iArg: */ 0 }, |
| 112664 | 112922 | #endif |
| 112665 | 112923 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 112666 | 112924 | {/* zName: */ "writable_schema", |
| 112667 | 112925 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -112668,11 +112926,11 @@ | ||
| 112668 | 112926 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
| 112669 | 112927 | /* ColNames: */ 0, 0, |
| 112670 | 112928 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 112671 | 112929 | #endif |
| 112672 | 112930 | }; |
| 112673 | -/* Number of pragmas: 60 on by default, 73 total. */ | |
| 112931 | +/* Number of pragmas: 60 on by default, 74 total. */ | |
| 112674 | 112932 | |
| 112675 | 112933 | /************** End of pragma.h **********************************************/ |
| 112676 | 112934 | /************** Continuing where we left off in pragma.c *********************/ |
| 112677 | 112935 | |
| 112678 | 112936 | /* |
| @@ -112937,10 +113195,26 @@ | ||
| 112937 | 113195 | lwr = mid + 1; |
| 112938 | 113196 | } |
| 112939 | 113197 | } |
| 112940 | 113198 | return lwr>upr ? 0 : &aPragmaName[mid]; |
| 112941 | 113199 | } |
| 113200 | + | |
| 113201 | +/* | |
| 113202 | +** Helper subroutine for PRAGMA integrity_check: | |
| 113203 | +** | |
| 113204 | +** Generate code to output a single-column result row with the result | |
| 113205 | +** held in register regResult. Decrement the result count and halt if | |
| 113206 | +** the maximum number of result rows have been issued. | |
| 113207 | +*/ | |
| 113208 | +static int integrityCheckResultRow(Vdbe *v, int regResult){ | |
| 113209 | + int addr; | |
| 113210 | + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1); | |
| 113211 | + addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); | |
| 113212 | + VdbeCoverage(v); | |
| 113213 | + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); | |
| 113214 | + return addr; | |
| 113215 | +} | |
| 112942 | 113216 | |
| 112943 | 113217 | /* |
| 112944 | 113218 | ** Process a pragma statement. |
| 112945 | 113219 | ** |
| 112946 | 113220 | ** Pragmas are of this form: |
| @@ -113741,33 +114015,37 @@ | ||
| 113741 | 114015 | } |
| 113742 | 114016 | } |
| 113743 | 114017 | } |
| 113744 | 114018 | break; |
| 113745 | 114019 | |
| 114020 | +#ifdef SQLITE_DEBUG | |
| 113746 | 114021 | case PragTyp_STATS: { |
| 113747 | 114022 | Index *pIdx; |
| 113748 | 114023 | HashElem *i; |
| 113749 | - pParse->nMem = 4; | |
| 114024 | + pParse->nMem = 5; | |
| 113750 | 114025 | sqlite3CodeVerifySchema(pParse, iDb); |
| 113751 | 114026 | for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ |
| 113752 | 114027 | Table *pTab = sqliteHashData(i); |
| 113753 | - sqlite3VdbeMultiLoad(v, 1, "ssii", | |
| 114028 | + sqlite3VdbeMultiLoad(v, 1, "ssiii", | |
| 113754 | 114029 | pTab->zName, |
| 113755 | 114030 | 0, |
| 113756 | 114031 | pTab->szTabRow, |
| 113757 | - pTab->nRowLogEst); | |
| 113758 | - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); | |
| 114032 | + pTab->nRowLogEst, | |
| 114033 | + pTab->tabFlags); | |
| 114034 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); | |
| 113759 | 114035 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 113760 | - sqlite3VdbeMultiLoad(v, 2, "sii", | |
| 114036 | + sqlite3VdbeMultiLoad(v, 2, "siii", | |
| 113761 | 114037 | pIdx->zName, |
| 113762 | 114038 | pIdx->szIdxRow, |
| 113763 | - pIdx->aiRowLogEst[0]); | |
| 113764 | - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); | |
| 114039 | + pIdx->aiRowLogEst[0], | |
| 114040 | + pIdx->hasStat1); | |
| 114041 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); | |
| 113765 | 114042 | } |
| 113766 | 114043 | } |
| 113767 | 114044 | } |
| 113768 | 114045 | break; |
| 114046 | +#endif | |
| 113769 | 114047 | |
| 113770 | 114048 | case PragTyp_INDEX_INFO: if( zRight ){ |
| 113771 | 114049 | Index *pIdx; |
| 113772 | 114050 | Table *pTab; |
| 113773 | 114051 | pIdx = sqlite3FindIndex(db, zRight, zDb); |
| @@ -114020,13 +114298,21 @@ | ||
| 114020 | 114298 | #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
| 114021 | 114299 | # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 |
| 114022 | 114300 | #endif |
| 114023 | 114301 | |
| 114024 | 114302 | #ifndef SQLITE_OMIT_INTEGRITY_CHECK |
| 114025 | - /* Pragma "quick_check" is reduced version of | |
| 114303 | + /* PRAGMA integrity_check | |
| 114304 | + ** PRAGMA integrity_check(N) | |
| 114305 | + ** PRAGMA quick_check | |
| 114306 | + ** PRAGMA quick_check(N) | |
| 114307 | + ** | |
| 114308 | + ** Verify the integrity of the database. | |
| 114309 | + ** | |
| 114310 | + ** The "quick_check" is reduced version of | |
| 114026 | 114311 | ** integrity_check designed to detect most database corruption |
| 114027 | - ** without most of the overhead of a full integrity-check. | |
| 114312 | + ** without the overhead of cross-checking indexes. Quick_check | |
| 114313 | + ** is linear time wherease integrity_check is O(NlogN). | |
| 114028 | 114314 | */ |
| 114029 | 114315 | case PragTyp_INTEGRITY_CHECK: { |
| 114030 | 114316 | int i, j, addr, mxErr; |
| 114031 | 114317 | |
| 114032 | 114318 | int isQuick = (sqlite3Tolower(zLeft[0])=='q'); |
| @@ -114053,11 +114339,11 @@ | ||
| 114053 | 114339 | sqlite3GetInt32(zRight, &mxErr); |
| 114054 | 114340 | if( mxErr<=0 ){ |
| 114055 | 114341 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 114056 | 114342 | } |
| 114057 | 114343 | } |
| 114058 | - sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ | |
| 114344 | + sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */ | |
| 114059 | 114345 | |
| 114060 | 114346 | /* Do an integrity check on each database file */ |
| 114061 | 114347 | for(i=0; i<db->nDb; i++){ |
| 114062 | 114348 | HashElem *x; |
| 114063 | 114349 | Hash *pTbls; |
| @@ -114068,14 +114354,10 @@ | ||
| 114068 | 114354 | |
| 114069 | 114355 | if( OMIT_TEMPDB && i==1 ) continue; |
| 114070 | 114356 | if( iDb>=0 && i!=iDb ) continue; |
| 114071 | 114357 | |
| 114072 | 114358 | sqlite3CodeVerifySchema(pParse, i); |
| 114073 | - addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ | |
| 114074 | - VdbeCoverage(v); | |
| 114075 | - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); | |
| 114076 | - sqlite3VdbeJumpHere(v, addr); | |
| 114077 | 114359 | |
| 114078 | 114360 | /* Do an integrity check of the B-Tree |
| 114079 | 114361 | ** |
| 114080 | 114362 | ** Begin by finding the root pages numbers |
| 114081 | 114363 | ** for all tables and indices in the database. |
| @@ -114111,29 +114393,30 @@ | ||
| 114111 | 114393 | sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, |
| 114112 | 114394 | sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), |
| 114113 | 114395 | P4_DYNAMIC); |
| 114114 | 114396 | sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); |
| 114115 | 114397 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); |
| 114116 | - sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); | |
| 114398 | + integrityCheckResultRow(v, 2); | |
| 114117 | 114399 | sqlite3VdbeJumpHere(v, addr); |
| 114118 | 114400 | |
| 114119 | 114401 | /* Make sure all the indices are constructed correctly. |
| 114120 | 114402 | */ |
| 114121 | - for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ | |
| 114403 | + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ | |
| 114122 | 114404 | Table *pTab = sqliteHashData(x); |
| 114123 | 114405 | Index *pIdx, *pPk; |
| 114124 | 114406 | Index *pPrior = 0; |
| 114125 | 114407 | int loopTop; |
| 114126 | 114408 | int iDataCur, iIdxCur; |
| 114127 | 114409 | int r1 = -1; |
| 114128 | 114410 | |
| 114129 | - if( pTab->pIndex==0 ) continue; | |
| 114411 | + if( pTab->pCheck==0 | |
| 114412 | + && (pTab->tabFlags & TF_HasNotNull)==0 | |
| 114413 | + && (pTab->pIndex==0 || isQuick) | |
| 114414 | + ){ | |
| 114415 | + continue; /* No additional checks needed for this table */ | |
| 114416 | + } | |
| 114130 | 114417 | pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
| 114131 | - addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ | |
| 114132 | - VdbeCoverage(v); | |
| 114133 | - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); | |
| 114134 | - sqlite3VdbeJumpHere(v, addr); | |
| 114135 | 114418 | sqlite3ExprCacheClear(pParse); |
| 114136 | 114419 | sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, |
| 114137 | 114420 | 1, 0, &iDataCur, &iIdxCur); |
| 114138 | 114421 | sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); |
| 114139 | 114422 | for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
| @@ -114144,28 +114427,46 @@ | ||
| 114144 | 114427 | sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); |
| 114145 | 114428 | loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); |
| 114146 | 114429 | /* Verify that all NOT NULL columns really are NOT NULL */ |
| 114147 | 114430 | for(j=0; j<pTab->nCol; j++){ |
| 114148 | 114431 | char *zErr; |
| 114149 | - int jmp2, jmp3; | |
| 114432 | + int jmp2; | |
| 114150 | 114433 | if( j==pTab->iPKey ) continue; |
| 114151 | 114434 | if( pTab->aCol[j].notNull==0 ) continue; |
| 114152 | 114435 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); |
| 114153 | 114436 | sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); |
| 114154 | 114437 | jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); |
| 114155 | - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ | |
| 114156 | 114438 | zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, |
| 114157 | 114439 | pTab->aCol[j].zName); |
| 114158 | 114440 | sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); |
| 114159 | - sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); | |
| 114160 | - jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); | |
| 114161 | - sqlite3VdbeAddOp0(v, OP_Halt); | |
| 114441 | + integrityCheckResultRow(v, 3); | |
| 114162 | 114442 | sqlite3VdbeJumpHere(v, jmp2); |
| 114163 | - sqlite3VdbeJumpHere(v, jmp3); | |
| 114443 | + } | |
| 114444 | + /* Verify CHECK constraints */ | |
| 114445 | + if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ | |
| 114446 | + int addrCkFault = sqlite3VdbeMakeLabel(v); | |
| 114447 | + int addrCkOk = sqlite3VdbeMakeLabel(v); | |
| 114448 | + ExprList *pCheck = pTab->pCheck; | |
| 114449 | + char *zErr; | |
| 114450 | + int k; | |
| 114451 | + pParse->iSelfTab = iDataCur; | |
| 114452 | + sqlite3ExprCachePush(pParse); | |
| 114453 | + for(k=pCheck->nExpr-1; k>0; k--){ | |
| 114454 | + sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); | |
| 114455 | + } | |
| 114456 | + sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, | |
| 114457 | + SQLITE_JUMPIFNULL); | |
| 114458 | + sqlite3VdbeResolveLabel(v, addrCkFault); | |
| 114459 | + zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s", | |
| 114460 | + pTab->zName); | |
| 114461 | + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); | |
| 114462 | + integrityCheckResultRow(v, 3); | |
| 114463 | + sqlite3VdbeResolveLabel(v, addrCkOk); | |
| 114464 | + sqlite3ExprCachePop(pParse); | |
| 114164 | 114465 | } |
| 114165 | 114466 | /* Validate index entries for the current row */ |
| 114166 | - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ | |
| 114467 | + for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){ | |
| 114167 | 114468 | int jmp2, jmp3, jmp4, jmp5; |
| 114168 | 114469 | int ckUniq = sqlite3VdbeMakeLabel(v); |
| 114169 | 114470 | if( pPk==pIdx ) continue; |
| 114170 | 114471 | r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, |
| 114171 | 114472 | pPrior, r1); |
| @@ -114172,20 +114473,17 @@ | ||
| 114172 | 114473 | pPrior = pIdx; |
| 114173 | 114474 | sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ |
| 114174 | 114475 | /* Verify that an index entry exists for the current table row */ |
| 114175 | 114476 | jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, |
| 114176 | 114477 | pIdx->nColumn); VdbeCoverage(v); |
| 114177 | - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ | |
| 114178 | 114478 | sqlite3VdbeLoadString(v, 3, "row "); |
| 114179 | 114479 | sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); |
| 114180 | 114480 | sqlite3VdbeLoadString(v, 4, " missing from index "); |
| 114181 | 114481 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
| 114182 | 114482 | jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); |
| 114183 | 114483 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
| 114184 | - sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); | |
| 114185 | - jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); | |
| 114186 | - sqlite3VdbeAddOp0(v, OP_Halt); | |
| 114484 | + jmp4 = integrityCheckResultRow(v, 3); | |
| 114187 | 114485 | sqlite3VdbeJumpHere(v, jmp2); |
| 114188 | 114486 | /* For UNIQUE indexes, verify that only one entry exists with the |
| 114189 | 114487 | ** current key. The entry is unique if (1) any column is NULL |
| 114190 | 114488 | ** or (2) the next entry has a different key */ |
| 114191 | 114489 | if( IsUniqueIndex(pIdx) ){ |
| @@ -114202,11 +114500,10 @@ | ||
| 114202 | 114500 | jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
| 114203 | 114501 | sqlite3VdbeGoto(v, uniqOk); |
| 114204 | 114502 | sqlite3VdbeJumpHere(v, jmp6); |
| 114205 | 114503 | sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, |
| 114206 | 114504 | pIdx->nKeyCol); VdbeCoverage(v); |
| 114207 | - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ | |
| 114208 | 114505 | sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); |
| 114209 | 114506 | sqlite3VdbeGoto(v, jmp5); |
| 114210 | 114507 | sqlite3VdbeResolveLabel(v, uniqOk); |
| 114211 | 114508 | } |
| 114212 | 114509 | sqlite3VdbeJumpHere(v, jmp4); |
| @@ -114213,40 +114510,39 @@ | ||
| 114213 | 114510 | sqlite3ResolvePartIdxLabel(pParse, jmp3); |
| 114214 | 114511 | } |
| 114215 | 114512 | sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); |
| 114216 | 114513 | sqlite3VdbeJumpHere(v, loopTop-1); |
| 114217 | 114514 | #ifndef SQLITE_OMIT_BTREECOUNT |
| 114218 | - sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); | |
| 114219 | - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ | |
| 114220 | - if( pPk==pIdx ) continue; | |
| 114221 | - addr = sqlite3VdbeCurrentAddr(v); | |
| 114222 | - sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); | |
| 114223 | - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); | |
| 114224 | - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); | |
| 114225 | - sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); | |
| 114226 | - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); | |
| 114227 | - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); | |
| 114228 | - sqlite3VdbeLoadString(v, 3, pIdx->zName); | |
| 114229 | - sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); | |
| 114230 | - sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1); | |
| 114515 | + if( !isQuick ){ | |
| 114516 | + sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); | |
| 114517 | + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ | |
| 114518 | + if( pPk==pIdx ) continue; | |
| 114519 | + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); | |
| 114520 | + addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v); | |
| 114521 | + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); | |
| 114522 | + sqlite3VdbeLoadString(v, 3, pIdx->zName); | |
| 114523 | + sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); | |
| 114524 | + integrityCheckResultRow(v, 7); | |
| 114525 | + sqlite3VdbeJumpHere(v, addr); | |
| 114526 | + } | |
| 114231 | 114527 | } |
| 114232 | 114528 | #endif /* SQLITE_OMIT_BTREECOUNT */ |
| 114233 | 114529 | } |
| 114234 | 114530 | } |
| 114235 | 114531 | { |
| 114236 | 114532 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 114237 | 114533 | static const VdbeOpList endCode[] = { |
| 114238 | 114534 | { OP_AddImm, 1, 0, 0}, /* 0 */ |
| 114239 | - { OP_If, 1, 4, 0}, /* 1 */ | |
| 114535 | + { OP_IfNotZero, 1, 4, 0}, /* 1 */ | |
| 114240 | 114536 | { OP_String8, 0, 3, 0}, /* 2 */ |
| 114241 | 114537 | { OP_ResultRow, 3, 1, 0}, /* 3 */ |
| 114242 | 114538 | }; |
| 114243 | 114539 | VdbeOp *aOp; |
| 114244 | 114540 | |
| 114245 | 114541 | aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
| 114246 | 114542 | if( aOp ){ |
| 114247 | - aOp[0].p2 = -mxErr; | |
| 114543 | + aOp[0].p2 = 1-mxErr; | |
| 114248 | 114544 | aOp[2].p4type = P4_STATIC; |
| 114249 | 114545 | aOp[2].p4.z = "ok"; |
| 114250 | 114546 | } |
| 114251 | 114547 | } |
| 114252 | 114548 | } |
| @@ -114466,10 +114762,122 @@ | ||
| 114466 | 114762 | */ |
| 114467 | 114763 | case PragTyp_SHRINK_MEMORY: { |
| 114468 | 114764 | sqlite3_db_release_memory(db); |
| 114469 | 114765 | break; |
| 114470 | 114766 | } |
| 114767 | + | |
| 114768 | + /* | |
| 114769 | + ** PRAGMA optimize | |
| 114770 | + ** PRAGMA optimize(MASK) | |
| 114771 | + ** PRAGMA schema.optimize | |
| 114772 | + ** PRAGMA schema.optimize(MASK) | |
| 114773 | + ** | |
| 114774 | + ** Attempt to optimize the database. All schemas are optimized in the first | |
| 114775 | + ** two forms, and only the specified schema is optimized in the latter two. | |
| 114776 | + ** | |
| 114777 | + ** The details of optimizations performed by this pragma are expected | |
| 114778 | + ** to change and improve over time. Applications should anticipate that | |
| 114779 | + ** this pragma will perform new optimizations in future releases. | |
| 114780 | + ** | |
| 114781 | + ** The optional argument is a bitmask of optimizations to perform: | |
| 114782 | + ** | |
| 114783 | + ** 0x0001 Debugging mode. Do not actually perform any optimizations | |
| 114784 | + ** but instead return one line of text for each optimization | |
| 114785 | + ** that would have been done. Off by default. | |
| 114786 | + ** | |
| 114787 | + ** 0x0002 Run ANALYZE on tables that might benefit. On by default. | |
| 114788 | + ** See below for additional information. | |
| 114789 | + ** | |
| 114790 | + ** 0x0004 (Not yet implemented) Record usage and performance | |
| 114791 | + ** information from the current session in the | |
| 114792 | + ** database file so that it will be available to "optimize" | |
| 114793 | + ** pragmas run by future database connections. | |
| 114794 | + ** | |
| 114795 | + ** 0x0008 (Not yet implemented) Create indexes that might have | |
| 114796 | + ** been helpful to recent queries | |
| 114797 | + ** | |
| 114798 | + ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all ** of the optimizations listed above except Debug Mode, including new | |
| 114799 | + ** optimizations that have not yet been invented. If new optimizations are | |
| 114800 | + ** ever added that should be off by default, those off-by-default | |
| 114801 | + ** optimizations will have bitmasks of 0x10000 or larger. | |
| 114802 | + ** | |
| 114803 | + ** DETERMINATION OF WHEN TO RUN ANALYZE | |
| 114804 | + ** | |
| 114805 | + ** In the current implementation, a table is analyzed if only if all of | |
| 114806 | + ** the following are true: | |
| 114807 | + ** | |
| 114808 | + ** (1) MASK bit 0x02 is set. | |
| 114809 | + ** | |
| 114810 | + ** (2) The query planner used sqlite_stat1-style statistics for one or | |
| 114811 | + ** more indexes of the table at some point during the lifetime of | |
| 114812 | + ** the current connection. | |
| 114813 | + ** | |
| 114814 | + ** (3) One or more indexes of the table are currently unanalyzed OR | |
| 114815 | + ** the number of rows in the table has increased by 25 times or more | |
| 114816 | + ** since the last time ANALYZE was run. | |
| 114817 | + ** | |
| 114818 | + ** The rules for when tables are analyzed are likely to change in | |
| 114819 | + ** future releases. | |
| 114820 | + */ | |
| 114821 | + case PragTyp_OPTIMIZE: { | |
| 114822 | + int iDbLast; /* Loop termination point for the schema loop */ | |
| 114823 | + int iTabCur; /* Cursor for a table whose size needs checking */ | |
| 114824 | + HashElem *k; /* Loop over tables of a schema */ | |
| 114825 | + Schema *pSchema; /* The current schema */ | |
| 114826 | + Table *pTab; /* A table in the schema */ | |
| 114827 | + Index *pIdx; /* An index of the table */ | |
| 114828 | + LogEst szThreshold; /* Size threshold above which reanalysis is needd */ | |
| 114829 | + char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ | |
| 114830 | + u32 opMask; /* Mask of operations to perform */ | |
| 114831 | + | |
| 114832 | + if( zRight ){ | |
| 114833 | + opMask = (u32)sqlite3Atoi(zRight); | |
| 114834 | + if( (opMask & 0x02)==0 ) break; | |
| 114835 | + }else{ | |
| 114836 | + opMask = 0xfffe; | |
| 114837 | + } | |
| 114838 | + iTabCur = pParse->nTab++; | |
| 114839 | + for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){ | |
| 114840 | + if( iDb==1 ) continue; | |
| 114841 | + sqlite3CodeVerifySchema(pParse, iDb); | |
| 114842 | + pSchema = db->aDb[iDb].pSchema; | |
| 114843 | + for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ | |
| 114844 | + pTab = (Table*)sqliteHashData(k); | |
| 114845 | + | |
| 114846 | + /* If table pTab has not been used in a way that would benefit from | |
| 114847 | + ** having analysis statistics during the current session, then skip it. | |
| 114848 | + ** This also has the effect of skipping virtual tables and views */ | |
| 114849 | + if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue; | |
| 114850 | + | |
| 114851 | + /* Reanalyze if the table is 25 times larger than the last analysis */ | |
| 114852 | + szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 ); | |
| 114853 | + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | |
| 114854 | + if( !pIdx->hasStat1 ){ | |
| 114855 | + szThreshold = 0; /* Always analyze if any index lacks statistics */ | |
| 114856 | + break; | |
| 114857 | + } | |
| 114858 | + } | |
| 114859 | + if( szThreshold ){ | |
| 114860 | + sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); | |
| 114861 | + sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur, | |
| 114862 | + sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold); | |
| 114863 | + VdbeCoverage(v); | |
| 114864 | + } | |
| 114865 | + zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"", | |
| 114866 | + db->aDb[iDb].zDbSName, pTab->zName); | |
| 114867 | + if( opMask & 0x01 ){ | |
| 114868 | + int r1 = sqlite3GetTempReg(pParse); | |
| 114869 | + sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC); | |
| 114870 | + sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1); | |
| 114871 | + }else{ | |
| 114872 | + sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC); | |
| 114873 | + } | |
| 114874 | + } | |
| 114875 | + } | |
| 114876 | + sqlite3VdbeAddOp0(v, OP_Expire); | |
| 114877 | + break; | |
| 114878 | + } | |
| 114471 | 114879 | |
| 114472 | 114880 | /* |
| 114473 | 114881 | ** PRAGMA busy_timeout |
| 114474 | 114882 | ** PRAGMA busy_timeout = N |
| 114475 | 114883 | ** |
| @@ -123782,12 +124190,29 @@ | ||
| 123782 | 124190 | ** transient would cause the database file to appear to be deleted |
| 123783 | 124191 | ** following reboot. |
| 123784 | 124192 | */ |
| 123785 | 124193 | SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ |
| 123786 | 124194 | Vdbe *v = sqlite3GetVdbe(pParse); |
| 123787 | - int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0; | |
| 123788 | - if( v && (iDb>=2 || iDb==0) ){ | |
| 124195 | + int iDb = 0; | |
| 124196 | + if( v==0 ) return; | |
| 124197 | + if( pNm ){ | |
| 124198 | +#ifndef SQLITE_BUG_COMPATIBLE_20160819 | |
| 124199 | + /* Default behavior: Report an error if the argument to VACUUM is | |
| 124200 | + ** not recognized */ | |
| 124201 | + iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm); | |
| 124202 | + if( iDb<0 ) return; | |
| 124203 | +#else | |
| 124204 | + /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments | |
| 124205 | + ** to VACUUM are silently ignored. This is a back-out of a bug fix that | |
| 124206 | + ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270). | |
| 124207 | + ** The buggy behavior is required for binary compatibility with some | |
| 124208 | + ** legacy applications. */ | |
| 124209 | + iDb = sqlite3FindDb(pParse->db, pNm); | |
| 124210 | + if( iDb<0 ) iDb = 0; | |
| 124211 | +#endif | |
| 124212 | + } | |
| 124213 | + if( iDb!=1 ){ | |
| 123789 | 124214 | sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); |
| 123790 | 124215 | sqlite3VdbeUsesBtree(v, iDb); |
| 123791 | 124216 | } |
| 123792 | 124217 | return; |
| 123793 | 124218 | } |
| @@ -124377,12 +124802,11 @@ | ||
| 124377 | 124802 | |
| 124378 | 124803 | db = pParse->db; |
| 124379 | 124804 | iDb = sqlite3SchemaToIndex(db, pTable->pSchema); |
| 124380 | 124805 | assert( iDb>=0 ); |
| 124381 | 124806 | |
| 124382 | - pTable->tabFlags |= TF_Virtual; | |
| 124383 | - pTable->nModuleArg = 0; | |
| 124807 | + assert( pTable->nModuleArg==0 ); | |
| 124384 | 124808 | addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); |
| 124385 | 124809 | addModuleArgument(db, pTable, 0); |
| 124386 | 124810 | addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); |
| 124387 | 124811 | assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) |
| 124388 | 124812 | || (pParse->sNameToken.z==pName1->z && pName2->z==0) |
| @@ -124666,11 +125090,11 @@ | ||
| 124666 | 125090 | const char *zMod; |
| 124667 | 125091 | Module *pMod; |
| 124668 | 125092 | int rc; |
| 124669 | 125093 | |
| 124670 | 125094 | assert( pTab ); |
| 124671 | - if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){ | |
| 125095 | + if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){ | |
| 124672 | 125096 | return SQLITE_OK; |
| 124673 | 125097 | } |
| 124674 | 125098 | |
| 124675 | 125099 | /* Locate the required virtual table module */ |
| 124676 | 125100 | zMod = pTab->azModuleArg[0]; |
| @@ -124736,11 +125160,11 @@ | ||
| 124736 | 125160 | Table *pTab; |
| 124737 | 125161 | Module *pMod; |
| 124738 | 125162 | const char *zMod; |
| 124739 | 125163 | |
| 124740 | 125164 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); |
| 124741 | - assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); | |
| 125165 | + assert( pTab && IsVirtual(pTab) && !pTab->pVTable ); | |
| 124742 | 125166 | |
| 124743 | 125167 | /* Locate the required virtual table module */ |
| 124744 | 125168 | zMod = pTab->azModuleArg[0]; |
| 124745 | 125169 | pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); |
| 124746 | 125170 | |
| @@ -124790,11 +125214,11 @@ | ||
| 124790 | 125214 | sqlite3Error(db, SQLITE_MISUSE); |
| 124791 | 125215 | sqlite3_mutex_leave(db->mutex); |
| 124792 | 125216 | return SQLITE_MISUSE_BKPT; |
| 124793 | 125217 | } |
| 124794 | 125218 | pTab = pCtx->pTab; |
| 124795 | - assert( (pTab->tabFlags & TF_Virtual)!=0 ); | |
| 125219 | + assert( IsVirtual(pTab) ); | |
| 124796 | 125220 | |
| 124797 | 125221 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 124798 | 125222 | if( pParse==0 ){ |
| 124799 | 125223 | rc = SQLITE_NOMEM_BKPT; |
| 124800 | 125224 | }else{ |
| @@ -124804,11 +125228,11 @@ | ||
| 124804 | 125228 | |
| 124805 | 125229 | if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) |
| 124806 | 125230 | && pParse->pNewTable |
| 124807 | 125231 | && !db->mallocFailed |
| 124808 | 125232 | && !pParse->pNewTable->pSelect |
| 124809 | - && (pParse->pNewTable->tabFlags & TF_Virtual)==0 | |
| 125233 | + && !IsVirtual(pParse->pNewTable) | |
| 124810 | 125234 | ){ |
| 124811 | 125235 | if( !pTab->aCol ){ |
| 124812 | 125236 | Table *pNew = pParse->pNewTable; |
| 124813 | 125237 | Index *pIdx; |
| 124814 | 125238 | pTab->aCol = pNew->aCol; |
| @@ -125093,11 +125517,11 @@ | ||
| 125093 | 125517 | /* Check to see the left operand is a column in a virtual table */ |
| 125094 | 125518 | if( NEVER(pExpr==0) ) return pDef; |
| 125095 | 125519 | if( pExpr->op!=TK_COLUMN ) return pDef; |
| 125096 | 125520 | pTab = pExpr->pTab; |
| 125097 | 125521 | if( NEVER(pTab==0) ) return pDef; |
| 125098 | - if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef; | |
| 125522 | + if( !IsVirtual(pTab) ) return pDef; | |
| 125099 | 125523 | pVtab = sqlite3GetVTable(db, pTab)->pVtab; |
| 125100 | 125524 | assert( pVtab!=0 ); |
| 125101 | 125525 | assert( pVtab->pModule!=0 ); |
| 125102 | 125526 | pMod = (sqlite3_module *)pVtab->pModule; |
| 125103 | 125527 | if( pMod->xFindFunction==0 ) return pDef; |
| @@ -125188,12 +125612,11 @@ | ||
| 125188 | 125612 | return 0; |
| 125189 | 125613 | } |
| 125190 | 125614 | pMod->pEpoTab = pTab; |
| 125191 | 125615 | pTab->nTabRef = 1; |
| 125192 | 125616 | pTab->pSchema = db->aDb[0].pSchema; |
| 125193 | - pTab->tabFlags |= TF_Virtual; | |
| 125194 | - pTab->nModuleArg = 0; | |
| 125617 | + assert( pTab->nModuleArg==0 ); | |
| 125195 | 125618 | pTab->iPKey = -1; |
| 125196 | 125619 | addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
| 125197 | 125620 | addModuleArgument(db, pTab, 0); |
| 125198 | 125621 | addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
| 125199 | 125622 | rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); |
| @@ -125260,11 +125683,11 @@ | ||
| 125260 | 125683 | case SQLITE_VTAB_CONSTRAINT_SUPPORT: { |
| 125261 | 125684 | VtabCtx *p = db->pVtabCtx; |
| 125262 | 125685 | if( !p ){ |
| 125263 | 125686 | rc = SQLITE_MISUSE_BKPT; |
| 125264 | 125687 | }else{ |
| 125265 | - assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 ); | |
| 125688 | + assert( p->pTab==0 || IsVirtual(p->pTab) ); | |
| 125266 | 125689 | p->pVTable->bConstraint = (u8)va_arg(ap, int); |
| 125267 | 125690 | } |
| 125268 | 125691 | break; |
| 125269 | 125692 | } |
| 125270 | 125693 | default: |
| @@ -125699,12 +126122,17 @@ | ||
| 125699 | 126122 | WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ |
| 125700 | 126123 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 125701 | 126124 | UnpackedRecord *pRec; /* Probe for stat4 (if required) */ |
| 125702 | 126125 | int nRecValid; /* Number of valid fields currently in pRec */ |
| 125703 | 126126 | #endif |
| 126127 | + unsigned int bldFlags; /* SQLITE_BLDF_* flags */ | |
| 125704 | 126128 | }; |
| 125705 | 126129 | |
| 126130 | +/* Allowed values for WhereLoopBuider.bldFlags */ | |
| 126131 | +#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ | |
| 126132 | +#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ | |
| 126133 | + | |
| 125706 | 126134 | /* |
| 125707 | 126135 | ** The WHERE clause processing routine has two halves. The |
| 125708 | 126136 | ** first part does the start of the WHERE loop and the second |
| 125709 | 126137 | ** half does the tail of the WHERE loop. An instance of |
| 125710 | 126138 | ** this structure is returned by the first half and passed |
| @@ -125715,11 +126143,11 @@ | ||
| 125715 | 126143 | */ |
| 125716 | 126144 | struct WhereInfo { |
| 125717 | 126145 | Parse *pParse; /* Parsing and code generating context */ |
| 125718 | 126146 | SrcList *pTabList; /* List of tables in the join */ |
| 125719 | 126147 | ExprList *pOrderBy; /* The ORDER BY clause or NULL */ |
| 125720 | - ExprList *pDistinctSet; /* DISTINCT over all these values */ | |
| 126148 | + ExprList *pResultSet; /* Result set of the query */ | |
| 125721 | 126149 | LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ |
| 125722 | 126150 | int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ |
| 125723 | 126151 | int iContinue; /* Jump here to continue with next record */ |
| 125724 | 126152 | int iBreak; /* Jump here to break out of the loop */ |
| 125725 | 126153 | int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ |
| @@ -126899,10 +127327,11 @@ | ||
| 126899 | 127327 | Parse *pParse; /* Parsing context */ |
| 126900 | 127328 | sqlite3 *db; /* Database connection */ |
| 126901 | 127329 | Vdbe *v; /* The prepared stmt under constructions */ |
| 126902 | 127330 | struct SrcList_item *pTabItem; /* FROM clause term being coded */ |
| 126903 | 127331 | int addrBrk; /* Jump here to break out of the loop */ |
| 127332 | + int addrHalt; /* addrBrk for the outermost loop */ | |
| 126904 | 127333 | int addrCont; /* Jump here to continue with next cycle */ |
| 126905 | 127334 | int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ |
| 126906 | 127335 | int iReleaseReg = 0; /* Temp register to free before returning */ |
| 126907 | 127336 | |
| 126908 | 127337 | pParse = pWInfo->pParse; |
| @@ -126939,10 +127368,15 @@ | ||
| 126939 | 127368 | if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ |
| 126940 | 127369 | pLevel->iLeftJoin = ++pParse->nMem; |
| 126941 | 127370 | sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); |
| 126942 | 127371 | VdbeComment((v, "init LEFT JOIN no-match flag")); |
| 126943 | 127372 | } |
| 127373 | + | |
| 127374 | + /* Compute a safe address to jump to if we discover that the table for | |
| 127375 | + ** this loop is empty and can never contribute content. */ | |
| 127376 | + for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){} | |
| 127377 | + addrHalt = pWInfo->a[j].addrBrk; | |
| 126944 | 127378 | |
| 126945 | 127379 | /* Special case of a FROM clause subquery implemented as a co-routine */ |
| 126946 | 127380 | if( pTabItem->fg.viaCoroutine ){ |
| 126947 | 127381 | int regYield = pTabItem->regReturn; |
| 126948 | 127382 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); |
| @@ -127124,11 +127558,11 @@ | ||
| 127124 | 127558 | VdbeCoverageIf(v, pX->op==TK_LT); |
| 127125 | 127559 | VdbeCoverageIf(v, pX->op==TK_GE); |
| 127126 | 127560 | sqlite3ExprCacheAffinityChange(pParse, r1, 1); |
| 127127 | 127561 | sqlite3ReleaseTempReg(pParse, rTemp); |
| 127128 | 127562 | }else{ |
| 127129 | - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); | |
| 127563 | + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); | |
| 127130 | 127564 | VdbeCoverageIf(v, bRev==0); |
| 127131 | 127565 | VdbeCoverageIf(v, bRev!=0); |
| 127132 | 127566 | } |
| 127133 | 127567 | if( pEnd ){ |
| 127134 | 127568 | Expr *pX; |
| @@ -127770,11 +128204,11 @@ | ||
| 127770 | 128204 | pLevel->op = OP_Noop; |
| 127771 | 128205 | }else{ |
| 127772 | 128206 | codeCursorHint(pTabItem, pWInfo, pLevel, 0); |
| 127773 | 128207 | pLevel->op = aStep[bRev]; |
| 127774 | 128208 | pLevel->p1 = iCur; |
| 127775 | - pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); | |
| 128209 | + pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt); | |
| 127776 | 128210 | VdbeCoverageIf(v, bRev==0); |
| 127777 | 128211 | VdbeCoverageIf(v, bRev!=0); |
| 127778 | 128212 | pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; |
| 127779 | 128213 | } |
| 127780 | 128214 | } |
| @@ -128095,19 +128529,10 @@ | ||
| 128095 | 128529 | #ifdef SQLITE_EBCDIC |
| 128096 | 128530 | if( *pnoCase ) return 0; |
| 128097 | 128531 | #endif |
| 128098 | 128532 | pList = pExpr->x.pList; |
| 128099 | 128533 | pLeft = pList->a[1].pExpr; |
| 128100 | - if( pLeft->op!=TK_COLUMN | |
| 128101 | - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT | |
| 128102 | - || IsVirtual(pLeft->pTab) /* Value might be numeric */ | |
| 128103 | - ){ | |
| 128104 | - /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must | |
| 128105 | - ** be the name of an indexed column with TEXT affinity. */ | |
| 128106 | - return 0; | |
| 128107 | - } | |
| 128108 | - assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ | |
| 128109 | 128534 | |
| 128110 | 128535 | pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); |
| 128111 | 128536 | op = pRight->op; |
| 128112 | 128537 | if( op==TK_VARIABLE ){ |
| 128113 | 128538 | Vdbe *pReprepare = pParse->pReprepare; |
| @@ -128120,10 +128545,27 @@ | ||
| 128120 | 128545 | assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); |
| 128121 | 128546 | }else if( op==TK_STRING ){ |
| 128122 | 128547 | z = pRight->u.zToken; |
| 128123 | 128548 | } |
| 128124 | 128549 | if( z ){ |
| 128550 | + | |
| 128551 | + /* If the RHS begins with a digit or a minus sign, then the LHS must | |
| 128552 | + ** be an ordinary column (not a virtual table column) with TEXT affinity. | |
| 128553 | + ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false | |
| 128554 | + ** even though "lhs LIKE rhs" is true. But if the RHS does not start | |
| 128555 | + ** with a digit or '-', then "lhs LIKE rhs" will always be false if | |
| 128556 | + ** the LHS is numeric and so the optimization still works. | |
| 128557 | + */ | |
| 128558 | + if( sqlite3Isdigit(z[0]) || z[0]=='-' ){ | |
| 128559 | + if( pLeft->op!=TK_COLUMN | |
| 128560 | + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT | |
| 128561 | + || IsVirtual(pLeft->pTab) /* Value might be numeric */ | |
| 128562 | + ){ | |
| 128563 | + sqlite3ValueFree(pVal); | |
| 128564 | + return 0; | |
| 128565 | + } | |
| 128566 | + } | |
| 128125 | 128567 | cnt = 0; |
| 128126 | 128568 | while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ |
| 128127 | 128569 | cnt++; |
| 128128 | 128570 | } |
| 128129 | 128571 | if( cnt!=0 && 255!=(u8)z[cnt-1] ){ |
| @@ -128748,11 +129190,11 @@ | ||
| 128748 | 129190 | iCur = pFrom->a[i].iCursor; |
| 128749 | 129191 | for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 128750 | 129192 | if( pIdx->aColExpr==0 ) continue; |
| 128751 | 129193 | for(i=0; i<pIdx->nKeyCol; i++){ |
| 128752 | 129194 | if( pIdx->aiColumn[i]!=XN_EXPR ) continue; |
| 128753 | - if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ | |
| 129195 | + if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ | |
| 128754 | 129196 | *piCur = iCur; |
| 128755 | 129197 | *piColumn = XN_EXPR; |
| 128756 | 129198 | return 1; |
| 128757 | 129199 | } |
| 128758 | 129200 | } |
| @@ -129539,11 +129981,12 @@ | ||
| 129539 | 129981 | do{ |
| 129540 | 129982 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 129541 | 129983 | if( pTerm->leftCursor==iCur |
| 129542 | 129984 | && pTerm->u.leftColumn==iColumn |
| 129543 | 129985 | && (iColumn!=XN_EXPR |
| 129544 | - || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) | |
| 129986 | + || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, | |
| 129987 | + pScan->pIdxExpr,iCur)==0) | |
| 129545 | 129988 | && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) |
| 129546 | 129989 | ){ |
| 129547 | 129990 | if( (pTerm->eOperator & WO_EQUIV)!=0 |
| 129548 | 129991 | && pScan->nEquiv<ArraySize(pScan->aiCur) |
| 129549 | 129992 | && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN |
| @@ -131716,10 +132159,15 @@ | ||
| 131716 | 132159 | testcase( eOp & WO_IS ); |
| 131717 | 132160 | testcase( eOp & WO_ISNULL ); |
| 131718 | 132161 | continue; |
| 131719 | 132162 | } |
| 131720 | 132163 | |
| 132164 | + if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ | |
| 132165 | + pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; | |
| 132166 | + }else{ | |
| 132167 | + pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; | |
| 132168 | + } | |
| 131721 | 132169 | pNew->wsFlags = saved_wsFlags; |
| 131722 | 132170 | pNew->u.btree.nEq = saved_nEq; |
| 131723 | 132171 | pNew->u.btree.nBtm = saved_nBtm; |
| 131724 | 132172 | pNew->u.btree.nTop = saved_nTop; |
| 131725 | 132173 | pNew->nLTerm = saved_nLTerm; |
| @@ -132263,11 +132711,19 @@ | ||
| 132263 | 132711 | pNew->nOut = rSize; |
| 132264 | 132712 | if( rc ) break; |
| 132265 | 132713 | } |
| 132266 | 132714 | } |
| 132267 | 132715 | |
| 132716 | + pBuilder->bldFlags = 0; | |
| 132268 | 132717 | rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); |
| 132718 | + if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){ | |
| 132719 | + /* If a non-unique index is used, or if a prefix of the key for | |
| 132720 | + ** unique index is used (making the index functionally non-unique) | |
| 132721 | + ** then the sqlite_stat1 data becomes important for scoring the | |
| 132722 | + ** plan */ | |
| 132723 | + pTab->tabFlags |= TF_StatsUsed; | |
| 132724 | + } | |
| 132269 | 132725 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 132270 | 132726 | sqlite3Stat4ProbeFree(pBuilder->pRec); |
| 132271 | 132727 | pBuilder->nRecValid = 0; |
| 132272 | 132728 | pBuilder->pRec = 0; |
| 132273 | 132729 | #endif |
| @@ -133443,13 +133899,13 @@ | ||
| 133443 | 133899 | && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 |
| 133444 | 133900 | && pWInfo->eDistinct==WHERE_DISTINCT_NOOP |
| 133445 | 133901 | && nRowEst |
| 133446 | 133902 | ){ |
| 133447 | 133903 | Bitmask notUsed; |
| 133448 | - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom, | |
| 133904 | + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, | |
| 133449 | 133905 | WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); |
| 133450 | - if( rc==pWInfo->pDistinctSet->nExpr ){ | |
| 133906 | + if( rc==pWInfo->pResultSet->nExpr ){ | |
| 133451 | 133907 | pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; |
| 133452 | 133908 | } |
| 133453 | 133909 | } |
| 133454 | 133910 | if( pWInfo->pOrderBy ){ |
| 133455 | 133911 | if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ |
| @@ -133682,11 +134138,11 @@ | ||
| 133682 | 134138 | SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( |
| 133683 | 134139 | Parse *pParse, /* The parser context */ |
| 133684 | 134140 | SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ |
| 133685 | 134141 | Expr *pWhere, /* The WHERE clause */ |
| 133686 | 134142 | ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ |
| 133687 | - ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */ | |
| 134143 | + ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ | |
| 133688 | 134144 | u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ |
| 133689 | 134145 | int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number |
| 133690 | 134146 | ** If WHERE_USE_LIMIT, then the limit amount */ |
| 133691 | 134147 | ){ |
| 133692 | 134148 | int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ |
| @@ -133758,11 +134214,11 @@ | ||
| 133758 | 134214 | goto whereBeginError; |
| 133759 | 134215 | } |
| 133760 | 134216 | pWInfo->pParse = pParse; |
| 133761 | 134217 | pWInfo->pTabList = pTabList; |
| 133762 | 134218 | pWInfo->pOrderBy = pOrderBy; |
| 133763 | - pWInfo->pDistinctSet = pDistinctSet; | |
| 134219 | + pWInfo->pResultSet = pResultSet; | |
| 133764 | 134220 | pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; |
| 133765 | 134221 | pWInfo->nLevel = nTabList; |
| 133766 | 134222 | pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); |
| 133767 | 134223 | pWInfo->wctrlFlags = wctrlFlags; |
| 133768 | 134224 | pWInfo->iLimit = iAuxArg; |
| @@ -133836,17 +134292,17 @@ | ||
| 133836 | 134292 | /* Analyze all of the subexpressions. */ |
| 133837 | 134293 | sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); |
| 133838 | 134294 | if( db->mallocFailed ) goto whereBeginError; |
| 133839 | 134295 | |
| 133840 | 134296 | if( wctrlFlags & WHERE_WANT_DISTINCT ){ |
| 133841 | - if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){ | |
| 134297 | + if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ | |
| 133842 | 134298 | /* The DISTINCT marking is pointless. Ignore it. */ |
| 133843 | 134299 | pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; |
| 133844 | 134300 | }else if( pOrderBy==0 ){ |
| 133845 | 134301 | /* Try to ORDER BY the result set to make distinct processing easier */ |
| 133846 | 134302 | pWInfo->wctrlFlags |= WHERE_DISTINCTBY; |
| 133847 | - pWInfo->pOrderBy = pDistinctSet; | |
| 134303 | + pWInfo->pOrderBy = pResultSet; | |
| 133848 | 134304 | } |
| 133849 | 134305 | } |
| 133850 | 134306 | |
| 133851 | 134307 | /* Construct the WhereLoop objects */ |
| 133852 | 134308 | #if defined(WHERETRACE_ENABLED) |
| @@ -133918,14 +134374,14 @@ | ||
| 133918 | 134374 | } |
| 133919 | 134375 | } |
| 133920 | 134376 | #endif |
| 133921 | 134377 | /* Attempt to omit tables from the join that do not effect the result */ |
| 133922 | 134378 | if( pWInfo->nLevel>=2 |
| 133923 | - && pDistinctSet!=0 | |
| 134379 | + && pResultSet!=0 | |
| 133924 | 134380 | && OptimizationEnabled(db, SQLITE_OmitNoopJoin) |
| 133925 | 134381 | ){ |
| 133926 | - Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet); | |
| 134382 | + Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); | |
| 133927 | 134383 | if( sWLB.pOrderBy ){ |
| 133928 | 134384 | tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); |
| 133929 | 134385 | } |
| 133930 | 134386 | while( pWInfo->nLevel>=2 ){ |
| 133931 | 134387 | WhereTerm *pTerm, *pEnd; |
| @@ -134704,166 +135160,166 @@ | ||
| 134704 | 135160 | ** |
| 134705 | 135161 | *********** Begin parsing tables **********************************************/ |
| 134706 | 135162 | #define YY_ACTTAB_COUNT (1567) |
| 134707 | 135163 | static const YYACTIONTYPE yy_action[] = { |
| 134708 | 135164 | /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100, |
| 134709 | - /* 10 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, | |
| 135165 | + /* 10 */ 90, 978, 978, 853, 856, 845, 845, 97, 97, 98, | |
| 134710 | 135166 | /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, |
| 134711 | - /* 30 */ 94, 94, 94, 93, 351, 325, 977, 977, 824, 824, | |
| 134712 | - /* 40 */ 826, 947, 354, 99, 100, 90, 842, 842, 854, 857, | |
| 134713 | - /* 50 */ 846, 846, 97, 97, 98, 98, 98, 98, 338, 96, | |
| 135167 | + /* 30 */ 94, 94, 94, 93, 351, 325, 976, 976, 824, 824, | |
| 135168 | + /* 40 */ 826, 946, 354, 99, 100, 90, 978, 978, 853, 856, | |
| 135169 | + /* 50 */ 845, 845, 97, 97, 98, 98, 98, 98, 338, 96, | |
| 134714 | 135170 | /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 134715 | - /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 977, 977, | |
| 135171 | + /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 976, 976, | |
| 134716 | 135172 | /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100, |
| 134717 | - /* 90 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, | |
| 135173 | + /* 90 */ 90, 978, 978, 853, 856, 845, 845, 97, 97, 98, | |
| 134718 | 135174 | /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, |
| 134719 | 135175 | /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325, |
| 134720 | 135176 | /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, |
| 134721 | - /* 130 */ 842, 842, 854, 857, 846, 846, 97, 97, 98, 98, | |
| 135177 | + /* 130 */ 978, 978, 853, 856, 845, 845, 97, 97, 98, 98, | |
| 134722 | 135178 | /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, |
| 134723 | - /* 150 */ 94, 94, 93, 351, 958, 958, 325, 268, 428, 413, | |
| 134724 | - /* 160 */ 411, 61, 752, 752, 99, 100, 90, 842, 842, 854, | |
| 134725 | - /* 170 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 60, | |
| 135179 | + /* 150 */ 94, 94, 93, 351, 957, 957, 325, 268, 428, 413, | |
| 135180 | + /* 160 */ 411, 61, 752, 752, 99, 100, 90, 978, 978, 853, | |
| 135181 | + /* 170 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 60, | |
| 134726 | 135182 | /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134727 | - /* 190 */ 351, 325, 270, 329, 273, 277, 959, 960, 250, 99, | |
| 134728 | - /* 200 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 135183 | + /* 190 */ 351, 325, 270, 329, 273, 277, 958, 959, 250, 99, | |
| 135184 | + /* 200 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, | |
| 134729 | 135185 | /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, |
| 134730 | - /* 220 */ 95, 94, 94, 94, 93, 351, 325, 938, 1326, 698, | |
| 134731 | - /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 842, 842, 854, | |
| 134732 | - /* 240 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 347, | |
| 135186 | + /* 220 */ 95, 94, 94, 94, 93, 351, 325, 937, 1326, 698, | |
| 135187 | + /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 978, 978, 853, | |
| 135188 | + /* 240 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 347, | |
| 134733 | 135189 | /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134734 | - /* 260 */ 351, 325, 938, 1327, 384, 699, 1327, 381, 379, 99, | |
| 134735 | - /* 270 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 135190 | + /* 260 */ 351, 325, 937, 1327, 384, 699, 1327, 381, 379, 99, | |
| 135191 | + /* 270 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, | |
| 134736 | 135192 | /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95, |
| 134737 | 135193 | /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, |
| 134738 | - /* 300 */ 833, 936, 373, 700, 99, 100, 90, 842, 842, 854, | |
| 134739 | - /* 310 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 375, | |
| 135194 | + /* 300 */ 833, 935, 373, 700, 99, 100, 90, 978, 978, 853, | |
| 135195 | + /* 310 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 375, | |
| 134740 | 135196 | /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134741 | - /* 330 */ 351, 325, 1276, 947, 354, 818, 936, 739, 739, 99, | |
| 134742 | - /* 340 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 135197 | + /* 330 */ 351, 325, 1275, 946, 354, 818, 935, 739, 739, 99, | |
| 135198 | + /* 340 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, | |
| 134743 | 135199 | /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, |
| 134744 | - /* 360 */ 95, 94, 94, 94, 93, 351, 325, 969, 227, 92, | |
| 134745 | - /* 370 */ 89, 178, 373, 300, 99, 100, 90, 842, 842, 854, | |
| 134746 | - /* 380 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 921, | |
| 135200 | + /* 360 */ 95, 94, 94, 94, 93, 351, 325, 968, 227, 92, | |
| 135201 | + /* 370 */ 89, 178, 373, 300, 99, 100, 90, 978, 978, 853, | |
| 135202 | + /* 380 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 920, | |
| 134747 | 135203 | /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134748 | 135204 | /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99, |
| 134749 | - /* 410 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 135205 | + /* 410 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, | |
| 134750 | 135206 | /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, |
| 134751 | - /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 958, | |
| 134752 | - /* 440 */ 958, 158, 25, 422, 99, 100, 90, 842, 842, 854, | |
| 134753 | - /* 450 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 450, | |
| 135207 | + /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 957, | |
| 135208 | + /* 440 */ 957, 158, 25, 422, 99, 100, 90, 978, 978, 853, | |
| 135209 | + /* 450 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 450, | |
| 134754 | 135210 | /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134755 | - /* 470 */ 351, 443, 224, 224, 420, 958, 958, 962, 325, 52, | |
| 134756 | - /* 480 */ 52, 959, 960, 176, 415, 78, 99, 100, 90, 842, | |
| 134757 | - /* 490 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, | |
| 135211 | + /* 470 */ 351, 443, 224, 224, 420, 957, 957, 961, 325, 52, | |
| 135212 | + /* 480 */ 52, 958, 959, 176, 415, 78, 99, 100, 90, 978, | |
| 135213 | + /* 490 */ 978, 853, 856, 845, 845, 97, 97, 98, 98, 98, | |
| 134758 | 135214 | /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, |
| 134759 | - /* 510 */ 94, 93, 351, 325, 428, 418, 298, 959, 960, 962, | |
| 134760 | - /* 520 */ 81, 99, 88, 90, 842, 842, 854, 857, 846, 846, | |
| 135215 | + /* 510 */ 94, 93, 351, 325, 428, 418, 298, 958, 959, 961, | |
| 135216 | + /* 520 */ 81, 99, 88, 90, 978, 978, 853, 856, 845, 845, | |
| 134761 | 135217 | /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96, |
| 134762 | - /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 843, | |
| 134763 | - /* 550 */ 843, 855, 858, 996, 318, 343, 379, 100, 90, 842, | |
| 134764 | - /* 560 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, | |
| 135218 | + /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 842, | |
| 135219 | + /* 550 */ 842, 854, 857, 996, 318, 343, 379, 100, 90, 978, | |
| 135220 | + /* 560 */ 978, 853, 856, 845, 845, 97, 97, 98, 98, 98, | |
| 134765 | 135221 | /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, |
| 134766 | 135222 | /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, |
| 134767 | - /* 590 */ 929, 52, 52, 90, 842, 842, 854, 857, 846, 846, | |
| 135223 | + /* 590 */ 928, 52, 52, 90, 978, 978, 853, 856, 845, 845, | |
| 134768 | 135224 | /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, |
| 134769 | 135225 | /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, |
| 134770 | - /* 620 */ 847, 3, 1203, 361, 360, 378, 344, 813, 958, 958, | |
| 134771 | - /* 630 */ 1300, 86, 445, 729, 3, 212, 169, 287, 405, 282, | |
| 135226 | + /* 620 */ 846, 3, 1202, 361, 360, 378, 344, 813, 957, 957, | |
| 135227 | + /* 630 */ 1299, 86, 445, 729, 3, 212, 169, 287, 405, 282, | |
| 134772 | 135228 | /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245, |
| 134773 | 135229 | /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, |
| 134774 | 135230 | /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, |
| 134775 | - /* 670 */ 959, 960, 194, 455, 670, 402, 399, 398, 448, 243, | |
| 135231 | + /* 670 */ 958, 959, 194, 455, 670, 402, 399, 398, 448, 243, | |
| 134776 | 135232 | /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224, |
| 134777 | 135233 | /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427, |
| 134778 | 135234 | /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452, |
| 134779 | - /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1271, | |
| 134780 | - /* 720 */ 1271, 23, 958, 958, 86, 445, 397, 3, 228, 429, | |
| 134781 | - /* 730 */ 895, 824, 824, 826, 827, 19, 203, 720, 52, 52, | |
| 135235 | + /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1270, | |
| 135236 | + /* 720 */ 1270, 23, 957, 957, 86, 445, 397, 3, 228, 429, | |
| 135237 | + /* 730 */ 894, 824, 824, 826, 827, 19, 203, 720, 52, 52, | |
| 134782 | 135238 | /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229, |
| 134783 | 135239 | /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85, |
| 134784 | - /* 760 */ 352, 352, 120, 157, 959, 960, 58, 977, 409, 355, | |
| 135240 | + /* 760 */ 352, 352, 120, 157, 958, 959, 58, 976, 409, 355, | |
| 134785 | 135241 | /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86, |
| 134786 | 135242 | /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96, |
| 134787 | 135243 | /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 134788 | - /* 800 */ 832, 120, 452, 451, 813, 887, 819, 83, 84, 977, | |
| 134789 | - /* 810 */ 813, 132, 410, 920, 85, 352, 352, 132, 407, 789, | |
| 134790 | - /* 820 */ 958, 958, 92, 89, 178, 917, 448, 262, 370, 261, | |
| 134791 | - /* 830 */ 82, 914, 80, 262, 370, 261, 776, 824, 824, 826, | |
| 134792 | - /* 840 */ 827, 19, 934, 434, 96, 96, 96, 96, 95, 95, | |
| 134793 | - /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 958, | |
| 134794 | - /* 860 */ 958, 819, 959, 960, 120, 92, 89, 178, 945, 2, | |
| 134795 | - /* 870 */ 918, 965, 268, 1, 976, 76, 445, 762, 3, 708, | |
| 134796 | - /* 880 */ 901, 901, 387, 958, 958, 757, 919, 371, 740, 778, | |
| 135244 | + /* 800 */ 832, 120, 452, 451, 813, 886, 819, 83, 84, 976, | |
| 135245 | + /* 810 */ 813, 132, 410, 919, 85, 352, 352, 132, 407, 789, | |
| 135246 | + /* 820 */ 957, 957, 92, 89, 178, 916, 448, 262, 370, 261, | |
| 135247 | + /* 830 */ 82, 913, 80, 262, 370, 261, 776, 824, 824, 826, | |
| 135248 | + /* 840 */ 827, 19, 933, 434, 96, 96, 96, 96, 95, 95, | |
| 135249 | + /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 957, | |
| 135250 | + /* 860 */ 957, 819, 958, 959, 120, 92, 89, 178, 944, 2, | |
| 135251 | + /* 870 */ 917, 964, 268, 1, 975, 76, 445, 762, 3, 708, | |
| 135252 | + /* 880 */ 900, 900, 387, 957, 957, 757, 918, 371, 740, 778, | |
| 134797 | 135253 | /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450, |
| 134798 | - /* 900 */ 24, 959, 960, 83, 84, 369, 958, 958, 177, 226, | |
| 134799 | - /* 910 */ 85, 352, 352, 885, 315, 314, 313, 215, 311, 10, | |
| 134800 | - /* 920 */ 10, 683, 448, 349, 348, 959, 960, 909, 777, 157, | |
| 134801 | - /* 930 */ 120, 958, 958, 337, 776, 416, 711, 310, 450, 434, | |
| 134802 | - /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 959, 960, | |
| 134803 | - /* 950 */ 908, 832, 792, 452, 451, 9, 9, 819, 10, 10, | |
| 135254 | + /* 900 */ 24, 958, 959, 83, 84, 369, 957, 957, 177, 226, | |
| 135255 | + /* 910 */ 85, 352, 352, 884, 315, 314, 313, 215, 311, 10, | |
| 135256 | + /* 920 */ 10, 683, 448, 349, 348, 958, 959, 908, 777, 157, | |
| 135257 | + /* 930 */ 120, 957, 957, 337, 776, 416, 711, 310, 450, 434, | |
| 135258 | + /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 958, 959, | |
| 135259 | + /* 950 */ 907, 832, 792, 452, 451, 9, 9, 819, 10, 10, | |
| 134804 | 135260 | /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171, |
| 134805 | - /* 970 */ 170, 167, 339, 959, 960, 247, 984, 702, 702, 450, | |
| 134806 | - /* 980 */ 715, 233, 686, 982, 889, 983, 182, 914, 824, 824, | |
| 135261 | + /* 970 */ 170, 167, 339, 958, 959, 247, 984, 702, 702, 450, | |
| 135262 | + /* 980 */ 715, 233, 686, 982, 888, 983, 182, 913, 824, 824, | |
| 134807 | 135263 | /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10, |
| 134808 | - /* 1000 */ 10, 889, 891, 749, 958, 958, 917, 268, 985, 198, | |
| 135264 | + /* 1000 */ 10, 888, 890, 749, 957, 957, 916, 268, 985, 198, | |
| 134809 | 135265 | /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825, |
| 134810 | 135266 | /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91, |
| 134811 | 135267 | /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134812 | - /* 1040 */ 351, 157, 810, 371, 382, 359, 959, 960, 358, 268, | |
| 134813 | - /* 1050 */ 450, 918, 368, 324, 824, 824, 826, 450, 709, 450, | |
| 134814 | - /* 1060 */ 264, 380, 889, 450, 877, 746, 253, 919, 255, 433, | |
| 135268 | + /* 1040 */ 351, 157, 810, 371, 382, 359, 958, 959, 358, 268, | |
| 135269 | + /* 1050 */ 450, 917, 368, 324, 824, 824, 826, 450, 709, 450, | |
| 135270 | + /* 1060 */ 264, 380, 888, 450, 876, 746, 253, 918, 255, 433, | |
| 134815 | 135271 | /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12, |
| 134816 | 135272 | /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162, |
| 134817 | 135273 | /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450, |
| 134818 | - /* 1100 */ 709, 1210, 450, 132, 450, 39, 39, 450, 40, 40, | |
| 135274 | + /* 1100 */ 709, 1209, 450, 132, 450, 39, 39, 450, 40, 40, | |
| 134819 | 135275 | /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28, |
| 134820 | 135276 | /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450, |
| 134821 | 135277 | /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767, |
| 134822 | 135278 | /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47, |
| 134823 | 135279 | /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172, |
| 134824 | 135280 | /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122, |
| 134825 | - /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 898, 56, 56, | |
| 134826 | - /* 1180 */ 450, 897, 35, 35, 450, 267, 450, 817, 450, 817, | |
| 135281 | + /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 897, 56, 56, | |
| 135282 | + /* 1180 */ 450, 896, 35, 35, 450, 267, 450, 817, 450, 817, | |
| 134827 | 135283 | /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817, |
| 134828 | 135284 | /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119, |
| 134829 | 135285 | /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111, |
| 134830 | - /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 912, | |
| 135286 | + /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 911, | |
| 134831 | 135287 | /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331, |
| 134832 | - /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 937, 197, | |
| 135288 | + /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 936, 197, | |
| 134833 | 135289 | /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436, |
| 134834 | - /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 933, | |
| 135290 | + /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 932, | |
| 134835 | 135291 | /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202, |
| 134836 | - /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 884, | |
| 135292 | + /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 883, | |
| 134837 | 135293 | /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74, |
| 134838 | - /* 1300 */ 726, 727, 785, 783, 880, 202, 999, 208, 894, 893, | |
| 134839 | - /* 1310 */ 894, 893, 694, 816, 763, 116, 774, 1290, 431, 432, | |
| 135294 | + /* 1300 */ 726, 727, 785, 783, 879, 202, 999, 208, 893, 892, | |
| 135295 | + /* 1310 */ 893, 892, 694, 816, 763, 116, 774, 1289, 431, 432, | |
| 134840 | 135296 | /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289, |
| 134841 | - /* 1330 */ 679, 884, 681, 952, 291, 218, 293, 7, 316, 828, | |
| 134842 | - /* 1340 */ 173, 805, 259, 364, 252, 911, 376, 713, 295, 435, | |
| 134843 | - /* 1350 */ 308, 168, 955, 993, 135, 400, 990, 284, 882, 881, | |
| 134844 | - /* 1360 */ 205, 928, 926, 59, 333, 62, 144, 156, 130, 72, | |
| 135297 | + /* 1330 */ 679, 883, 681, 951, 291, 218, 293, 7, 316, 828, | |
| 135298 | + /* 1340 */ 173, 805, 259, 364, 252, 910, 376, 713, 295, 435, | |
| 135299 | + /* 1350 */ 308, 168, 954, 993, 135, 400, 990, 284, 881, 880, | |
| 135300 | + /* 1360 */ 205, 927, 925, 59, 333, 62, 144, 156, 130, 72, | |
| 134845 | 135301 | /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383, |
| 134846 | - /* 1380 */ 67, 896, 140, 141, 142, 148, 389, 812, 775, 266, | |
| 134847 | - /* 1390 */ 219, 190, 154, 391, 913, 876, 271, 406, 191, 322, | |
| 135302 | + /* 1380 */ 67, 895, 140, 141, 142, 148, 389, 812, 775, 266, | |
| 135303 | + /* 1390 */ 219, 190, 154, 391, 912, 875, 271, 406, 191, 322, | |
| 134848 | 135304 | /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421, |
| 134849 | 135305 | /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346, |
| 134850 | - /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 967, 239, | |
| 134851 | - /* 1430 */ 769, 102, 862, 438, 426, 240, 424, 442, 73, 213, | |
| 134852 | - /* 1440 */ 688, 238, 22, 453, 953, 214, 217, 216, 454, 677, | |
| 135306 | + /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 966, 239, | |
| 135307 | + /* 1430 */ 769, 102, 861, 438, 426, 240, 424, 442, 73, 213, | |
| 135308 | + /* 1440 */ 688, 238, 22, 453, 952, 214, 217, 216, 454, 677, | |
| 134853 | 135309 | /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166, |
| 134854 | - /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 892, | |
| 134855 | - /* 1470 */ 327, 890, 811, 328, 134, 128, 136, 138, 743, 258, | |
| 134856 | - /* 1480 */ 907, 184, 143, 129, 910, 186, 63, 64, 145, 187, | |
| 134857 | - /* 1490 */ 906, 65, 8, 66, 13, 188, 202, 899, 265, 149, | |
| 135310 | + /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 891, | |
| 135311 | + /* 1470 */ 327, 889, 811, 328, 134, 128, 136, 138, 743, 258, | |
| 135312 | + /* 1480 */ 906, 184, 143, 129, 909, 186, 63, 64, 145, 187, | |
| 135313 | + /* 1490 */ 905, 65, 8, 66, 13, 188, 202, 898, 265, 149, | |
| 134858 | 135314 | /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396, |
| 134859 | 135315 | /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131, |
| 134860 | - /* 1520 */ 830, 860, 70, 751, 16, 414, 755, 4, 174, 220, | |
| 134861 | - /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 875, | |
| 134862 | - /* 1540 */ 861, 859, 916, 864, 915, 207, 206, 942, 163, 437, | |
| 134863 | - /* 1550 */ 948, 943, 164, 209, 1002, 441, 863, 165, 210, 829, | |
| 134864 | - /* 1560 */ 695, 87, 312, 211, 1292, 1291, 309, | |
| 135316 | + /* 1520 */ 830, 859, 70, 751, 16, 414, 755, 4, 174, 220, | |
| 135317 | + /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 874, | |
| 135318 | + /* 1540 */ 860, 858, 915, 863, 914, 207, 206, 941, 163, 437, | |
| 135319 | + /* 1550 */ 947, 942, 164, 209, 1002, 441, 862, 165, 210, 829, | |
| 135320 | + /* 1560 */ 695, 87, 312, 211, 1291, 1290, 309, | |
| 134865 | 135321 | }; |
| 134866 | 135322 | static const YYCODETYPE yy_lookahead[] = { |
| 134867 | 135323 | /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, |
| 134868 | 135324 | /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
| 134869 | 135325 | /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, |
| @@ -135112,55 +135568,55 @@ | ||
| 135112 | 135568 | /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278, |
| 135113 | 135569 | /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228, |
| 135114 | 135570 | /* 320 */ 1288, 1291, 1276, 1277, 1295, |
| 135115 | 135571 | }; |
| 135116 | 135572 | static const YYACTIONTYPE yy_default[] = { |
| 135117 | - /* 0 */ 1281, 1271, 1271, 1271, 1203, 1203, 1203, 1203, 1271, 1096, | |
| 135118 | - /* 10 */ 1125, 1125, 1255, 1332, 1332, 1332, 1332, 1332, 1332, 1202, | |
| 135119 | - /* 20 */ 1332, 1332, 1332, 1332, 1271, 1100, 1131, 1332, 1332, 1332, | |
| 135120 | - /* 30 */ 1332, 1204, 1205, 1332, 1332, 1332, 1254, 1256, 1141, 1140, | |
| 135121 | - /* 40 */ 1139, 1138, 1237, 1112, 1136, 1129, 1133, 1204, 1198, 1199, | |
| 135122 | - /* 50 */ 1197, 1201, 1205, 1332, 1132, 1167, 1182, 1166, 1332, 1332, | |
| 135573 | + /* 0 */ 1280, 1270, 1270, 1270, 1202, 1202, 1202, 1202, 1270, 1096, | |
| 135574 | + /* 10 */ 1125, 1125, 1254, 1332, 1332, 1332, 1332, 1332, 1332, 1201, | |
| 135575 | + /* 20 */ 1332, 1332, 1332, 1332, 1270, 1100, 1131, 1332, 1332, 1332, | |
| 135576 | + /* 30 */ 1332, 1203, 1204, 1332, 1332, 1332, 1253, 1255, 1141, 1140, | |
| 135577 | + /* 40 */ 1139, 1138, 1236, 1112, 1136, 1129, 1133, 1203, 1197, 1198, | |
| 135578 | + /* 50 */ 1196, 1200, 1204, 1332, 1132, 1167, 1181, 1166, 1332, 1332, | |
| 135123 | 135579 | /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135124 | 135580 | /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135125 | 135581 | /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135126 | 135582 | /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135127 | - /* 100 */ 1332, 1332, 1332, 1332, 1176, 1181, 1188, 1180, 1177, 1169, | |
| 135583 | + /* 100 */ 1332, 1332, 1332, 1332, 1175, 1180, 1187, 1179, 1176, 1169, | |
| 135128 | 135584 | /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, |
| 135129 | - /* 120 */ 1332, 1173, 1185, 1184, 1183, 1262, 1289, 1288, 1332, 1332, | |
| 135585 | + /* 120 */ 1332, 1173, 1184, 1183, 1182, 1261, 1288, 1287, 1332, 1332, | |
| 135130 | 135586 | /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135131 | 135587 | /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135132 | - /* 150 */ 1332, 1332, 1332, 1332, 1332, 1281, 1271, 1025, 1025, 1332, | |
| 135133 | - /* 160 */ 1271, 1271, 1271, 1271, 1271, 1271, 1267, 1100, 1091, 1332, | |
| 135588 | + /* 150 */ 1332, 1332, 1332, 1332, 1332, 1280, 1270, 1025, 1025, 1332, | |
| 135589 | + /* 160 */ 1270, 1270, 1270, 1270, 1270, 1270, 1266, 1100, 1091, 1332, | |
| 135134 | 135590 | /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135135 | - /* 180 */ 1259, 1257, 1332, 1218, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 135591 | + /* 180 */ 1258, 1256, 1332, 1217, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 135136 | 135592 | /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135137 | 135593 | /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, |
| 135138 | - /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1283, 1332, 1232, | |
| 135594 | + /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1282, 1332, 1231, | |
| 135139 | 135595 | /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, |
| 135140 | - /* 230 */ 1321, 1135, 1321, 1042, 1303, 1039, 1125, 1114, 1200, 1125, | |
| 135596 | + /* 230 */ 1321, 1135, 1321, 1042, 1302, 1039, 1125, 1114, 1199, 1125, | |
| 135141 | 135597 | /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, |
| 135142 | 135598 | /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, |
| 135143 | - /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1236, 1318, 1105, 1105, | |
| 135144 | - /* 270 */ 1016, 1211, 1105, 1016, 1105, 1016, 1211, 1068, 1068, 1068, | |
| 135145 | - /* 280 */ 1057, 1211, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, | |
| 135146 | - /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1206, 1105, 1332, | |
| 135147 | - /* 300 */ 1211, 1215, 1215, 1211, 1130, 1119, 1128, 1126, 1135, 1022, | |
| 135148 | - /* 310 */ 1060, 1286, 1286, 1282, 1282, 1282, 1282, 1329, 1329, 1267, | |
| 135149 | - /* 320 */ 1298, 1298, 1044, 1044, 1298, 1332, 1332, 1332, 1332, 1332, | |
| 135150 | - /* 330 */ 1332, 1293, 1332, 1220, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 135599 | + /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1235, 1318, 1105, 1105, | |
| 135600 | + /* 270 */ 1016, 1210, 1105, 1016, 1105, 1016, 1210, 1068, 1068, 1068, | |
| 135601 | + /* 280 */ 1057, 1210, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, | |
| 135602 | + /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1205, 1105, 1332, | |
| 135603 | + /* 300 */ 1210, 1214, 1214, 1210, 1130, 1119, 1128, 1126, 1135, 1022, | |
| 135604 | + /* 310 */ 1060, 1285, 1285, 1281, 1281, 1281, 1281, 1329, 1329, 1266, | |
| 135605 | + /* 320 */ 1297, 1297, 1044, 1044, 1297, 1332, 1332, 1332, 1332, 1332, | |
| 135606 | + /* 330 */ 1332, 1292, 1332, 1219, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 135151 | 135607 | /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135152 | - /* 350 */ 1332, 1332, 1152, 1332, 1000, 1264, 1332, 1332, 1263, 1332, | |
| 135608 | + /* 350 */ 1332, 1332, 1152, 1332, 1000, 1263, 1332, 1332, 1262, 1332, | |
| 135153 | 135609 | /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135154 | 135610 | /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, |
| 135155 | - /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1235, 1234, 1332, 1332, | |
| 135611 | + /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1234, 1233, 1332, 1332, | |
| 135156 | 135612 | /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135157 | 135613 | /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135158 | - /* 410 */ 1332, 1082, 1332, 1332, 1332, 1307, 1332, 1332, 1332, 1332, | |
| 135614 | + /* 410 */ 1332, 1082, 1332, 1332, 1332, 1306, 1332, 1332, 1332, 1332, | |
| 135159 | 135615 | /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, |
| 135160 | - /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1273, | |
| 135161 | - /* 440 */ 1332, 1332, 1332, 1272, 1332, 1332, 1332, 1332, 1332, 1154, | |
| 135616 | + /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1272, | |
| 135617 | + /* 440 */ 1332, 1332, 1332, 1271, 1332, 1332, 1332, 1332, 1332, 1154, | |
| 135162 | 135618 | /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, |
| 135163 | 135619 | }; |
| 135164 | 135620 | /********** End of lemon-generated parsing tables *****************************/ |
| 135165 | 135621 | |
| 135166 | 135622 | /* The next table maps tokens (terminal symbols) into fallback tokens. |
| @@ -135602,147 +136058,147 @@ | ||
| 135602 | 136058 | /* 169 */ "expr ::= expr EQ|NE expr", |
| 135603 | 136059 | /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", |
| 135604 | 136060 | /* 171 */ "expr ::= expr PLUS|MINUS expr", |
| 135605 | 136061 | /* 172 */ "expr ::= expr STAR|SLASH|REM expr", |
| 135606 | 136062 | /* 173 */ "expr ::= expr CONCAT expr", |
| 135607 | - /* 174 */ "likeop ::= LIKE_KW|MATCH", | |
| 135608 | - /* 175 */ "likeop ::= NOT LIKE_KW|MATCH", | |
| 135609 | - /* 176 */ "expr ::= expr likeop expr", | |
| 135610 | - /* 177 */ "expr ::= expr likeop expr ESCAPE expr", | |
| 135611 | - /* 178 */ "expr ::= expr ISNULL|NOTNULL", | |
| 135612 | - /* 179 */ "expr ::= expr NOT NULL", | |
| 135613 | - /* 180 */ "expr ::= expr IS expr", | |
| 135614 | - /* 181 */ "expr ::= expr IS NOT expr", | |
| 135615 | - /* 182 */ "expr ::= NOT expr", | |
| 135616 | - /* 183 */ "expr ::= BITNOT expr", | |
| 135617 | - /* 184 */ "expr ::= MINUS expr", | |
| 135618 | - /* 185 */ "expr ::= PLUS expr", | |
| 135619 | - /* 186 */ "between_op ::= BETWEEN", | |
| 135620 | - /* 187 */ "between_op ::= NOT BETWEEN", | |
| 135621 | - /* 188 */ "expr ::= expr between_op expr AND expr", | |
| 135622 | - /* 189 */ "in_op ::= IN", | |
| 135623 | - /* 190 */ "in_op ::= NOT IN", | |
| 135624 | - /* 191 */ "expr ::= expr in_op LP exprlist RP", | |
| 135625 | - /* 192 */ "expr ::= LP select RP", | |
| 135626 | - /* 193 */ "expr ::= expr in_op LP select RP", | |
| 135627 | - /* 194 */ "expr ::= expr in_op nm dbnm paren_exprlist", | |
| 135628 | - /* 195 */ "expr ::= EXISTS LP select RP", | |
| 135629 | - /* 196 */ "expr ::= CASE case_operand case_exprlist case_else END", | |
| 135630 | - /* 197 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", | |
| 135631 | - /* 198 */ "case_exprlist ::= WHEN expr THEN expr", | |
| 135632 | - /* 199 */ "case_else ::= ELSE expr", | |
| 135633 | - /* 200 */ "case_else ::=", | |
| 135634 | - /* 201 */ "case_operand ::= expr", | |
| 135635 | - /* 202 */ "case_operand ::=", | |
| 135636 | - /* 203 */ "exprlist ::=", | |
| 135637 | - /* 204 */ "nexprlist ::= nexprlist COMMA expr", | |
| 135638 | - /* 205 */ "nexprlist ::= expr", | |
| 135639 | - /* 206 */ "paren_exprlist ::=", | |
| 135640 | - /* 207 */ "paren_exprlist ::= LP exprlist RP", | |
| 135641 | - /* 208 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", | |
| 135642 | - /* 209 */ "uniqueflag ::= UNIQUE", | |
| 135643 | - /* 210 */ "uniqueflag ::=", | |
| 135644 | - /* 211 */ "eidlist_opt ::=", | |
| 135645 | - /* 212 */ "eidlist_opt ::= LP eidlist RP", | |
| 135646 | - /* 213 */ "eidlist ::= eidlist COMMA nm collate sortorder", | |
| 135647 | - /* 214 */ "eidlist ::= nm collate sortorder", | |
| 135648 | - /* 215 */ "collate ::=", | |
| 135649 | - /* 216 */ "collate ::= COLLATE ID|STRING", | |
| 135650 | - /* 217 */ "cmd ::= DROP INDEX ifexists fullname", | |
| 135651 | - /* 218 */ "cmd ::= VACUUM", | |
| 135652 | - /* 219 */ "cmd ::= VACUUM nm", | |
| 135653 | - /* 220 */ "cmd ::= PRAGMA nm dbnm", | |
| 135654 | - /* 221 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", | |
| 135655 | - /* 222 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", | |
| 135656 | - /* 223 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", | |
| 135657 | - /* 224 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", | |
| 135658 | - /* 225 */ "plus_num ::= PLUS INTEGER|FLOAT", | |
| 135659 | - /* 226 */ "minus_num ::= MINUS INTEGER|FLOAT", | |
| 135660 | - /* 227 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", | |
| 135661 | - /* 228 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", | |
| 135662 | - /* 229 */ "trigger_time ::= BEFORE", | |
| 135663 | - /* 230 */ "trigger_time ::= AFTER", | |
| 135664 | - /* 231 */ "trigger_time ::= INSTEAD OF", | |
| 135665 | - /* 232 */ "trigger_time ::=", | |
| 135666 | - /* 233 */ "trigger_event ::= DELETE|INSERT", | |
| 135667 | - /* 234 */ "trigger_event ::= UPDATE", | |
| 135668 | - /* 235 */ "trigger_event ::= UPDATE OF idlist", | |
| 135669 | - /* 236 */ "when_clause ::=", | |
| 135670 | - /* 237 */ "when_clause ::= WHEN expr", | |
| 135671 | - /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", | |
| 135672 | - /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", | |
| 135673 | - /* 240 */ "trnm ::= nm DOT nm", | |
| 135674 | - /* 241 */ "tridxby ::= INDEXED BY nm", | |
| 135675 | - /* 242 */ "tridxby ::= NOT INDEXED", | |
| 135676 | - /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", | |
| 135677 | - /* 244 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", | |
| 135678 | - /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", | |
| 135679 | - /* 246 */ "trigger_cmd ::= select", | |
| 135680 | - /* 247 */ "expr ::= RAISE LP IGNORE RP", | |
| 135681 | - /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", | |
| 135682 | - /* 249 */ "raisetype ::= ROLLBACK", | |
| 135683 | - /* 250 */ "raisetype ::= ABORT", | |
| 135684 | - /* 251 */ "raisetype ::= FAIL", | |
| 135685 | - /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", | |
| 135686 | - /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", | |
| 135687 | - /* 254 */ "cmd ::= DETACH database_kw_opt expr", | |
| 135688 | - /* 255 */ "key_opt ::=", | |
| 135689 | - /* 256 */ "key_opt ::= KEY expr", | |
| 135690 | - /* 257 */ "cmd ::= REINDEX", | |
| 135691 | - /* 258 */ "cmd ::= REINDEX nm dbnm", | |
| 135692 | - /* 259 */ "cmd ::= ANALYZE", | |
| 135693 | - /* 260 */ "cmd ::= ANALYZE nm dbnm", | |
| 135694 | - /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", | |
| 135695 | - /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", | |
| 135696 | - /* 263 */ "add_column_fullname ::= fullname", | |
| 135697 | - /* 264 */ "cmd ::= create_vtab", | |
| 135698 | - /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", | |
| 135699 | - /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", | |
| 135700 | - /* 267 */ "vtabarg ::=", | |
| 135701 | - /* 268 */ "vtabargtoken ::= ANY", | |
| 135702 | - /* 269 */ "vtabargtoken ::= lp anylist RP", | |
| 135703 | - /* 270 */ "lp ::= LP", | |
| 135704 | - /* 271 */ "with ::=", | |
| 135705 | - /* 272 */ "with ::= WITH wqlist", | |
| 135706 | - /* 273 */ "with ::= WITH RECURSIVE wqlist", | |
| 135707 | - /* 274 */ "wqlist ::= nm eidlist_opt AS LP select RP", | |
| 135708 | - /* 275 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", | |
| 135709 | - /* 276 */ "input ::= cmdlist", | |
| 135710 | - /* 277 */ "cmdlist ::= cmdlist ecmd", | |
| 135711 | - /* 278 */ "cmdlist ::= ecmd", | |
| 135712 | - /* 279 */ "ecmd ::= SEMI", | |
| 135713 | - /* 280 */ "ecmd ::= explain cmdx SEMI", | |
| 135714 | - /* 281 */ "explain ::=", | |
| 135715 | - /* 282 */ "trans_opt ::=", | |
| 135716 | - /* 283 */ "trans_opt ::= TRANSACTION", | |
| 135717 | - /* 284 */ "trans_opt ::= TRANSACTION nm", | |
| 135718 | - /* 285 */ "savepoint_opt ::= SAVEPOINT", | |
| 135719 | - /* 286 */ "savepoint_opt ::=", | |
| 135720 | - /* 287 */ "cmd ::= create_table create_table_args", | |
| 135721 | - /* 288 */ "columnlist ::= columnlist COMMA columnname carglist", | |
| 135722 | - /* 289 */ "columnlist ::= columnname carglist", | |
| 135723 | - /* 290 */ "nm ::= ID|INDEXED", | |
| 135724 | - /* 291 */ "nm ::= STRING", | |
| 135725 | - /* 292 */ "nm ::= JOIN_KW", | |
| 135726 | - /* 293 */ "typetoken ::= typename", | |
| 135727 | - /* 294 */ "typename ::= ID|STRING", | |
| 135728 | - /* 295 */ "signed ::= plus_num", | |
| 135729 | - /* 296 */ "signed ::= minus_num", | |
| 135730 | - /* 297 */ "carglist ::= carglist ccons", | |
| 135731 | - /* 298 */ "carglist ::=", | |
| 135732 | - /* 299 */ "ccons ::= NULL onconf", | |
| 135733 | - /* 300 */ "conslist_opt ::= COMMA conslist", | |
| 135734 | - /* 301 */ "conslist ::= conslist tconscomma tcons", | |
| 135735 | - /* 302 */ "conslist ::= tcons", | |
| 135736 | - /* 303 */ "tconscomma ::=", | |
| 135737 | - /* 304 */ "defer_subclause_opt ::= defer_subclause", | |
| 135738 | - /* 305 */ "resolvetype ::= raisetype", | |
| 135739 | - /* 306 */ "selectnowith ::= oneselect", | |
| 135740 | - /* 307 */ "oneselect ::= values", | |
| 135741 | - /* 308 */ "sclp ::= selcollist COMMA", | |
| 135742 | - /* 309 */ "as ::= ID|STRING", | |
| 135743 | - /* 310 */ "expr ::= term", | |
| 136063 | + /* 174 */ "likeop ::= NOT LIKE_KW|MATCH", | |
| 136064 | + /* 175 */ "expr ::= expr likeop expr", | |
| 136065 | + /* 176 */ "expr ::= expr likeop expr ESCAPE expr", | |
| 136066 | + /* 177 */ "expr ::= expr ISNULL|NOTNULL", | |
| 136067 | + /* 178 */ "expr ::= expr NOT NULL", | |
| 136068 | + /* 179 */ "expr ::= expr IS expr", | |
| 136069 | + /* 180 */ "expr ::= expr IS NOT expr", | |
| 136070 | + /* 181 */ "expr ::= NOT expr", | |
| 136071 | + /* 182 */ "expr ::= BITNOT expr", | |
| 136072 | + /* 183 */ "expr ::= MINUS expr", | |
| 136073 | + /* 184 */ "expr ::= PLUS expr", | |
| 136074 | + /* 185 */ "between_op ::= BETWEEN", | |
| 136075 | + /* 186 */ "between_op ::= NOT BETWEEN", | |
| 136076 | + /* 187 */ "expr ::= expr between_op expr AND expr", | |
| 136077 | + /* 188 */ "in_op ::= IN", | |
| 136078 | + /* 189 */ "in_op ::= NOT IN", | |
| 136079 | + /* 190 */ "expr ::= expr in_op LP exprlist RP", | |
| 136080 | + /* 191 */ "expr ::= LP select RP", | |
| 136081 | + /* 192 */ "expr ::= expr in_op LP select RP", | |
| 136082 | + /* 193 */ "expr ::= expr in_op nm dbnm paren_exprlist", | |
| 136083 | + /* 194 */ "expr ::= EXISTS LP select RP", | |
| 136084 | + /* 195 */ "expr ::= CASE case_operand case_exprlist case_else END", | |
| 136085 | + /* 196 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", | |
| 136086 | + /* 197 */ "case_exprlist ::= WHEN expr THEN expr", | |
| 136087 | + /* 198 */ "case_else ::= ELSE expr", | |
| 136088 | + /* 199 */ "case_else ::=", | |
| 136089 | + /* 200 */ "case_operand ::= expr", | |
| 136090 | + /* 201 */ "case_operand ::=", | |
| 136091 | + /* 202 */ "exprlist ::=", | |
| 136092 | + /* 203 */ "nexprlist ::= nexprlist COMMA expr", | |
| 136093 | + /* 204 */ "nexprlist ::= expr", | |
| 136094 | + /* 205 */ "paren_exprlist ::=", | |
| 136095 | + /* 206 */ "paren_exprlist ::= LP exprlist RP", | |
| 136096 | + /* 207 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", | |
| 136097 | + /* 208 */ "uniqueflag ::= UNIQUE", | |
| 136098 | + /* 209 */ "uniqueflag ::=", | |
| 136099 | + /* 210 */ "eidlist_opt ::=", | |
| 136100 | + /* 211 */ "eidlist_opt ::= LP eidlist RP", | |
| 136101 | + /* 212 */ "eidlist ::= eidlist COMMA nm collate sortorder", | |
| 136102 | + /* 213 */ "eidlist ::= nm collate sortorder", | |
| 136103 | + /* 214 */ "collate ::=", | |
| 136104 | + /* 215 */ "collate ::= COLLATE ID|STRING", | |
| 136105 | + /* 216 */ "cmd ::= DROP INDEX ifexists fullname", | |
| 136106 | + /* 217 */ "cmd ::= VACUUM", | |
| 136107 | + /* 218 */ "cmd ::= VACUUM nm", | |
| 136108 | + /* 219 */ "cmd ::= PRAGMA nm dbnm", | |
| 136109 | + /* 220 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", | |
| 136110 | + /* 221 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", | |
| 136111 | + /* 222 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", | |
| 136112 | + /* 223 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", | |
| 136113 | + /* 224 */ "plus_num ::= PLUS INTEGER|FLOAT", | |
| 136114 | + /* 225 */ "minus_num ::= MINUS INTEGER|FLOAT", | |
| 136115 | + /* 226 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", | |
| 136116 | + /* 227 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", | |
| 136117 | + /* 228 */ "trigger_time ::= BEFORE", | |
| 136118 | + /* 229 */ "trigger_time ::= AFTER", | |
| 136119 | + /* 230 */ "trigger_time ::= INSTEAD OF", | |
| 136120 | + /* 231 */ "trigger_time ::=", | |
| 136121 | + /* 232 */ "trigger_event ::= DELETE|INSERT", | |
| 136122 | + /* 233 */ "trigger_event ::= UPDATE", | |
| 136123 | + /* 234 */ "trigger_event ::= UPDATE OF idlist", | |
| 136124 | + /* 235 */ "when_clause ::=", | |
| 136125 | + /* 236 */ "when_clause ::= WHEN expr", | |
| 136126 | + /* 237 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", | |
| 136127 | + /* 238 */ "trigger_cmd_list ::= trigger_cmd SEMI", | |
| 136128 | + /* 239 */ "trnm ::= nm DOT nm", | |
| 136129 | + /* 240 */ "tridxby ::= INDEXED BY nm", | |
| 136130 | + /* 241 */ "tridxby ::= NOT INDEXED", | |
| 136131 | + /* 242 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", | |
| 136132 | + /* 243 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", | |
| 136133 | + /* 244 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", | |
| 136134 | + /* 245 */ "trigger_cmd ::= select", | |
| 136135 | + /* 246 */ "expr ::= RAISE LP IGNORE RP", | |
| 136136 | + /* 247 */ "expr ::= RAISE LP raisetype COMMA nm RP", | |
| 136137 | + /* 248 */ "raisetype ::= ROLLBACK", | |
| 136138 | + /* 249 */ "raisetype ::= ABORT", | |
| 136139 | + /* 250 */ "raisetype ::= FAIL", | |
| 136140 | + /* 251 */ "cmd ::= DROP TRIGGER ifexists fullname", | |
| 136141 | + /* 252 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", | |
| 136142 | + /* 253 */ "cmd ::= DETACH database_kw_opt expr", | |
| 136143 | + /* 254 */ "key_opt ::=", | |
| 136144 | + /* 255 */ "key_opt ::= KEY expr", | |
| 136145 | + /* 256 */ "cmd ::= REINDEX", | |
| 136146 | + /* 257 */ "cmd ::= REINDEX nm dbnm", | |
| 136147 | + /* 258 */ "cmd ::= ANALYZE", | |
| 136148 | + /* 259 */ "cmd ::= ANALYZE nm dbnm", | |
| 136149 | + /* 260 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", | |
| 136150 | + /* 261 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", | |
| 136151 | + /* 262 */ "add_column_fullname ::= fullname", | |
| 136152 | + /* 263 */ "cmd ::= create_vtab", | |
| 136153 | + /* 264 */ "cmd ::= create_vtab LP vtabarglist RP", | |
| 136154 | + /* 265 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", | |
| 136155 | + /* 266 */ "vtabarg ::=", | |
| 136156 | + /* 267 */ "vtabargtoken ::= ANY", | |
| 136157 | + /* 268 */ "vtabargtoken ::= lp anylist RP", | |
| 136158 | + /* 269 */ "lp ::= LP", | |
| 136159 | + /* 270 */ "with ::=", | |
| 136160 | + /* 271 */ "with ::= WITH wqlist", | |
| 136161 | + /* 272 */ "with ::= WITH RECURSIVE wqlist", | |
| 136162 | + /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", | |
| 136163 | + /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", | |
| 136164 | + /* 275 */ "input ::= cmdlist", | |
| 136165 | + /* 276 */ "cmdlist ::= cmdlist ecmd", | |
| 136166 | + /* 277 */ "cmdlist ::= ecmd", | |
| 136167 | + /* 278 */ "ecmd ::= SEMI", | |
| 136168 | + /* 279 */ "ecmd ::= explain cmdx SEMI", | |
| 136169 | + /* 280 */ "explain ::=", | |
| 136170 | + /* 281 */ "trans_opt ::=", | |
| 136171 | + /* 282 */ "trans_opt ::= TRANSACTION", | |
| 136172 | + /* 283 */ "trans_opt ::= TRANSACTION nm", | |
| 136173 | + /* 284 */ "savepoint_opt ::= SAVEPOINT", | |
| 136174 | + /* 285 */ "savepoint_opt ::=", | |
| 136175 | + /* 286 */ "cmd ::= create_table create_table_args", | |
| 136176 | + /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", | |
| 136177 | + /* 288 */ "columnlist ::= columnname carglist", | |
| 136178 | + /* 289 */ "nm ::= ID|INDEXED", | |
| 136179 | + /* 290 */ "nm ::= STRING", | |
| 136180 | + /* 291 */ "nm ::= JOIN_KW", | |
| 136181 | + /* 292 */ "typetoken ::= typename", | |
| 136182 | + /* 293 */ "typename ::= ID|STRING", | |
| 136183 | + /* 294 */ "signed ::= plus_num", | |
| 136184 | + /* 295 */ "signed ::= minus_num", | |
| 136185 | + /* 296 */ "carglist ::= carglist ccons", | |
| 136186 | + /* 297 */ "carglist ::=", | |
| 136187 | + /* 298 */ "ccons ::= NULL onconf", | |
| 136188 | + /* 299 */ "conslist_opt ::= COMMA conslist", | |
| 136189 | + /* 300 */ "conslist ::= conslist tconscomma tcons", | |
| 136190 | + /* 301 */ "conslist ::= tcons", | |
| 136191 | + /* 302 */ "tconscomma ::=", | |
| 136192 | + /* 303 */ "defer_subclause_opt ::= defer_subclause", | |
| 136193 | + /* 304 */ "resolvetype ::= raisetype", | |
| 136194 | + /* 305 */ "selectnowith ::= oneselect", | |
| 136195 | + /* 306 */ "oneselect ::= values", | |
| 136196 | + /* 307 */ "sclp ::= selcollist COMMA", | |
| 136197 | + /* 308 */ "as ::= ID|STRING", | |
| 136198 | + /* 309 */ "expr ::= term", | |
| 136199 | + /* 310 */ "likeop ::= LIKE_KW|MATCH", | |
| 135744 | 136200 | /* 311 */ "exprlist ::= nexprlist", |
| 135745 | 136201 | /* 312 */ "nmnum ::= plus_num", |
| 135746 | 136202 | /* 313 */ "nmnum ::= nm", |
| 135747 | 136203 | /* 314 */ "nmnum ::= ON", |
| 135748 | 136204 | /* 315 */ "nmnum ::= DELETE", |
| @@ -136375,11 +136831,10 @@ | ||
| 136375 | 136831 | { 173, 3 }, |
| 136376 | 136832 | { 173, 3 }, |
| 136377 | 136833 | { 173, 3 }, |
| 136378 | 136834 | { 173, 3 }, |
| 136379 | 136835 | { 173, 3 }, |
| 136380 | - { 221, 1 }, | |
| 136381 | 136836 | { 221, 2 }, |
| 136382 | 136837 | { 173, 3 }, |
| 136383 | 136838 | { 173, 5 }, |
| 136384 | 136839 | { 173, 2 }, |
| 136385 | 136840 | { 173, 3 }, |
| @@ -136512,10 +136967,11 @@ | ||
| 136512 | 136967 | { 194, 1 }, |
| 136513 | 136968 | { 195, 1 }, |
| 136514 | 136969 | { 209, 2 }, |
| 136515 | 136970 | { 210, 1 }, |
| 136516 | 136971 | { 173, 1 }, |
| 136972 | + { 221, 1 }, | |
| 136517 | 136973 | { 208, 1 }, |
| 136518 | 136974 | { 230, 1 }, |
| 136519 | 136975 | { 230, 1 }, |
| 136520 | 136976 | { 230, 1 }, |
| 136521 | 136977 | { 230, 1 }, |
| @@ -136654,11 +137110,11 @@ | ||
| 136654 | 137110 | case 42: /* autoinc ::= */ yytestcase(yyruleno==42); |
| 136655 | 137111 | case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); |
| 136656 | 137112 | case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); |
| 136657 | 137113 | case 76: /* ifexists ::= */ yytestcase(yyruleno==76); |
| 136658 | 137114 | case 90: /* distinct ::= */ yytestcase(yyruleno==90); |
| 136659 | - case 215: /* collate ::= */ yytestcase(yyruleno==215); | |
| 137115 | + case 214: /* collate ::= */ yytestcase(yyruleno==214); | |
| 136660 | 137116 | {yymsp[1].minor.yy194 = 0;} |
| 136661 | 137117 | break; |
| 136662 | 137118 | case 17: /* ifnotexists ::= IF NOT EXISTS */ |
| 136663 | 137119 | {yymsp[-2].minor.yy194 = 1;} |
| 136664 | 137120 | break; |
| @@ -136798,13 +137254,13 @@ | ||
| 136798 | 137254 | case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); |
| 136799 | 137255 | {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} |
| 136800 | 137256 | break; |
| 136801 | 137257 | case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ |
| 136802 | 137258 | case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); |
| 136803 | - case 187: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==187); | |
| 136804 | - case 190: /* in_op ::= NOT IN */ yytestcase(yyruleno==190); | |
| 136805 | - case 216: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==216); | |
| 137259 | + case 186: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==186); | |
| 137260 | + case 189: /* in_op ::= NOT IN */ yytestcase(yyruleno==189); | |
| 137261 | + case 215: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==215); | |
| 136806 | 137262 | {yymsp[-1].minor.yy194 = 1;} |
| 136807 | 137263 | break; |
| 136808 | 137264 | case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ |
| 136809 | 137265 | {yymsp[-1].minor.yy194 = 0;} |
| 136810 | 137266 | break; |
| @@ -136964,13 +137420,13 @@ | ||
| 136964 | 137420 | {yymsp[0].minor.yy194 = SF_All;} |
| 136965 | 137421 | break; |
| 136966 | 137422 | case 91: /* sclp ::= */ |
| 136967 | 137423 | case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); |
| 136968 | 137424 | case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); |
| 136969 | - case 203: /* exprlist ::= */ yytestcase(yyruleno==203); | |
| 136970 | - case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206); | |
| 136971 | - case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211); | |
| 137425 | + case 202: /* exprlist ::= */ yytestcase(yyruleno==202); | |
| 137426 | + case 205: /* paren_exprlist ::= */ yytestcase(yyruleno==205); | |
| 137427 | + case 210: /* eidlist_opt ::= */ yytestcase(yyruleno==210); | |
| 136972 | 137428 | {yymsp[1].minor.yy148 = 0;} |
| 136973 | 137429 | break; |
| 136974 | 137430 | case 92: /* selcollist ::= sclp expr as */ |
| 136975 | 137431 | { |
| 136976 | 137432 | yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| @@ -136992,12 +137448,12 @@ | ||
| 136992 | 137448 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); |
| 136993 | 137449 | } |
| 136994 | 137450 | break; |
| 136995 | 137451 | case 95: /* as ::= AS nm */ |
| 136996 | 137452 | case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); |
| 136997 | - case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225); | |
| 136998 | - case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226); | |
| 137453 | + case 224: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==224); | |
| 137454 | + case 225: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==225); | |
| 136999 | 137455 | {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} |
| 137000 | 137456 | break; |
| 137001 | 137457 | case 97: /* from ::= */ |
| 137002 | 137458 | {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} |
| 137003 | 137459 | break; |
| @@ -137076,18 +137532,18 @@ | ||
| 137076 | 137532 | {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} |
| 137077 | 137533 | break; |
| 137078 | 137534 | case 112: /* on_opt ::= ON expr */ |
| 137079 | 137535 | case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); |
| 137080 | 137536 | case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); |
| 137081 | - case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199); | |
| 137537 | + case 198: /* case_else ::= ELSE expr */ yytestcase(yyruleno==198); | |
| 137082 | 137538 | {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} |
| 137083 | 137539 | break; |
| 137084 | 137540 | case 113: /* on_opt ::= */ |
| 137085 | 137541 | case 128: /* having_opt ::= */ yytestcase(yyruleno==128); |
| 137086 | 137542 | case 135: /* where_opt ::= */ yytestcase(yyruleno==135); |
| 137087 | - case 200: /* case_else ::= */ yytestcase(yyruleno==200); | |
| 137088 | - case 202: /* case_operand ::= */ yytestcase(yyruleno==202); | |
| 137543 | + case 199: /* case_else ::= */ yytestcase(yyruleno==199); | |
| 137544 | + case 201: /* case_operand ::= */ yytestcase(yyruleno==201); | |
| 137089 | 137545 | {yymsp[1].minor.yy72 = 0;} |
| 137090 | 137546 | break; |
| 137091 | 137547 | case 115: /* indexed_opt ::= INDEXED BY nm */ |
| 137092 | 137548 | {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} |
| 137093 | 137549 | break; |
| @@ -137230,11 +137686,11 @@ | ||
| 137230 | 137686 | case 158: /* term ::= INTEGER */ |
| 137231 | 137687 | { |
| 137232 | 137688 | yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); |
| 137233 | 137689 | yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; |
| 137234 | 137690 | yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; |
| 137235 | - if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf; | |
| 137691 | + if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf|EP_Resolved; | |
| 137236 | 137692 | } |
| 137237 | 137693 | yymsp[0].minor.yy190 = yylhsminor.yy190; |
| 137238 | 137694 | break; |
| 137239 | 137695 | case 159: /* expr ::= VARIABLE */ |
| 137240 | 137696 | { |
| @@ -137320,17 +137776,14 @@ | ||
| 137320 | 137776 | case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); |
| 137321 | 137777 | case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); |
| 137322 | 137778 | case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); |
| 137323 | 137779 | {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} |
| 137324 | 137780 | break; |
| 137325 | - case 174: /* likeop ::= LIKE_KW|MATCH */ | |
| 137326 | -{yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/} | |
| 137327 | - break; | |
| 137328 | - case 175: /* likeop ::= NOT LIKE_KW|MATCH */ | |
| 137781 | + case 174: /* likeop ::= NOT LIKE_KW|MATCH */ | |
| 137329 | 137782 | {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} |
| 137330 | 137783 | break; |
| 137331 | - case 176: /* expr ::= expr likeop expr */ | |
| 137784 | + case 175: /* expr ::= expr likeop expr */ | |
| 137332 | 137785 | { |
| 137333 | 137786 | ExprList *pList; |
| 137334 | 137787 | int bNot = yymsp[-1].minor.yy0.n & 0x80000000; |
| 137335 | 137788 | yymsp[-1].minor.yy0.n &= 0x7fffffff; |
| 137336 | 137789 | pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); |
| @@ -137339,11 +137792,11 @@ | ||
| 137339 | 137792 | exprNot(pParse, bNot, &yymsp[-2].minor.yy190); |
| 137340 | 137793 | yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137341 | 137794 | if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 137342 | 137795 | } |
| 137343 | 137796 | break; |
| 137344 | - case 177: /* expr ::= expr likeop expr ESCAPE expr */ | |
| 137797 | + case 176: /* expr ::= expr likeop expr ESCAPE expr */ | |
| 137345 | 137798 | { |
| 137346 | 137799 | ExprList *pList; |
| 137347 | 137800 | int bNot = yymsp[-3].minor.yy0.n & 0x80000000; |
| 137348 | 137801 | yymsp[-3].minor.yy0.n &= 0x7fffffff; |
| 137349 | 137802 | pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| @@ -137353,43 +137806,43 @@ | ||
| 137353 | 137806 | exprNot(pParse, bNot, &yymsp[-4].minor.yy190); |
| 137354 | 137807 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137355 | 137808 | if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 137356 | 137809 | } |
| 137357 | 137810 | break; |
| 137358 | - case 178: /* expr ::= expr ISNULL|NOTNULL */ | |
| 137811 | + case 177: /* expr ::= expr ISNULL|NOTNULL */ | |
| 137359 | 137812 | {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} |
| 137360 | 137813 | break; |
| 137361 | - case 179: /* expr ::= expr NOT NULL */ | |
| 137814 | + case 178: /* expr ::= expr NOT NULL */ | |
| 137362 | 137815 | {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} |
| 137363 | 137816 | break; |
| 137364 | - case 180: /* expr ::= expr IS expr */ | |
| 137817 | + case 179: /* expr ::= expr IS expr */ | |
| 137365 | 137818 | { |
| 137366 | 137819 | spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); |
| 137367 | 137820 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); |
| 137368 | 137821 | } |
| 137369 | 137822 | break; |
| 137370 | - case 181: /* expr ::= expr IS NOT expr */ | |
| 137823 | + case 180: /* expr ::= expr IS NOT expr */ | |
| 137371 | 137824 | { |
| 137372 | 137825 | spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); |
| 137373 | 137826 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); |
| 137374 | 137827 | } |
| 137375 | 137828 | break; |
| 137376 | - case 182: /* expr ::= NOT expr */ | |
| 137377 | - case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183); | |
| 137829 | + case 181: /* expr ::= NOT expr */ | |
| 137830 | + case 182: /* expr ::= BITNOT expr */ yytestcase(yyruleno==182); | |
| 137378 | 137831 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137379 | 137832 | break; |
| 137380 | - case 184: /* expr ::= MINUS expr */ | |
| 137833 | + case 183: /* expr ::= MINUS expr */ | |
| 137381 | 137834 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137382 | 137835 | break; |
| 137383 | - case 185: /* expr ::= PLUS expr */ | |
| 137836 | + case 184: /* expr ::= PLUS expr */ | |
| 137384 | 137837 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137385 | 137838 | break; |
| 137386 | - case 186: /* between_op ::= BETWEEN */ | |
| 137387 | - case 189: /* in_op ::= IN */ yytestcase(yyruleno==189); | |
| 137839 | + case 185: /* between_op ::= BETWEEN */ | |
| 137840 | + case 188: /* in_op ::= IN */ yytestcase(yyruleno==188); | |
| 137388 | 137841 | {yymsp[0].minor.yy194 = 0;} |
| 137389 | 137842 | break; |
| 137390 | - case 188: /* expr ::= expr between_op expr AND expr */ | |
| 137843 | + case 187: /* expr ::= expr between_op expr AND expr */ | |
| 137391 | 137844 | { |
| 137392 | 137845 | ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 137393 | 137846 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 137394 | 137847 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); |
| 137395 | 137848 | if( yymsp[-4].minor.yy190.pExpr ){ |
| @@ -137399,11 +137852,11 @@ | ||
| 137399 | 137852 | } |
| 137400 | 137853 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137401 | 137854 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137402 | 137855 | } |
| 137403 | 137856 | break; |
| 137404 | - case 191: /* expr ::= expr in_op LP exprlist RP */ | |
| 137857 | + case 190: /* expr ::= expr in_op LP exprlist RP */ | |
| 137405 | 137858 | { |
| 137406 | 137859 | if( yymsp[-1].minor.yy148==0 ){ |
| 137407 | 137860 | /* Expressions of the form |
| 137408 | 137861 | ** |
| 137409 | 137862 | ** expr1 IN () |
| @@ -137452,26 +137905,26 @@ | ||
| 137452 | 137905 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137453 | 137906 | } |
| 137454 | 137907 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 137455 | 137908 | } |
| 137456 | 137909 | break; |
| 137457 | - case 192: /* expr ::= LP select RP */ | |
| 137910 | + case 191: /* expr ::= LP select RP */ | |
| 137458 | 137911 | { |
| 137459 | 137912 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 137460 | 137913 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); |
| 137461 | 137914 | sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 137462 | 137915 | } |
| 137463 | 137916 | break; |
| 137464 | - case 193: /* expr ::= expr in_op LP select RP */ | |
| 137917 | + case 192: /* expr ::= expr in_op LP select RP */ | |
| 137465 | 137918 | { |
| 137466 | 137919 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); |
| 137467 | 137920 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 137468 | 137921 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137469 | 137922 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 137470 | 137923 | } |
| 137471 | 137924 | break; |
| 137472 | - case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */ | |
| 137925 | + case 193: /* expr ::= expr in_op nm dbnm paren_exprlist */ | |
| 137473 | 137926 | { |
| 137474 | 137927 | SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); |
| 137475 | 137928 | Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); |
| 137476 | 137929 | if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); |
| 137477 | 137930 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); |
| @@ -137478,19 +137931,19 @@ | ||
| 137478 | 137931 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); |
| 137479 | 137932 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137480 | 137933 | yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; |
| 137481 | 137934 | } |
| 137482 | 137935 | break; |
| 137483 | - case 195: /* expr ::= EXISTS LP select RP */ | |
| 137936 | + case 194: /* expr ::= EXISTS LP select RP */ | |
| 137484 | 137937 | { |
| 137485 | 137938 | Expr *p; |
| 137486 | 137939 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 137487 | 137940 | p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); |
| 137488 | 137941 | sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); |
| 137489 | 137942 | } |
| 137490 | 137943 | break; |
| 137491 | - case 196: /* expr ::= CASE case_operand case_exprlist case_else END */ | |
| 137944 | + case 195: /* expr ::= CASE case_operand case_exprlist case_else END */ | |
| 137492 | 137945 | { |
| 137493 | 137946 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ |
| 137494 | 137947 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); |
| 137495 | 137948 | if( yymsp[-4].minor.yy190.pExpr ){ |
| 137496 | 137949 | yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; |
| @@ -137499,313 +137952,314 @@ | ||
| 137499 | 137952 | sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); |
| 137500 | 137953 | sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); |
| 137501 | 137954 | } |
| 137502 | 137955 | } |
| 137503 | 137956 | break; |
| 137504 | - case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ | |
| 137957 | + case 196: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ | |
| 137505 | 137958 | { |
| 137506 | 137959 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); |
| 137507 | 137960 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 137508 | 137961 | } |
| 137509 | 137962 | break; |
| 137510 | - case 198: /* case_exprlist ::= WHEN expr THEN expr */ | |
| 137963 | + case 197: /* case_exprlist ::= WHEN expr THEN expr */ | |
| 137511 | 137964 | { |
| 137512 | 137965 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 137513 | 137966 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 137514 | 137967 | } |
| 137515 | 137968 | break; |
| 137516 | - case 201: /* case_operand ::= expr */ | |
| 137969 | + case 200: /* case_operand ::= expr */ | |
| 137517 | 137970 | {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} |
| 137518 | 137971 | break; |
| 137519 | - case 204: /* nexprlist ::= nexprlist COMMA expr */ | |
| 137972 | + case 203: /* nexprlist ::= nexprlist COMMA expr */ | |
| 137520 | 137973 | {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} |
| 137521 | 137974 | break; |
| 137522 | - case 205: /* nexprlist ::= expr */ | |
| 137975 | + case 204: /* nexprlist ::= expr */ | |
| 137523 | 137976 | {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} |
| 137524 | 137977 | break; |
| 137525 | - case 207: /* paren_exprlist ::= LP exprlist RP */ | |
| 137526 | - case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212); | |
| 137978 | + case 206: /* paren_exprlist ::= LP exprlist RP */ | |
| 137979 | + case 211: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==211); | |
| 137527 | 137980 | {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} |
| 137528 | 137981 | break; |
| 137529 | - case 208: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ | |
| 137982 | + case 207: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ | |
| 137530 | 137983 | { |
| 137531 | 137984 | sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, |
| 137532 | 137985 | sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, |
| 137533 | 137986 | &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); |
| 137534 | 137987 | } |
| 137535 | 137988 | break; |
| 137536 | - case 209: /* uniqueflag ::= UNIQUE */ | |
| 137537 | - case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); | |
| 137989 | + case 208: /* uniqueflag ::= UNIQUE */ | |
| 137990 | + case 249: /* raisetype ::= ABORT */ yytestcase(yyruleno==249); | |
| 137538 | 137991 | {yymsp[0].minor.yy194 = OE_Abort;} |
| 137539 | 137992 | break; |
| 137540 | - case 210: /* uniqueflag ::= */ | |
| 137993 | + case 209: /* uniqueflag ::= */ | |
| 137541 | 137994 | {yymsp[1].minor.yy194 = OE_None;} |
| 137542 | 137995 | break; |
| 137543 | - case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */ | |
| 137996 | + case 212: /* eidlist ::= eidlist COMMA nm collate sortorder */ | |
| 137544 | 137997 | { |
| 137545 | 137998 | yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); |
| 137546 | 137999 | } |
| 137547 | 138000 | break; |
| 137548 | - case 214: /* eidlist ::= nm collate sortorder */ | |
| 138001 | + case 213: /* eidlist ::= nm collate sortorder */ | |
| 137549 | 138002 | { |
| 137550 | 138003 | yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ |
| 137551 | 138004 | } |
| 137552 | 138005 | break; |
| 137553 | - case 217: /* cmd ::= DROP INDEX ifexists fullname */ | |
| 138006 | + case 216: /* cmd ::= DROP INDEX ifexists fullname */ | |
| 137554 | 138007 | {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} |
| 137555 | 138008 | break; |
| 137556 | - case 218: /* cmd ::= VACUUM */ | |
| 138009 | + case 217: /* cmd ::= VACUUM */ | |
| 137557 | 138010 | {sqlite3Vacuum(pParse,0);} |
| 137558 | 138011 | break; |
| 137559 | - case 219: /* cmd ::= VACUUM nm */ | |
| 138012 | + case 218: /* cmd ::= VACUUM nm */ | |
| 137560 | 138013 | {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} |
| 137561 | 138014 | break; |
| 137562 | - case 220: /* cmd ::= PRAGMA nm dbnm */ | |
| 138015 | + case 219: /* cmd ::= PRAGMA nm dbnm */ | |
| 137563 | 138016 | {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} |
| 137564 | 138017 | break; |
| 137565 | - case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ | |
| 138018 | + case 220: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ | |
| 137566 | 138019 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} |
| 137567 | 138020 | break; |
| 137568 | - case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ | |
| 138021 | + case 221: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ | |
| 137569 | 138022 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} |
| 137570 | 138023 | break; |
| 137571 | - case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ | |
| 138024 | + case 222: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ | |
| 137572 | 138025 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} |
| 137573 | 138026 | break; |
| 137574 | - case 224: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ | |
| 138027 | + case 223: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ | |
| 137575 | 138028 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} |
| 137576 | 138029 | break; |
| 137577 | - case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ | |
| 138030 | + case 226: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ | |
| 137578 | 138031 | { |
| 137579 | 138032 | Token all; |
| 137580 | 138033 | all.z = yymsp[-3].minor.yy0.z; |
| 137581 | 138034 | all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; |
| 137582 | 138035 | sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); |
| 137583 | 138036 | } |
| 137584 | 138037 | break; |
| 137585 | - case 228: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ | |
| 138038 | + case 227: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ | |
| 137586 | 138039 | { |
| 137587 | 138040 | sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); |
| 137588 | 138041 | yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ |
| 137589 | 138042 | } |
| 137590 | 138043 | break; |
| 137591 | - case 229: /* trigger_time ::= BEFORE */ | |
| 138044 | + case 228: /* trigger_time ::= BEFORE */ | |
| 137592 | 138045 | { yymsp[0].minor.yy194 = TK_BEFORE; } |
| 137593 | 138046 | break; |
| 137594 | - case 230: /* trigger_time ::= AFTER */ | |
| 138047 | + case 229: /* trigger_time ::= AFTER */ | |
| 137595 | 138048 | { yymsp[0].minor.yy194 = TK_AFTER; } |
| 137596 | 138049 | break; |
| 137597 | - case 231: /* trigger_time ::= INSTEAD OF */ | |
| 138050 | + case 230: /* trigger_time ::= INSTEAD OF */ | |
| 137598 | 138051 | { yymsp[-1].minor.yy194 = TK_INSTEAD;} |
| 137599 | 138052 | break; |
| 137600 | - case 232: /* trigger_time ::= */ | |
| 138053 | + case 231: /* trigger_time ::= */ | |
| 137601 | 138054 | { yymsp[1].minor.yy194 = TK_BEFORE; } |
| 137602 | 138055 | break; |
| 137603 | - case 233: /* trigger_event ::= DELETE|INSERT */ | |
| 137604 | - case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); | |
| 138056 | + case 232: /* trigger_event ::= DELETE|INSERT */ | |
| 138057 | + case 233: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==233); | |
| 137605 | 138058 | {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} |
| 137606 | 138059 | break; |
| 137607 | - case 235: /* trigger_event ::= UPDATE OF idlist */ | |
| 138060 | + case 234: /* trigger_event ::= UPDATE OF idlist */ | |
| 137608 | 138061 | {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} |
| 137609 | 138062 | break; |
| 137610 | - case 236: /* when_clause ::= */ | |
| 137611 | - case 255: /* key_opt ::= */ yytestcase(yyruleno==255); | |
| 138063 | + case 235: /* when_clause ::= */ | |
| 138064 | + case 254: /* key_opt ::= */ yytestcase(yyruleno==254); | |
| 137612 | 138065 | { yymsp[1].minor.yy72 = 0; } |
| 137613 | 138066 | break; |
| 137614 | - case 237: /* when_clause ::= WHEN expr */ | |
| 137615 | - case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); | |
| 138067 | + case 236: /* when_clause ::= WHEN expr */ | |
| 138068 | + case 255: /* key_opt ::= KEY expr */ yytestcase(yyruleno==255); | |
| 137616 | 138069 | { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } |
| 137617 | 138070 | break; |
| 137618 | - case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ | |
| 138071 | + case 237: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ | |
| 137619 | 138072 | { |
| 137620 | 138073 | assert( yymsp[-2].minor.yy145!=0 ); |
| 137621 | 138074 | yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; |
| 137622 | 138075 | yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 137623 | 138076 | } |
| 137624 | 138077 | break; |
| 137625 | - case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ | |
| 138078 | + case 238: /* trigger_cmd_list ::= trigger_cmd SEMI */ | |
| 137626 | 138079 | { |
| 137627 | 138080 | assert( yymsp[-1].minor.yy145!=0 ); |
| 137628 | 138081 | yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 137629 | 138082 | } |
| 137630 | 138083 | break; |
| 137631 | - case 240: /* trnm ::= nm DOT nm */ | |
| 138084 | + case 239: /* trnm ::= nm DOT nm */ | |
| 137632 | 138085 | { |
| 137633 | 138086 | yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; |
| 137634 | 138087 | sqlite3ErrorMsg(pParse, |
| 137635 | 138088 | "qualified table names are not allowed on INSERT, UPDATE, and DELETE " |
| 137636 | 138089 | "statements within triggers"); |
| 137637 | 138090 | } |
| 137638 | 138091 | break; |
| 137639 | - case 241: /* tridxby ::= INDEXED BY nm */ | |
| 138092 | + case 240: /* tridxby ::= INDEXED BY nm */ | |
| 137640 | 138093 | { |
| 137641 | 138094 | sqlite3ErrorMsg(pParse, |
| 137642 | 138095 | "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " |
| 137643 | 138096 | "within triggers"); |
| 137644 | 138097 | } |
| 137645 | 138098 | break; |
| 137646 | - case 242: /* tridxby ::= NOT INDEXED */ | |
| 138099 | + case 241: /* tridxby ::= NOT INDEXED */ | |
| 137647 | 138100 | { |
| 137648 | 138101 | sqlite3ErrorMsg(pParse, |
| 137649 | 138102 | "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " |
| 137650 | 138103 | "within triggers"); |
| 137651 | 138104 | } |
| 137652 | 138105 | break; |
| 137653 | - case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ | |
| 138106 | + case 242: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ | |
| 137654 | 138107 | {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} |
| 137655 | 138108 | break; |
| 137656 | - case 244: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ | |
| 138109 | + case 243: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ | |
| 137657 | 138110 | {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} |
| 137658 | 138111 | break; |
| 137659 | - case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ | |
| 138112 | + case 244: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ | |
| 137660 | 138113 | {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} |
| 137661 | 138114 | break; |
| 137662 | - case 246: /* trigger_cmd ::= select */ | |
| 138115 | + case 245: /* trigger_cmd ::= select */ | |
| 137663 | 138116 | {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} |
| 137664 | 138117 | break; |
| 137665 | - case 247: /* expr ::= RAISE LP IGNORE RP */ | |
| 138118 | + case 246: /* expr ::= RAISE LP IGNORE RP */ | |
| 137666 | 138119 | { |
| 137667 | 138120 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 137668 | 138121 | yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); |
| 137669 | 138122 | if( yymsp[-3].minor.yy190.pExpr ){ |
| 137670 | 138123 | yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; |
| 137671 | 138124 | } |
| 137672 | 138125 | } |
| 137673 | 138126 | break; |
| 137674 | - case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ | |
| 138127 | + case 247: /* expr ::= RAISE LP raisetype COMMA nm RP */ | |
| 137675 | 138128 | { |
| 137676 | 138129 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 137677 | 138130 | yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); |
| 137678 | 138131 | if( yymsp[-5].minor.yy190.pExpr ) { |
| 137679 | 138132 | yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; |
| 137680 | 138133 | } |
| 137681 | 138134 | } |
| 137682 | 138135 | break; |
| 137683 | - case 249: /* raisetype ::= ROLLBACK */ | |
| 138136 | + case 248: /* raisetype ::= ROLLBACK */ | |
| 137684 | 138137 | {yymsp[0].minor.yy194 = OE_Rollback;} |
| 137685 | 138138 | break; |
| 137686 | - case 251: /* raisetype ::= FAIL */ | |
| 138139 | + case 250: /* raisetype ::= FAIL */ | |
| 137687 | 138140 | {yymsp[0].minor.yy194 = OE_Fail;} |
| 137688 | 138141 | break; |
| 137689 | - case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ | |
| 138142 | + case 251: /* cmd ::= DROP TRIGGER ifexists fullname */ | |
| 137690 | 138143 | { |
| 137691 | 138144 | sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); |
| 137692 | 138145 | } |
| 137693 | 138146 | break; |
| 137694 | - case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ | |
| 138147 | + case 252: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ | |
| 137695 | 138148 | { |
| 137696 | 138149 | sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); |
| 137697 | 138150 | } |
| 137698 | 138151 | break; |
| 137699 | - case 254: /* cmd ::= DETACH database_kw_opt expr */ | |
| 138152 | + case 253: /* cmd ::= DETACH database_kw_opt expr */ | |
| 137700 | 138153 | { |
| 137701 | 138154 | sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); |
| 137702 | 138155 | } |
| 137703 | 138156 | break; |
| 137704 | - case 257: /* cmd ::= REINDEX */ | |
| 138157 | + case 256: /* cmd ::= REINDEX */ | |
| 137705 | 138158 | {sqlite3Reindex(pParse, 0, 0);} |
| 137706 | 138159 | break; |
| 137707 | - case 258: /* cmd ::= REINDEX nm dbnm */ | |
| 138160 | + case 257: /* cmd ::= REINDEX nm dbnm */ | |
| 137708 | 138161 | {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 137709 | 138162 | break; |
| 137710 | - case 259: /* cmd ::= ANALYZE */ | |
| 138163 | + case 258: /* cmd ::= ANALYZE */ | |
| 137711 | 138164 | {sqlite3Analyze(pParse, 0, 0);} |
| 137712 | 138165 | break; |
| 137713 | - case 260: /* cmd ::= ANALYZE nm dbnm */ | |
| 138166 | + case 259: /* cmd ::= ANALYZE nm dbnm */ | |
| 137714 | 138167 | {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 137715 | 138168 | break; |
| 137716 | - case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ | |
| 138169 | + case 260: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ | |
| 137717 | 138170 | { |
| 137718 | 138171 | sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); |
| 137719 | 138172 | } |
| 137720 | 138173 | break; |
| 137721 | - case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ | |
| 138174 | + case 261: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ | |
| 137722 | 138175 | { |
| 137723 | 138176 | yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; |
| 137724 | 138177 | sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); |
| 137725 | 138178 | } |
| 137726 | 138179 | break; |
| 137727 | - case 263: /* add_column_fullname ::= fullname */ | |
| 138180 | + case 262: /* add_column_fullname ::= fullname */ | |
| 137728 | 138181 | { |
| 137729 | 138182 | disableLookaside(pParse); |
| 137730 | 138183 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); |
| 137731 | 138184 | } |
| 137732 | 138185 | break; |
| 137733 | - case 264: /* cmd ::= create_vtab */ | |
| 138186 | + case 263: /* cmd ::= create_vtab */ | |
| 137734 | 138187 | {sqlite3VtabFinishParse(pParse,0);} |
| 137735 | 138188 | break; |
| 137736 | - case 265: /* cmd ::= create_vtab LP vtabarglist RP */ | |
| 138189 | + case 264: /* cmd ::= create_vtab LP vtabarglist RP */ | |
| 137737 | 138190 | {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} |
| 137738 | 138191 | break; |
| 137739 | - case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ | |
| 138192 | + case 265: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ | |
| 137740 | 138193 | { |
| 137741 | 138194 | sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); |
| 137742 | 138195 | } |
| 137743 | 138196 | break; |
| 137744 | - case 267: /* vtabarg ::= */ | |
| 138197 | + case 266: /* vtabarg ::= */ | |
| 137745 | 138198 | {sqlite3VtabArgInit(pParse);} |
| 137746 | 138199 | break; |
| 137747 | - case 268: /* vtabargtoken ::= ANY */ | |
| 137748 | - case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); | |
| 137749 | - case 270: /* lp ::= LP */ yytestcase(yyruleno==270); | |
| 138200 | + case 267: /* vtabargtoken ::= ANY */ | |
| 138201 | + case 268: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==268); | |
| 138202 | + case 269: /* lp ::= LP */ yytestcase(yyruleno==269); | |
| 137750 | 138203 | {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} |
| 137751 | 138204 | break; |
| 137752 | - case 271: /* with ::= */ | |
| 138205 | + case 270: /* with ::= */ | |
| 137753 | 138206 | {yymsp[1].minor.yy285 = 0;} |
| 137754 | 138207 | break; |
| 137755 | - case 272: /* with ::= WITH wqlist */ | |
| 138208 | + case 271: /* with ::= WITH wqlist */ | |
| 137756 | 138209 | { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } |
| 137757 | 138210 | break; |
| 137758 | - case 273: /* with ::= WITH RECURSIVE wqlist */ | |
| 138211 | + case 272: /* with ::= WITH RECURSIVE wqlist */ | |
| 137759 | 138212 | { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } |
| 137760 | 138213 | break; |
| 137761 | - case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */ | |
| 138214 | + case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ | |
| 137762 | 138215 | { |
| 137763 | 138216 | yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ |
| 137764 | 138217 | } |
| 137765 | 138218 | break; |
| 137766 | - case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ | |
| 138219 | + case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ | |
| 137767 | 138220 | { |
| 137768 | 138221 | yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); |
| 137769 | 138222 | } |
| 137770 | 138223 | break; |
| 137771 | 138224 | default: |
| 137772 | - /* (276) input ::= cmdlist */ yytestcase(yyruleno==276); | |
| 137773 | - /* (277) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==277); | |
| 137774 | - /* (278) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=278); | |
| 137775 | - /* (279) ecmd ::= SEMI */ yytestcase(yyruleno==279); | |
| 137776 | - /* (280) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==280); | |
| 137777 | - /* (281) explain ::= */ yytestcase(yyruleno==281); | |
| 137778 | - /* (282) trans_opt ::= */ yytestcase(yyruleno==282); | |
| 137779 | - /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283); | |
| 137780 | - /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284); | |
| 137781 | - /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285); | |
| 137782 | - /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286); | |
| 137783 | - /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287); | |
| 137784 | - /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288); | |
| 137785 | - /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289); | |
| 137786 | - /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290); | |
| 137787 | - /* (291) nm ::= STRING */ yytestcase(yyruleno==291); | |
| 137788 | - /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292); | |
| 137789 | - /* (293) typetoken ::= typename */ yytestcase(yyruleno==293); | |
| 137790 | - /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294); | |
| 137791 | - /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); | |
| 137792 | - /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296); | |
| 137793 | - /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297); | |
| 137794 | - /* (298) carglist ::= */ yytestcase(yyruleno==298); | |
| 137795 | - /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299); | |
| 137796 | - /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300); | |
| 137797 | - /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301); | |
| 137798 | - /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302); | |
| 137799 | - /* (303) tconscomma ::= */ yytestcase(yyruleno==303); | |
| 137800 | - /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304); | |
| 137801 | - /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305); | |
| 137802 | - /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306); | |
| 137803 | - /* (307) oneselect ::= values */ yytestcase(yyruleno==307); | |
| 137804 | - /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308); | |
| 137805 | - /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309); | |
| 137806 | - /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310); | |
| 138225 | + /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); | |
| 138226 | + /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); | |
| 138227 | + /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); | |
| 138228 | + /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); | |
| 138229 | + /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); | |
| 138230 | + /* (280) explain ::= */ yytestcase(yyruleno==280); | |
| 138231 | + /* (281) trans_opt ::= */ yytestcase(yyruleno==281); | |
| 138232 | + /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); | |
| 138233 | + /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); | |
| 138234 | + /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); | |
| 138235 | + /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); | |
| 138236 | + /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); | |
| 138237 | + /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); | |
| 138238 | + /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); | |
| 138239 | + /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); | |
| 138240 | + /* (290) nm ::= STRING */ yytestcase(yyruleno==290); | |
| 138241 | + /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); | |
| 138242 | + /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); | |
| 138243 | + /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); | |
| 138244 | + /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); | |
| 138245 | + /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); | |
| 138246 | + /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); | |
| 138247 | + /* (297) carglist ::= */ yytestcase(yyruleno==297); | |
| 138248 | + /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); | |
| 138249 | + /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); | |
| 138250 | + /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); | |
| 138251 | + /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); | |
| 138252 | + /* (302) tconscomma ::= */ yytestcase(yyruleno==302); | |
| 138253 | + /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); | |
| 138254 | + /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); | |
| 138255 | + /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); | |
| 138256 | + /* (306) oneselect ::= values */ yytestcase(yyruleno==306); | |
| 138257 | + /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); | |
| 138258 | + /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); | |
| 138259 | + /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); | |
| 138260 | + /* (310) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==310); | |
| 137807 | 138261 | /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); |
| 137808 | 138262 | /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); |
| 137809 | 138263 | /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); |
| 137810 | 138264 | /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); |
| 137811 | 138265 | /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); |
| @@ -138854,12 +139308,12 @@ | ||
| 138854 | 139308 | ** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that |
| 138855 | 139309 | ** error message. |
| 138856 | 139310 | */ |
| 138857 | 139311 | SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ |
| 138858 | 139312 | int nErr = 0; /* Number of errors encountered */ |
| 138859 | - int i; /* Loop counter */ | |
| 138860 | 139313 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 139314 | + int n = 0; /* Length of the next token token */ | |
| 138861 | 139315 | int tokenType; /* type of the next token */ |
| 138862 | 139316 | int lastTokenParsed = -1; /* type of the previous token */ |
| 138863 | 139317 | sqlite3 *db = pParse->db; /* The database connection */ |
| 138864 | 139318 | int mxSqlLen; /* Max length of an SQL string */ |
| 138865 | 139319 | #ifdef sqlite3Parser_ENGINEALWAYSONSTACK |
| @@ -138871,11 +139325,10 @@ | ||
| 138871 | 139325 | if( db->nVdbeActive==0 ){ |
| 138872 | 139326 | db->u1.isInterrupted = 0; |
| 138873 | 139327 | } |
| 138874 | 139328 | pParse->rc = SQLITE_OK; |
| 138875 | 139329 | pParse->zTail = zSql; |
| 138876 | - i = 0; | |
| 138877 | 139330 | assert( pzErrMsg!=0 ); |
| 138878 | 139331 | /* sqlite3ParserTrace(stdout, "parser: "); */ |
| 138879 | 139332 | #ifdef sqlite3Parser_ENGINEALWAYSONSTACK |
| 138880 | 139333 | pEngine = zSpace; |
| 138881 | 139334 | sqlite3ParserInit(pEngine); |
| @@ -138889,16 +139342,14 @@ | ||
| 138889 | 139342 | assert( pParse->pNewTable==0 ); |
| 138890 | 139343 | assert( pParse->pNewTrigger==0 ); |
| 138891 | 139344 | assert( pParse->nVar==0 ); |
| 138892 | 139345 | assert( pParse->pVList==0 ); |
| 138893 | 139346 | while( 1 ){ |
| 138894 | - assert( i>=0 ); | |
| 138895 | - if( zSql[i]!=0 ){ | |
| 138896 | - pParse->sLastToken.z = &zSql[i]; | |
| 138897 | - pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType); | |
| 138898 | - i += pParse->sLastToken.n; | |
| 138899 | - if( i>mxSqlLen ){ | |
| 139347 | + if( zSql[0]!=0 ){ | |
| 139348 | + n = sqlite3GetToken((u8*)zSql, &tokenType); | |
| 139349 | + mxSqlLen -= n; | |
| 139350 | + if( mxSqlLen<0 ){ | |
| 138900 | 139351 | pParse->rc = SQLITE_TOOBIG; |
| 138901 | 139352 | break; |
| 138902 | 139353 | } |
| 138903 | 139354 | }else{ |
| 138904 | 139355 | /* Upon reaching the end of input, call the parser two more times |
| @@ -138908,30 +139359,34 @@ | ||
| 138908 | 139359 | }else if( lastTokenParsed==0 ){ |
| 138909 | 139360 | break; |
| 138910 | 139361 | }else{ |
| 138911 | 139362 | tokenType = TK_SEMI; |
| 138912 | 139363 | } |
| 139364 | + zSql -= n; | |
| 138913 | 139365 | } |
| 138914 | 139366 | if( tokenType>=TK_SPACE ){ |
| 138915 | 139367 | assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); |
| 138916 | 139368 | if( db->u1.isInterrupted ){ |
| 138917 | 139369 | pParse->rc = SQLITE_INTERRUPT; |
| 138918 | 139370 | break; |
| 138919 | 139371 | } |
| 138920 | 139372 | if( tokenType==TK_ILLEGAL ){ |
| 138921 | - sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", | |
| 138922 | - &pParse->sLastToken); | |
| 139373 | + sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); | |
| 138923 | 139374 | break; |
| 138924 | 139375 | } |
| 139376 | + zSql += n; | |
| 138925 | 139377 | }else{ |
| 139378 | + pParse->sLastToken.z = zSql; | |
| 139379 | + pParse->sLastToken.n = n; | |
| 138926 | 139380 | sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); |
| 138927 | 139381 | lastTokenParsed = tokenType; |
| 139382 | + zSql += n; | |
| 138928 | 139383 | if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; |
| 138929 | 139384 | } |
| 138930 | 139385 | } |
| 138931 | 139386 | assert( nErr==0 ); |
| 138932 | - pParse->zTail = &zSql[i]; | |
| 139387 | + pParse->zTail = zSql; | |
| 138933 | 139388 | #ifdef YYTRACKMAXSTACKDEPTH |
| 138934 | 139389 | sqlite3_mutex_enter(sqlite3MallocMutex()); |
| 138935 | 139390 | sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, |
| 138936 | 139391 | sqlite3ParserStackPeak(pEngine) |
| 138937 | 139392 | ); |
| @@ -140301,10 +140756,25 @@ | ||
| 140301 | 140756 | return 0; |
| 140302 | 140757 | } |
| 140303 | 140758 | #endif |
| 140304 | 140759 | return db->lastRowid; |
| 140305 | 140760 | } |
| 140761 | + | |
| 140762 | +/* | |
| 140763 | +** Set the value returned by the sqlite3_last_insert_rowid() API function. | |
| 140764 | +*/ | |
| 140765 | +SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){ | |
| 140766 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 140767 | + if( !sqlite3SafetyCheckOk(db) ){ | |
| 140768 | + (void)SQLITE_MISUSE_BKPT; | |
| 140769 | + return; | |
| 140770 | + } | |
| 140771 | +#endif | |
| 140772 | + sqlite3_mutex_enter(db->mutex); | |
| 140773 | + db->lastRowid = iRowid; | |
| 140774 | + sqlite3_mutex_leave(db->mutex); | |
| 140775 | +} | |
| 140306 | 140776 | |
| 140307 | 140777 | /* |
| 140308 | 140778 | ** Return the number of changes in the most recent call to sqlite3_exec(). |
| 140309 | 140779 | */ |
| 140310 | 140780 | SQLITE_API int sqlite3_changes(sqlite3 *db){ |
| @@ -148111,12 +148581,14 @@ | ||
| 148111 | 148581 | ** segments. |
| 148112 | 148582 | */ |
| 148113 | 148583 | const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ |
| 148114 | 148584 | |
| 148115 | 148585 | Fts3Table *p = (Fts3Table*)pVtab; |
| 148116 | - int rc = sqlite3Fts3PendingTermsFlush(p); | |
| 148586 | + int rc; | |
| 148587 | + i64 iLastRowid = sqlite3_last_insert_rowid(p->db); | |
| 148117 | 148588 | |
| 148589 | + rc = sqlite3Fts3PendingTermsFlush(p); | |
| 148118 | 148590 | if( rc==SQLITE_OK |
| 148119 | 148591 | && p->nLeafAdd>(nMinMerge/16) |
| 148120 | 148592 | && p->nAutoincrmerge && p->nAutoincrmerge!=0xff |
| 148121 | 148593 | ){ |
| 148122 | 148594 | int mxLevel = 0; /* Maximum relative level value in db */ |
| @@ -148127,10 +148599,11 @@ | ||
| 148127 | 148599 | A = p->nLeafAdd * mxLevel; |
| 148128 | 148600 | A += (A/2); |
| 148129 | 148601 | if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); |
| 148130 | 148602 | } |
| 148131 | 148603 | sqlite3Fts3SegmentsClose(p); |
| 148604 | + sqlite3_set_last_insert_rowid(p->db, iLastRowid); | |
| 148132 | 148605 | return rc; |
| 148133 | 148606 | } |
| 148134 | 148607 | |
| 148135 | 148608 | /* |
| 148136 | 148609 | ** If it is currently unknown whether or not the FTS table has an %_stat |
| @@ -168462,10 +168935,11 @@ | ||
| 168462 | 168935 | int nStep; /* Rows processed for current object */ |
| 168463 | 168936 | int nProgress; /* Rows processed for all objects */ |
| 168464 | 168937 | RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ |
| 168465 | 168938 | const char *zVfsName; /* Name of automatically created rbu vfs */ |
| 168466 | 168939 | rbu_file *pTargetFd; /* File handle open on target db */ |
| 168940 | + int nPagePerSector; /* Pages per sector for pTargetFd */ | |
| 168467 | 168941 | i64 iOalSz; |
| 168468 | 168942 | i64 nPhaseOneStep; |
| 168469 | 168943 | |
| 168470 | 168944 | /* The following state variables are used as part of the incremental |
| 168471 | 168945 | ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding |
| @@ -170726,10 +171200,27 @@ | ||
| 170726 | 171200 | |
| 170727 | 171201 | if( p->rc==SQLITE_OK ){ |
| 170728 | 171202 | if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){ |
| 170729 | 171203 | p->rc = SQLITE_DONE; |
| 170730 | 171204 | p->eStage = RBU_STAGE_DONE; |
| 171205 | + }else{ | |
| 171206 | + int nSectorSize; | |
| 171207 | + sqlite3_file *pDb = p->pTargetFd->pReal; | |
| 171208 | + sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal; | |
| 171209 | + assert( p->nPagePerSector==0 ); | |
| 171210 | + nSectorSize = pDb->pMethods->xSectorSize(pDb); | |
| 171211 | + if( nSectorSize>p->pgsz ){ | |
| 171212 | + p->nPagePerSector = nSectorSize / p->pgsz; | |
| 171213 | + }else{ | |
| 171214 | + p->nPagePerSector = 1; | |
| 171215 | + } | |
| 171216 | + | |
| 171217 | + /* Call xSync() on the wal file. This causes SQLite to sync the | |
| 171218 | + ** directory in which the target database and the wal file reside, in | |
| 171219 | + ** case it has not been synced since the rename() call in | |
| 171220 | + ** rbuMoveOalFile(). */ | |
| 171221 | + p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL); | |
| 170731 | 171222 | } |
| 170732 | 171223 | } |
| 170733 | 171224 | } |
| 170734 | 171225 | |
| 170735 | 171226 | /* |
| @@ -171381,13 +171872,30 @@ | ||
| 171381 | 171872 | if( p->rc==SQLITE_OK ){ |
| 171382 | 171873 | p->eStage = RBU_STAGE_DONE; |
| 171383 | 171874 | p->rc = SQLITE_DONE; |
| 171384 | 171875 | } |
| 171385 | 171876 | }else{ |
| 171386 | - RbuFrame *pFrame = &p->aFrame[p->nStep]; | |
| 171387 | - rbuCheckpointFrame(p, pFrame); | |
| 171388 | - p->nStep++; | |
| 171877 | + /* At one point the following block copied a single frame from the | |
| 171878 | + ** wal file to the database file. So that one call to sqlite3rbu_step() | |
| 171879 | + ** checkpointed a single frame. | |
| 171880 | + ** | |
| 171881 | + ** However, if the sector-size is larger than the page-size, and the | |
| 171882 | + ** application calls sqlite3rbu_savestate() or close() immediately | |
| 171883 | + ** after this step, then rbu_step() again, then a power failure occurs, | |
| 171884 | + ** then the database page written here may be damaged. Work around | |
| 171885 | + ** this by checkpointing frames until the next page in the aFrame[] | |
| 171886 | + ** lies on a different disk sector to the current one. */ | |
| 171887 | + u32 iSector; | |
| 171888 | + do{ | |
| 171889 | + RbuFrame *pFrame = &p->aFrame[p->nStep]; | |
| 171890 | + iSector = (pFrame->iDbPage-1) / p->nPagePerSector; | |
| 171891 | + rbuCheckpointFrame(p, pFrame); | |
| 171892 | + p->nStep++; | |
| 171893 | + }while( p->nStep<p->nFrame | |
| 171894 | + && iSector==((p->aFrame[p->nStep].iDbPage-1) / p->nPagePerSector) | |
| 171895 | + && p->rc==SQLITE_OK | |
| 171896 | + ); | |
| 171389 | 171897 | } |
| 171390 | 171898 | p->nProgress++; |
| 171391 | 171899 | } |
| 171392 | 171900 | break; |
| 171393 | 171901 | } |
| @@ -171823,10 +172331,16 @@ | ||
| 171823 | 172331 | |
| 171824 | 172332 | /* Commit the transaction to the *-oal file. */ |
| 171825 | 172333 | if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ |
| 171826 | 172334 | p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); |
| 171827 | 172335 | } |
| 172336 | + | |
| 172337 | + /* Sync the db file if currently doing an incremental checkpoint */ | |
| 172338 | + if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){ | |
| 172339 | + sqlite3_file *pDb = p->pTargetFd->pReal; | |
| 172340 | + p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); | |
| 172341 | + } | |
| 171828 | 172342 | |
| 171829 | 172343 | rbuSaveState(p, p->eStage); |
| 171830 | 172344 | |
| 171831 | 172345 | if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ |
| 171832 | 172346 | p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); |
| @@ -171947,10 +172461,16 @@ | ||
| 171947 | 172461 | assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE ); |
| 171948 | 172462 | if( p->eStage==RBU_STAGE_OAL ){ |
| 171949 | 172463 | assert( rc!=SQLITE_DONE ); |
| 171950 | 172464 | if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0); |
| 171951 | 172465 | } |
| 172466 | + | |
| 172467 | + /* Sync the db file */ | |
| 172468 | + if( rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){ | |
| 172469 | + sqlite3_file *pDb = p->pTargetFd->pReal; | |
| 172470 | + rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); | |
| 172471 | + } | |
| 171952 | 172472 | |
| 171953 | 172473 | p->rc = rc; |
| 171954 | 172474 | rbuSaveState(p, p->eStage); |
| 171955 | 172475 | rc = p->rc; |
| 171956 | 172476 | |
| @@ -181079,11 +181599,13 @@ | ||
| 181079 | 181599 | typedef unsigned short u16; |
| 181080 | 181600 | typedef short i16; |
| 181081 | 181601 | typedef sqlite3_int64 i64; |
| 181082 | 181602 | typedef sqlite3_uint64 u64; |
| 181083 | 181603 | |
| 181084 | -#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) | |
| 181604 | +#ifndef ArraySize | |
| 181605 | +# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) | |
| 181606 | +#endif | |
| 181085 | 181607 | |
| 181086 | 181608 | #define testcase(x) |
| 181087 | 181609 | #define ALWAYS(x) 1 |
| 181088 | 181610 | #define NEVER(x) 0 |
| 181089 | 181611 | |
| @@ -186302,11 +186824,14 @@ | ||
| 186302 | 186824 | if( p1->bEof==0 ){ |
| 186303 | 186825 | if( (p1->iRowid==iLast) |
| 186304 | 186826 | || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) |
| 186305 | 186827 | ){ |
| 186306 | 186828 | int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); |
| 186307 | - if( rc!=SQLITE_OK ) return rc; | |
| 186829 | + if( rc!=SQLITE_OK ){ | |
| 186830 | + pNode->bNomatch = 0; | |
| 186831 | + return rc; | |
| 186832 | + } | |
| 186308 | 186833 | } |
| 186309 | 186834 | } |
| 186310 | 186835 | } |
| 186311 | 186836 | |
| 186312 | 186837 | fts5ExprNodeTest_OR(pExpr, pNode); |
| @@ -186333,11 +186858,14 @@ | ||
| 186333 | 186858 | Fts5ExprNode *pChild = pAnd->apChild[iChild]; |
| 186334 | 186859 | int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); |
| 186335 | 186860 | if( cmp>0 ){ |
| 186336 | 186861 | /* Advance pChild until it points to iLast or laster */ |
| 186337 | 186862 | rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); |
| 186338 | - if( rc!=SQLITE_OK ) return rc; | |
| 186863 | + if( rc!=SQLITE_OK ){ | |
| 186864 | + pAnd->bNomatch = 0; | |
| 186865 | + return rc; | |
| 186866 | + } | |
| 186339 | 186867 | } |
| 186340 | 186868 | |
| 186341 | 186869 | /* If the child node is now at EOF, so is the parent AND node. Otherwise, |
| 186342 | 186870 | ** the child node is guaranteed to have advanced at least as far as |
| 186343 | 186871 | ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the |
| @@ -186372,10 +186900,12 @@ | ||
| 186372 | 186900 | i64 iFrom |
| 186373 | 186901 | ){ |
| 186374 | 186902 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 186375 | 186903 | if( rc==SQLITE_OK ){ |
| 186376 | 186904 | rc = fts5ExprNodeTest_AND(pExpr, pNode); |
| 186905 | + }else{ | |
| 186906 | + pNode->bNomatch = 0; | |
| 186377 | 186907 | } |
| 186378 | 186908 | return rc; |
| 186379 | 186909 | } |
| 186380 | 186910 | |
| 186381 | 186911 | static int fts5ExprNodeTest_NOT( |
| @@ -186414,10 +186944,13 @@ | ||
| 186414 | 186944 | ){ |
| 186415 | 186945 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 186416 | 186946 | if( rc==SQLITE_OK ){ |
| 186417 | 186947 | rc = fts5ExprNodeTest_NOT(pExpr, pNode); |
| 186418 | 186948 | } |
| 186949 | + if( rc!=SQLITE_OK ){ | |
| 186950 | + pNode->bNomatch = 0; | |
| 186951 | + } | |
| 186419 | 186952 | return rc; |
| 186420 | 186953 | } |
| 186421 | 186954 | |
| 186422 | 186955 | /* |
| 186423 | 186956 | ** If pNode currently points to a match, this function returns SQLITE_OK |
| @@ -197534,11 +198067,11 @@ | ||
| 197534 | 198067 | int nArg, /* Number of args */ |
| 197535 | 198068 | sqlite3_value **apUnused /* Function arguments */ |
| 197536 | 198069 | ){ |
| 197537 | 198070 | assert( nArg==0 ); |
| 197538 | 198071 | UNUSED_PARAM2(nArg, apUnused); |
| 197539 | - sqlite3_result_text(pCtx, "fts5: 2017-02-13 16:02:40 ada05cfa86ad7f5645450ac7a2a21c9aa6e57d2c", -1, SQLITE_TRANSIENT); | |
| 198072 | + sqlite3_result_text(pCtx, "fts5: 2017-03-10 17:03:11 f8560c60d10c0365b33342ab05b5a953987b0471", -1, SQLITE_TRANSIENT); | |
| 197540 | 198073 | } |
| 197541 | 198074 | |
| 197542 | 198075 | static int fts5Init(sqlite3 *db){ |
| 197543 | 198076 | static const sqlite3_module fts5Mod = { |
| 197544 | 198077 | /* iVersion */ 2, |
| @@ -198197,15 +198730,10 @@ | ||
| 198197 | 198730 | sqlite3_step(pDel); |
| 198198 | 198731 | rc = sqlite3_reset(pDel); |
| 198199 | 198732 | } |
| 198200 | 198733 | } |
| 198201 | 198734 | |
| 198202 | - /* Write the averages record */ | |
| 198203 | - if( rc==SQLITE_OK ){ | |
| 198204 | - rc = fts5StorageSaveTotals(p); | |
| 198205 | - } | |
| 198206 | - | |
| 198207 | 198735 | return rc; |
| 198208 | 198736 | } |
| 198209 | 198737 | |
| 198210 | 198738 | /* |
| 198211 | 198739 | ** Delete all entries in the FTS5 index. |
| @@ -198405,15 +198933,10 @@ | ||
| 198405 | 198933 | if( rc==SQLITE_OK ){ |
| 198406 | 198934 | rc = fts5StorageInsertDocsize(p, iRowid, &buf); |
| 198407 | 198935 | } |
| 198408 | 198936 | sqlite3_free(buf.p); |
| 198409 | 198937 | |
| 198410 | - /* Write the averages record */ | |
| 198411 | - if( rc==SQLITE_OK ){ | |
| 198412 | - rc = fts5StorageSaveTotals(p); | |
| 198413 | - } | |
| 198414 | - | |
| 198415 | 198938 | return rc; |
| 198416 | 198939 | } |
| 198417 | 198940 | |
| 198418 | 198941 | static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){ |
| 198419 | 198942 | Fts5Config *pConfig = p->pConfig; |
| @@ -198744,16 +199267,21 @@ | ||
| 198744 | 199267 | |
| 198745 | 199268 | /* |
| 198746 | 199269 | ** Flush any data currently held in-memory to disk. |
| 198747 | 199270 | */ |
| 198748 | 199271 | static int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){ |
| 198749 | - if( bCommit && p->bTotalsValid ){ | |
| 198750 | - int rc = fts5StorageSaveTotals(p); | |
| 198751 | - p->bTotalsValid = 0; | |
| 198752 | - if( rc!=SQLITE_OK ) return rc; | |
| 199272 | + int rc = SQLITE_OK; | |
| 199273 | + i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db); | |
| 199274 | + if( p->bTotalsValid ){ | |
| 199275 | + rc = fts5StorageSaveTotals(p); | |
| 199276 | + if( bCommit ) p->bTotalsValid = 0; | |
| 198753 | 199277 | } |
| 198754 | - return sqlite3Fts5IndexSync(p->pIndex, bCommit); | |
| 199278 | + if( rc==SQLITE_OK ){ | |
| 199279 | + rc = sqlite3Fts5IndexSync(p->pIndex, bCommit); | |
| 199280 | + } | |
| 199281 | + sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid); | |
| 199282 | + return rc; | |
| 198755 | 199283 | } |
| 198756 | 199284 | |
| 198757 | 199285 | static int sqlite3Fts5StorageRollback(Fts5Storage *p){ |
| 198758 | 199286 | p->bTotalsValid = 0; |
| 198759 | 199287 | return sqlite3Fts5IndexRollback(p->pIndex); |
| 198760 | 199288 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.17.0. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -396,13 +396,13 @@ | |
| 396 | ** |
| 397 | ** See also: [sqlite3_libversion()], |
| 398 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 399 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 400 | */ |
| 401 | #define SQLITE_VERSION "3.17.0" |
| 402 | #define SQLITE_VERSION_NUMBER 3017000 |
| 403 | #define SQLITE_SOURCE_ID "2017-02-13 16:02:40 ada05cfa86ad7f5645450ac7a2a21c9aa6e57d2c" |
| 404 | |
| 405 | /* |
| 406 | ** CAPI3REF: Run-Time Library Version Numbers |
| 407 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 408 | ** |
| @@ -2315,24 +2315,34 @@ | |
| 2315 | ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those |
| 2316 | ** names are not also used by explicitly declared columns. ^If |
| 2317 | ** the table has a column of type [INTEGER PRIMARY KEY] then that column |
| 2318 | ** is another alias for the rowid. |
| 2319 | ** |
| 2320 | ** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the |
| 2321 | ** most recent successful [INSERT] into a rowid table or [virtual table] |
| 2322 | ** on database connection D. |
| 2323 | ** ^Inserts into [WITHOUT ROWID] tables are not recorded. |
| 2324 | ** ^If no successful [INSERT]s into rowid tables |
| 2325 | ** have ever occurred on the database connection D, |
| 2326 | ** then sqlite3_last_insert_rowid(D) returns zero. |
| 2327 | ** |
| 2328 | ** ^(If an [INSERT] occurs within a trigger or within a [virtual table] |
| 2329 | ** method, then this routine will return the [rowid] of the inserted |
| 2330 | ** row as long as the trigger or virtual table method is running. |
| 2331 | ** But once the trigger or virtual table method ends, the value returned |
| 2332 | ** by this routine reverts to what it was before the trigger or virtual |
| 2333 | ** table method began.)^ |
| 2334 | ** |
| 2335 | ** ^An [INSERT] that fails due to a constraint violation is not a |
| 2336 | ** successful [INSERT] and does not change the value returned by this |
| 2337 | ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, |
| 2338 | ** and INSERT OR ABORT make no changes to the return value of this |
| @@ -2355,10 +2365,20 @@ | |
| 2355 | ** unpredictable and might not equal either the old or the new |
| 2356 | ** last insert [rowid]. |
| 2357 | */ |
| 2358 | SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); |
| 2359 | |
| 2360 | /* |
| 2361 | ** CAPI3REF: Count The Number Of Rows Modified |
| 2362 | ** METHOD: sqlite3 |
| 2363 | ** |
| 2364 | ** ^This function returns the number of rows modified, inserted or |
| @@ -12457,10 +12477,11 @@ | |
| 12457 | SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); |
| 12458 | SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); |
| 12459 | |
| 12460 | SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); |
| 12461 | SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); |
| 12462 | |
| 12463 | #ifndef SQLITE_OMIT_INCRBLOB |
| 12464 | SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*); |
| 12465 | SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); |
| 12466 | SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); |
| @@ -12757,117 +12778,119 @@ | |
| 12757 | #define OP_Divide 50 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ |
| 12758 | #define OP_Remainder 51 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ |
| 12759 | #define OP_Concat 52 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ |
| 12760 | #define OP_Last 53 |
| 12761 | #define OP_BitNot 54 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ |
| 12762 | #define OP_SorterSort 55 |
| 12763 | #define OP_Sort 56 |
| 12764 | #define OP_Rewind 57 |
| 12765 | #define OP_IdxLE 58 /* synopsis: key=r[P3@P4] */ |
| 12766 | #define OP_IdxGT 59 /* synopsis: key=r[P3@P4] */ |
| 12767 | #define OP_IdxLT 60 /* synopsis: key=r[P3@P4] */ |
| 12768 | #define OP_IdxGE 61 /* synopsis: key=r[P3@P4] */ |
| 12769 | #define OP_RowSetRead 62 /* synopsis: r[P3]=rowset(P1) */ |
| 12770 | #define OP_RowSetTest 63 /* synopsis: if r[P3] in rowset(P1) goto P2 */ |
| 12771 | #define OP_Program 64 |
| 12772 | #define OP_FkIfZero 65 /* synopsis: if fkctr[P1]==0 goto P2 */ |
| 12773 | #define OP_IfPos 66 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ |
| 12774 | #define OP_IfNotZero 67 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ |
| 12775 | #define OP_DecrJumpZero 68 /* synopsis: if (--r[P1])==0 goto P2 */ |
| 12776 | #define OP_IncrVacuum 69 |
| 12777 | #define OP_VNext 70 |
| 12778 | #define OP_Init 71 /* synopsis: Start at P2 */ |
| 12779 | #define OP_Return 72 |
| 12780 | #define OP_EndCoroutine 73 |
| 12781 | #define OP_HaltIfNull 74 /* synopsis: if r[P3]=null halt */ |
| 12782 | #define OP_Halt 75 |
| 12783 | #define OP_Integer 76 /* synopsis: r[P2]=P1 */ |
| 12784 | #define OP_Int64 77 /* synopsis: r[P2]=P4 */ |
| 12785 | #define OP_String 78 /* synopsis: r[P2]='P4' (len=P1) */ |
| 12786 | #define OP_Null 79 /* synopsis: r[P2..P3]=NULL */ |
| 12787 | #define OP_SoftNull 80 /* synopsis: r[P1]=NULL */ |
| 12788 | #define OP_Blob 81 /* synopsis: r[P2]=P4 (len=P1) */ |
| 12789 | #define OP_Variable 82 /* synopsis: r[P2]=parameter(P1,P4) */ |
| 12790 | #define OP_Move 83 /* synopsis: r[P2@P3]=r[P1@P3] */ |
| 12791 | #define OP_Copy 84 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ |
| 12792 | #define OP_SCopy 85 /* synopsis: r[P2]=r[P1] */ |
| 12793 | #define OP_IntCopy 86 /* synopsis: r[P2]=r[P1] */ |
| 12794 | #define OP_ResultRow 87 /* synopsis: output=r[P1@P2] */ |
| 12795 | #define OP_CollSeq 88 |
| 12796 | #define OP_Function0 89 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 12797 | #define OP_Function 90 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 12798 | #define OP_AddImm 91 /* synopsis: r[P1]=r[P1]+P2 */ |
| 12799 | #define OP_RealAffinity 92 |
| 12800 | #define OP_Cast 93 /* synopsis: affinity(r[P1]) */ |
| 12801 | #define OP_Permutation 94 |
| 12802 | #define OP_Compare 95 /* synopsis: r[P1@P3] <-> r[P2@P3] */ |
| 12803 | #define OP_Column 96 /* synopsis: r[P3]=PX */ |
| 12804 | #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ |
| 12805 | #define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ |
| 12806 | #define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ |
| 12807 | #define OP_Count 100 /* synopsis: r[P2]=count() */ |
| 12808 | #define OP_ReadCookie 101 |
| 12809 | #define OP_SetCookie 102 |
| 12810 | #define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */ |
| 12811 | #define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */ |
| 12812 | #define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */ |
| 12813 | #define OP_OpenAutoindex 106 /* synopsis: nColumn=P2 */ |
| 12814 | #define OP_OpenEphemeral 107 /* synopsis: nColumn=P2 */ |
| 12815 | #define OP_SorterOpen 108 |
| 12816 | #define OP_SequenceTest 109 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ |
| 12817 | #define OP_OpenPseudo 110 /* synopsis: P3 columns in r[P2] */ |
| 12818 | #define OP_Close 111 |
| 12819 | #define OP_ColumnsUsed 112 |
| 12820 | #define OP_Sequence 113 /* synopsis: r[P2]=cursor[P1].ctr++ */ |
| 12821 | #define OP_NewRowid 114 /* synopsis: r[P2]=rowid */ |
| 12822 | #define OP_Insert 115 /* synopsis: intkey=r[P3] data=r[P2] */ |
| 12823 | #define OP_InsertInt 116 /* synopsis: intkey=P3 data=r[P2] */ |
| 12824 | #define OP_Delete 117 |
| 12825 | #define OP_ResetCount 118 |
| 12826 | #define OP_SorterCompare 119 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ |
| 12827 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12828 | #define OP_RowData 121 /* synopsis: r[P2]=data */ |
| 12829 | #define OP_Rowid 122 /* synopsis: r[P2]=rowid */ |
| 12830 | #define OP_NullRow 123 |
| 12831 | #define OP_SorterInsert 124 /* synopsis: key=r[P2] */ |
| 12832 | #define OP_IdxInsert 125 /* synopsis: key=r[P2] */ |
| 12833 | #define OP_IdxDelete 126 /* synopsis: key=r[P2@P3] */ |
| 12834 | #define OP_Seek 127 /* synopsis: Move P3 to P1.rowid */ |
| 12835 | #define OP_IdxRowid 128 /* synopsis: r[P2]=rowid */ |
| 12836 | #define OP_Destroy 129 |
| 12837 | #define OP_Clear 130 |
| 12838 | #define OP_ResetSorter 131 |
| 12839 | #define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 12840 | #define OP_CreateIndex 133 /* synopsis: r[P2]=root iDb=P1 */ |
| 12841 | #define OP_CreateTable 134 /* synopsis: r[P2]=root iDb=P1 */ |
| 12842 | #define OP_ParseSchema 135 |
| 12843 | #define OP_LoadAnalysis 136 |
| 12844 | #define OP_DropTable 137 |
| 12845 | #define OP_DropIndex 138 |
| 12846 | #define OP_DropTrigger 139 |
| 12847 | #define OP_IntegrityCk 140 |
| 12848 | #define OP_RowSetAdd 141 /* synopsis: rowset(P1)=r[P2] */ |
| 12849 | #define OP_Param 142 |
| 12850 | #define OP_FkCounter 143 /* synopsis: fkctr[P1]+=P2 */ |
| 12851 | #define OP_MemMax 144 /* synopsis: r[P1]=max(r[P1],r[P2]) */ |
| 12852 | #define OP_OffsetLimit 145 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ |
| 12853 | #define OP_AggStep0 146 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 12854 | #define OP_AggStep 147 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 12855 | #define OP_AggFinal 148 /* synopsis: accum=r[P1] N=P2 */ |
| 12856 | #define OP_Expire 149 |
| 12857 | #define OP_TableLock 150 /* synopsis: iDb=P1 root=P2 write=P3 */ |
| 12858 | #define OP_VBegin 151 |
| 12859 | #define OP_VCreate 152 |
| 12860 | #define OP_VDestroy 153 |
| 12861 | #define OP_VOpen 154 |
| 12862 | #define OP_VColumn 155 /* synopsis: r[P3]=vcolumn(P2) */ |
| 12863 | #define OP_VRename 156 |
| 12864 | #define OP_Pagecount 157 |
| 12865 | #define OP_MaxPgcnt 158 |
| 12866 | #define OP_CursorHint 159 |
| 12867 | #define OP_Noop 160 |
| 12868 | #define OP_Explain 161 |
| 12869 | |
| 12870 | /* Properties such as "out2" or "jump" that are specified in |
| 12871 | ** comments following the "case" for each opcode in the vdbe.c |
| 12872 | ** are encoded into bitvectors as follows: |
| 12873 | */ |
| @@ -12883,32 +12906,32 @@ | |
| 12883 | /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x09,\ |
| 12884 | /* 24 */ 0x09, 0x09, 0x09, 0x26, 0x26, 0x09, 0x09, 0x09,\ |
| 12885 | /* 32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ |
| 12886 | /* 40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\ |
| 12887 | /* 48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\ |
| 12888 | /* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0b,\ |
| 12889 | /* 64 */ 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01,\ |
| 12890 | /* 72 */ 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10,\ |
| 12891 | /* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,\ |
| 12892 | /* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ |
| 12893 | /* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ |
| 12894 | /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12895 | /* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12896 | /* 120 */ 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00, 0x00,\ |
| 12897 | /* 128 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\ |
| 12898 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\ |
| 12899 | /* 144 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12900 | /* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ |
| 12901 | /* 160 */ 0x00, 0x00,} |
| 12902 | |
| 12903 | /* The sqlite3P2Values() routine is able to run faster if it knows |
| 12904 | ** the value of the largest JUMP opcode. The smaller the maximum |
| 12905 | ** JUMP opcode the better, so the mkopcodeh.tcl script that |
| 12906 | ** generated this include file strives to group all JUMP opcodes |
| 12907 | ** together near the beginning of the list. |
| 12908 | */ |
| 12909 | #define SQLITE_MX_JUMP_OPCODE 71 /* Maximum JUMP opcode */ |
| 12910 | |
| 12911 | /************** End of opcodes.h *********************************************/ |
| 12912 | /************** Continuing where we left off in vdbe.h ***********************/ |
| 12913 | |
| 12914 | /* |
| @@ -14074,10 +14097,11 @@ | |
| 14074 | u8 suppressErr; /* Do not issue error messages if true */ |
| 14075 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
| 14076 | u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ |
| 14077 | u8 mTrace; /* zero or more SQLITE_TRACE flags */ |
| 14078 | u8 skipBtreeMutex; /* True if no shared-cache backends */ |
| 14079 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 14080 | u32 magic; /* Magic number for detect library misuse */ |
| 14081 | int nChange; /* Value returned by sqlite3_changes() */ |
| 14082 | int nTotalChange; /* Value returned by sqlite3_total_changes() */ |
| 14083 | int aLimit[SQLITE_N_LIMIT]; /* Limits */ |
| @@ -14589,18 +14613,18 @@ | |
| 14589 | char *zColAff; /* String defining the affinity of each column */ |
| 14590 | ExprList *pCheck; /* All CHECK constraints */ |
| 14591 | /* ... also used as column name list in a VIEW */ |
| 14592 | int tnum; /* Root BTree page for this table */ |
| 14593 | u32 nTabRef; /* Number of pointers to this Table */ |
| 14594 | i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ |
| 14595 | i16 nCol; /* Number of columns in this table */ |
| 14596 | LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ |
| 14597 | LogEst szTabRow; /* Estimated size of each table row in bytes */ |
| 14598 | #ifdef SQLITE_ENABLE_COSTMULT |
| 14599 | LogEst costMult; /* Cost multiplier for using this table */ |
| 14600 | #endif |
| 14601 | u8 tabFlags; /* Mask of TF_* values */ |
| 14602 | u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ |
| 14603 | #ifndef SQLITE_OMIT_ALTERTABLE |
| 14604 | int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ |
| 14605 | #endif |
| 14606 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| @@ -14620,27 +14644,29 @@ | |
| 14620 | ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING |
| 14621 | ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, |
| 14622 | ** the TF_OOOHidden attribute would apply in this case. Such tables require |
| 14623 | ** special handling during INSERT processing. |
| 14624 | */ |
| 14625 | #define TF_Readonly 0x01 /* Read-only system table */ |
| 14626 | #define TF_Ephemeral 0x02 /* An ephemeral table */ |
| 14627 | #define TF_HasPrimaryKey 0x04 /* Table has a primary key */ |
| 14628 | #define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ |
| 14629 | #define TF_Virtual 0x10 /* Is a virtual table */ |
| 14630 | #define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */ |
| 14631 | #define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */ |
| 14632 | #define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */ |
| 14633 | |
| 14634 | |
| 14635 | /* |
| 14636 | ** Test to see whether or not a table is a virtual table. This is |
| 14637 | ** done as a macro so that it will be optimized out when virtual |
| 14638 | ** table support is omitted from the build. |
| 14639 | */ |
| 14640 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 14641 | # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) |
| 14642 | #else |
| 14643 | # define IsVirtual(X) 0 |
| 14644 | #endif |
| 14645 | |
| 14646 | /* |
| @@ -14871,10 +14897,11 @@ | |
| 14871 | unsigned bUnordered:1; /* Use this index for == or IN queries only */ |
| 14872 | unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ |
| 14873 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ |
| 14874 | unsigned isCovering:1; /* True if this is a covering index */ |
| 14875 | unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ |
| 14876 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 14877 | int nSample; /* Number of elements in aSample[] */ |
| 14878 | int nSampleCol; /* Size of IndexSample.anEq[] and so on */ |
| 14879 | tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ |
| 14880 | IndexSample *aSample; /* Samples of the left-most key */ |
| @@ -15181,11 +15208,11 @@ | |
| 15181 | ** form is used for name resolution with nested FROM clauses. |
| 15182 | */ |
| 15183 | struct ExprList { |
| 15184 | int nExpr; /* Number of expressions on the list */ |
| 15185 | struct ExprList_item { /* For each expression in the list */ |
| 15186 | Expr *pExpr; /* The list of expressions */ |
| 15187 | char *zName; /* Token associated with this expression */ |
| 15188 | char *zSpan; /* Original text of the expression */ |
| 15189 | u8 sortOrder; /* 1 for DESC or 0 for ASC */ |
| 15190 | unsigned done :1; /* A flag to indicate when processing is finished */ |
| 15191 | unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ |
| @@ -16504,10 +16531,11 @@ | |
| 16504 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); |
| 16505 | SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*); |
| 16506 | SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int); |
| 16507 | SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); |
| 16508 | SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int); |
| 16509 | SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); |
| 16510 | SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int); |
| 16511 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); |
| 16512 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); |
| 16513 | SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); |
| @@ -17450,11 +17478,11 @@ | |
| 17450 | "COMPILER=gcc-" __VERSION__, |
| 17451 | #endif |
| 17452 | #if SQLITE_COVERAGE_TEST |
| 17453 | "COVERAGE_TEST", |
| 17454 | #endif |
| 17455 | #if SQLITE_DEBUG |
| 17456 | "DEBUG", |
| 17457 | #endif |
| 17458 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17459 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17460 | #endif |
| @@ -19505,22 +19533,23 @@ | |
| 19505 | ** |
| 19506 | ** Move the date backwards to the beginning of the current day, |
| 19507 | ** or month or year. |
| 19508 | */ |
| 19509 | if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break; |
| 19510 | z += 9; |
| 19511 | computeYMD(p); |
| 19512 | p->validHMS = 1; |
| 19513 | p->h = p->m = 0; |
| 19514 | p->s = 0.0; |
| 19515 | p->validTZ = 0; |
| 19516 | p->validJD = 0; |
| 19517 | if( sqlite3_stricmp(z,"month")==0 ){ |
| 19518 | p->D = 1; |
| 19519 | rc = 0; |
| 19520 | }else if( sqlite3_stricmp(z,"year")==0 ){ |
| 19521 | computeYMD(p); |
| 19522 | p->M = 1; |
| 19523 | p->D = 1; |
| 19524 | rc = 0; |
| 19525 | }else if( sqlite3_stricmp(z,"day")==0 ){ |
| 19526 | rc = 0; |
| @@ -24050,12 +24079,12 @@ | |
| 24050 | #ifdef SQLITE_DEBUG |
| 24051 | assert( p->nRef>0 || p->owner==0 ); |
| 24052 | p->owner = tid; |
| 24053 | p->nRef++; |
| 24054 | if( p->trace ){ |
| 24055 | OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", |
| 24056 | tid, p, p->trace, p->nRef)); |
| 24057 | } |
| 24058 | #endif |
| 24059 | } |
| 24060 | |
| 24061 | static int winMutexTry(sqlite3_mutex *p){ |
| @@ -24093,12 +24122,12 @@ | |
| 24093 | #else |
| 24094 | UNUSED_PARAMETER(p); |
| 24095 | #endif |
| 24096 | #ifdef SQLITE_DEBUG |
| 24097 | if( p->trace ){ |
| 24098 | OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n", |
| 24099 | tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); |
| 24100 | } |
| 24101 | #endif |
| 24102 | return rc; |
| 24103 | } |
| 24104 | |
| @@ -24122,12 +24151,12 @@ | |
| 24122 | #endif |
| 24123 | assert( winMutex_isInit==1 ); |
| 24124 | LeaveCriticalSection(&p->mutex); |
| 24125 | #ifdef SQLITE_DEBUG |
| 24126 | if( p->trace ){ |
| 24127 | OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", |
| 24128 | tid, p, p->trace, p->nRef)); |
| 24129 | } |
| 24130 | #endif |
| 24131 | } |
| 24132 | |
| 24133 | SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ |
| @@ -24383,10 +24412,17 @@ | |
| 24383 | ** implementation of malloc_good_size(), which must be called in debug |
| 24384 | ** mode and specifically when the DMD "Dark Matter Detector" is enabled |
| 24385 | ** or else a crash results. Hence, do not attempt to optimize out the |
| 24386 | ** following xRoundup() call. */ |
| 24387 | nFull = sqlite3GlobalConfig.m.xRoundup(n); |
| 24388 | |
| 24389 | sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); |
| 24390 | if( mem0.alarmThreshold>0 ){ |
| 24391 | sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); |
| 24392 | if( nUsed >= mem0.alarmThreshold - nFull ){ |
| @@ -24572,11 +24608,11 @@ | |
| 24572 | return sqlite3GlobalConfig.m.xSize(p); |
| 24573 | } |
| 24574 | SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ |
| 24575 | assert( p!=0 ); |
| 24576 | if( db==0 || !isLookaside(db,p) ){ |
| 24577 | #if SQLITE_DEBUG |
| 24578 | if( db==0 ){ |
| 24579 | assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); |
| 24580 | assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); |
| 24581 | }else{ |
| 24582 | assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| @@ -24633,11 +24669,11 @@ | |
| 24633 | measureAllocationSize(db, p); |
| 24634 | return; |
| 24635 | } |
| 24636 | if( isLookaside(db, p) ){ |
| 24637 | LookasideSlot *pBuf = (LookasideSlot*)p; |
| 24638 | #if SQLITE_DEBUG |
| 24639 | /* Trash all content in the buffer being freed */ |
| 24640 | memset(p, 0xaa, db->lookaside.sz); |
| 24641 | #endif |
| 24642 | pBuf->pNext = db->lookaside.pFree; |
| 24643 | db->lookaside.pFree = pBuf; |
| @@ -25002,11 +25038,11 @@ | |
| 25002 | |
| 25003 | /* |
| 25004 | ** Conversion types fall into various categories as defined by the |
| 25005 | ** following enumeration. |
| 25006 | */ |
| 25007 | #define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */ |
| 25008 | #define etFLOAT 1 /* Floating point. %f */ |
| 25009 | #define etEXP 2 /* Exponentional notation. %e and %E */ |
| 25010 | #define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ |
| 25011 | #define etSIZE 4 /* Return number of characters processed so far. %n */ |
| 25012 | #define etSTRING 5 /* Strings. %s */ |
| @@ -25020,12 +25056,13 @@ | |
| 25020 | #define etTOKEN 11 /* a pointer to a Token structure */ |
| 25021 | #define etSRCLIST 12 /* a pointer to a SrcList */ |
| 25022 | #define etPOINTER 13 /* The %p conversion */ |
| 25023 | #define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ |
| 25024 | #define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ |
| 25025 | |
| 25026 | #define etINVALID 16 /* Any unrecognized conversion type */ |
| 25027 | |
| 25028 | |
| 25029 | /* |
| 25030 | ** An "etByte" is an 8-bit unsigned value. |
| 25031 | */ |
| @@ -25045,40 +25082,40 @@ | |
| 25045 | } et_info; |
| 25046 | |
| 25047 | /* |
| 25048 | ** Allowed values for et_info.flags |
| 25049 | */ |
| 25050 | #define FLAG_SIGNED 1 /* True if the value to convert is signed */ |
| 25051 | #define FLAG_STRING 4 /* Allow infinity precision */ |
| 25052 | |
| 25053 | |
| 25054 | /* |
| 25055 | ** The following table is searched linearly, so it is good to put the |
| 25056 | ** most frequently used conversion types first. |
| 25057 | */ |
| 25058 | static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; |
| 25059 | static const char aPrefix[] = "-x0\000X0"; |
| 25060 | static const et_info fmtinfo[] = { |
| 25061 | { 'd', 10, 1, etRADIX, 0, 0 }, |
| 25062 | { 's', 0, 4, etSTRING, 0, 0 }, |
| 25063 | { 'g', 0, 1, etGENERIC, 30, 0 }, |
| 25064 | { 'z', 0, 4, etDYNSTRING, 0, 0 }, |
| 25065 | { 'q', 0, 4, etSQLESCAPE, 0, 0 }, |
| 25066 | { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, |
| 25067 | { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, |
| 25068 | { 'c', 0, 0, etCHARX, 0, 0 }, |
| 25069 | { 'o', 8, 0, etRADIX, 0, 2 }, |
| 25070 | { 'u', 10, 0, etRADIX, 0, 0 }, |
| 25071 | { 'x', 16, 0, etRADIX, 16, 1 }, |
| 25072 | { 'X', 16, 0, etRADIX, 0, 4 }, |
| 25073 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 25074 | { 'f', 0, 1, etFLOAT, 0, 0 }, |
| 25075 | { 'e', 0, 1, etEXP, 30, 0 }, |
| 25076 | { 'E', 0, 1, etEXP, 14, 0 }, |
| 25077 | { 'G', 0, 1, etGENERIC, 14, 0 }, |
| 25078 | #endif |
| 25079 | { 'i', 10, 1, etRADIX, 0, 0 }, |
| 25080 | { 'n', 0, 0, etSIZE, 0, 0 }, |
| 25081 | { '%', 0, 0, etPERCENT, 0, 0 }, |
| 25082 | { 'p', 16, 0, etPOINTER, 0, 1 }, |
| 25083 | |
| 25084 | /* All the rest are undocumented and are for internal use only */ |
| @@ -25166,18 +25203,17 @@ | |
| 25166 | int precision; /* Precision of the current field */ |
| 25167 | int length; /* Length of the field */ |
| 25168 | int idx; /* A general purpose loop counter */ |
| 25169 | int width; /* Width of the current field */ |
| 25170 | etByte flag_leftjustify; /* True if "-" flag is present */ |
| 25171 | etByte flag_plussign; /* True if "+" flag is present */ |
| 25172 | etByte flag_blanksign; /* True if " " flag is present */ |
| 25173 | etByte flag_alternateform; /* True if "#" flag is present */ |
| 25174 | etByte flag_altform2; /* True if "!" flag is present */ |
| 25175 | etByte flag_zeropad; /* True if field width constant starts with zero */ |
| 25176 | etByte flag_long; /* True if "l" flag is present */ |
| 25177 | etByte flag_longlong; /* True if the "ll" flag is present */ |
| 25178 | etByte done; /* Loop termination flag */ |
| 25179 | etByte xtype = etINVALID; /* Conversion paradigm */ |
| 25180 | u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ |
| 25181 | char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ |
| 25182 | sqlite_uint64 longvalue; /* Value for integer types */ |
| 25183 | LONGDOUBLE_TYPE realvalue; /* Value for real types */ |
| @@ -25216,21 +25252,22 @@ | |
| 25216 | if( (c=(*++fmt))==0 ){ |
| 25217 | sqlite3StrAccumAppend(pAccum, "%", 1); |
| 25218 | break; |
| 25219 | } |
| 25220 | /* Find out what flags are present */ |
| 25221 | flag_leftjustify = flag_plussign = flag_blanksign = |
| 25222 | flag_alternateform = flag_altform2 = flag_zeropad = 0; |
| 25223 | done = 0; |
| 25224 | do{ |
| 25225 | switch( c ){ |
| 25226 | case '-': flag_leftjustify = 1; break; |
| 25227 | case '+': flag_plussign = 1; break; |
| 25228 | case ' ': flag_blanksign = 1; break; |
| 25229 | case '#': flag_alternateform = 1; break; |
| 25230 | case '!': flag_altform2 = 1; break; |
| 25231 | case '0': flag_zeropad = 1; break; |
| 25232 | default: done = 1; break; |
| 25233 | } |
| 25234 | }while( !done && (c=(*++fmt))!=0 ); |
| 25235 | /* Get the field width */ |
| 25236 | if( c=='*' ){ |
| @@ -25296,17 +25333,15 @@ | |
| 25296 | /* Get the conversion type modifier */ |
| 25297 | if( c=='l' ){ |
| 25298 | flag_long = 1; |
| 25299 | c = *++fmt; |
| 25300 | if( c=='l' ){ |
| 25301 | flag_longlong = 1; |
| 25302 | c = *++fmt; |
| 25303 | }else{ |
| 25304 | flag_longlong = 0; |
| 25305 | } |
| 25306 | }else{ |
| 25307 | flag_long = flag_longlong = 0; |
| 25308 | } |
| 25309 | /* Fetch the info entry for the field */ |
| 25310 | infop = &fmtinfo[0]; |
| 25311 | xtype = etINVALID; |
| 25312 | for(idx=0; idx<ArraySize(fmtinfo); idx++){ |
| @@ -25320,41 +25355,42 @@ | |
| 25320 | /* |
| 25321 | ** At this point, variables are initialized as follows: |
| 25322 | ** |
| 25323 | ** flag_alternateform TRUE if a '#' is present. |
| 25324 | ** flag_altform2 TRUE if a '!' is present. |
| 25325 | ** flag_plussign TRUE if a '+' is present. |
| 25326 | ** flag_leftjustify TRUE if a '-' is present or if the |
| 25327 | ** field width was negative. |
| 25328 | ** flag_zeropad TRUE if the width began with 0. |
| 25329 | ** flag_long TRUE if the letter 'l' (ell) prefixed |
| 25330 | ** the conversion character. |
| 25331 | ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed |
| 25332 | ** the conversion character. |
| 25333 | ** flag_blanksign TRUE if a ' ' is present. |
| 25334 | ** width The specified field width. This is |
| 25335 | ** always non-negative. Zero is the default. |
| 25336 | ** precision The specified precision. The default |
| 25337 | ** is -1. |
| 25338 | ** xtype The class of the conversion. |
| 25339 | ** infop Pointer to the appropriate info struct. |
| 25340 | */ |
| 25341 | switch( xtype ){ |
| 25342 | case etPOINTER: |
| 25343 | flag_longlong = sizeof(char*)==sizeof(i64); |
| 25344 | flag_long = sizeof(char*)==sizeof(long int); |
| 25345 | /* Fall through into the next case */ |
| 25346 | case etORDINAL: |
| 25347 | case etRADIX: |
| 25348 | if( infop->flags & FLAG_SIGNED ){ |
| 25349 | i64 v; |
| 25350 | if( bArgList ){ |
| 25351 | v = getIntArg(pArgList); |
| 25352 | }else if( flag_longlong ){ |
| 25353 | v = va_arg(ap,i64); |
| 25354 | }else if( flag_long ){ |
| 25355 | v = va_arg(ap,long int); |
| 25356 | }else{ |
| 25357 | v = va_arg(ap,int); |
| 25358 | } |
| 25359 | if( v<0 ){ |
| 25360 | if( v==SMALLEST_INT64 ){ |
| @@ -25363,35 +25399,35 @@ | |
| 25363 | longvalue = -v; |
| 25364 | } |
| 25365 | prefix = '-'; |
| 25366 | }else{ |
| 25367 | longvalue = v; |
| 25368 | if( flag_plussign ) prefix = '+'; |
| 25369 | else if( flag_blanksign ) prefix = ' '; |
| 25370 | else prefix = 0; |
| 25371 | } |
| 25372 | }else{ |
| 25373 | if( bArgList ){ |
| 25374 | longvalue = (u64)getIntArg(pArgList); |
| 25375 | }else if( flag_longlong ){ |
| 25376 | longvalue = va_arg(ap,u64); |
| 25377 | }else if( flag_long ){ |
| 25378 | longvalue = va_arg(ap,unsigned long int); |
| 25379 | }else{ |
| 25380 | longvalue = va_arg(ap,unsigned int); |
| 25381 | } |
| 25382 | prefix = 0; |
| 25383 | } |
| 25384 | if( longvalue==0 ) flag_alternateform = 0; |
| 25385 | if( flag_zeropad && precision<width-(prefix!=0) ){ |
| 25386 | precision = width-(prefix!=0); |
| 25387 | } |
| 25388 | if( precision<etBUFSIZE-10 ){ |
| 25389 | nOut = etBUFSIZE; |
| 25390 | zOut = buf; |
| 25391 | }else{ |
| 25392 | nOut = precision + 10; |
| 25393 | zOut = zExtra = sqlite3Malloc( nOut ); |
| 25394 | if( zOut==0 ){ |
| 25395 | setStrAccumError(pAccum, STRACCUM_NOMEM); |
| 25396 | return; |
| 25397 | } |
| @@ -25413,12 +25449,27 @@ | |
| 25413 | *(--bufpt) = cset[longvalue%base]; |
| 25414 | longvalue = longvalue/base; |
| 25415 | }while( longvalue>0 ); |
| 25416 | } |
| 25417 | length = (int)(&zOut[nOut-1]-bufpt); |
| 25418 | for(idx=precision-length; idx>0; idx--){ |
| 25419 | *(--bufpt) = '0'; /* Zero pad */ |
| 25420 | } |
| 25421 | if( prefix ) *(--bufpt) = prefix; /* Add sign */ |
| 25422 | if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ |
| 25423 | const char *pre; |
| 25424 | char x; |
| @@ -25441,13 +25492,11 @@ | |
| 25441 | if( precision<0 ) precision = 6; /* Set default precision */ |
| 25442 | if( realvalue<0.0 ){ |
| 25443 | realvalue = -realvalue; |
| 25444 | prefix = '-'; |
| 25445 | }else{ |
| 25446 | if( flag_plussign ) prefix = '+'; |
| 25447 | else if( flag_blanksign ) prefix = ' '; |
| 25448 | else prefix = 0; |
| 25449 | } |
| 25450 | if( xtype==etGENERIC && precision>0 ) precision--; |
| 25451 | testcase( precision>0xfff ); |
| 25452 | for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} |
| 25453 | if( xtype==etFLOAT ) realvalue += rounder; |
| @@ -29464,117 +29513,119 @@ | |
| 29464 | /* 50 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), |
| 29465 | /* 51 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), |
| 29466 | /* 52 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), |
| 29467 | /* 53 */ "Last" OpHelp(""), |
| 29468 | /* 54 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), |
| 29469 | /* 55 */ "SorterSort" OpHelp(""), |
| 29470 | /* 56 */ "Sort" OpHelp(""), |
| 29471 | /* 57 */ "Rewind" OpHelp(""), |
| 29472 | /* 58 */ "IdxLE" OpHelp("key=r[P3@P4]"), |
| 29473 | /* 59 */ "IdxGT" OpHelp("key=r[P3@P4]"), |
| 29474 | /* 60 */ "IdxLT" OpHelp("key=r[P3@P4]"), |
| 29475 | /* 61 */ "IdxGE" OpHelp("key=r[P3@P4]"), |
| 29476 | /* 62 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), |
| 29477 | /* 63 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), |
| 29478 | /* 64 */ "Program" OpHelp(""), |
| 29479 | /* 65 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), |
| 29480 | /* 66 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), |
| 29481 | /* 67 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), |
| 29482 | /* 68 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), |
| 29483 | /* 69 */ "IncrVacuum" OpHelp(""), |
| 29484 | /* 70 */ "VNext" OpHelp(""), |
| 29485 | /* 71 */ "Init" OpHelp("Start at P2"), |
| 29486 | /* 72 */ "Return" OpHelp(""), |
| 29487 | /* 73 */ "EndCoroutine" OpHelp(""), |
| 29488 | /* 74 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), |
| 29489 | /* 75 */ "Halt" OpHelp(""), |
| 29490 | /* 76 */ "Integer" OpHelp("r[P2]=P1"), |
| 29491 | /* 77 */ "Int64" OpHelp("r[P2]=P4"), |
| 29492 | /* 78 */ "String" OpHelp("r[P2]='P4' (len=P1)"), |
| 29493 | /* 79 */ "Null" OpHelp("r[P2..P3]=NULL"), |
| 29494 | /* 80 */ "SoftNull" OpHelp("r[P1]=NULL"), |
| 29495 | /* 81 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), |
| 29496 | /* 82 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), |
| 29497 | /* 83 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), |
| 29498 | /* 84 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), |
| 29499 | /* 85 */ "SCopy" OpHelp("r[P2]=r[P1]"), |
| 29500 | /* 86 */ "IntCopy" OpHelp("r[P2]=r[P1]"), |
| 29501 | /* 87 */ "ResultRow" OpHelp("output=r[P1@P2]"), |
| 29502 | /* 88 */ "CollSeq" OpHelp(""), |
| 29503 | /* 89 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), |
| 29504 | /* 90 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), |
| 29505 | /* 91 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), |
| 29506 | /* 92 */ "RealAffinity" OpHelp(""), |
| 29507 | /* 93 */ "Cast" OpHelp("affinity(r[P1])"), |
| 29508 | /* 94 */ "Permutation" OpHelp(""), |
| 29509 | /* 95 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), |
| 29510 | /* 96 */ "Column" OpHelp("r[P3]=PX"), |
| 29511 | /* 97 */ "String8" OpHelp("r[P2]='P4'"), |
| 29512 | /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), |
| 29513 | /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), |
| 29514 | /* 100 */ "Count" OpHelp("r[P2]=count()"), |
| 29515 | /* 101 */ "ReadCookie" OpHelp(""), |
| 29516 | /* 102 */ "SetCookie" OpHelp(""), |
| 29517 | /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), |
| 29518 | /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"), |
| 29519 | /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), |
| 29520 | /* 106 */ "OpenAutoindex" OpHelp("nColumn=P2"), |
| 29521 | /* 107 */ "OpenEphemeral" OpHelp("nColumn=P2"), |
| 29522 | /* 108 */ "SorterOpen" OpHelp(""), |
| 29523 | /* 109 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), |
| 29524 | /* 110 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), |
| 29525 | /* 111 */ "Close" OpHelp(""), |
| 29526 | /* 112 */ "ColumnsUsed" OpHelp(""), |
| 29527 | /* 113 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), |
| 29528 | /* 114 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 29529 | /* 115 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 29530 | /* 116 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), |
| 29531 | /* 117 */ "Delete" OpHelp(""), |
| 29532 | /* 118 */ "ResetCount" OpHelp(""), |
| 29533 | /* 119 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), |
| 29534 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29535 | /* 121 */ "RowData" OpHelp("r[P2]=data"), |
| 29536 | /* 122 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29537 | /* 123 */ "NullRow" OpHelp(""), |
| 29538 | /* 124 */ "SorterInsert" OpHelp("key=r[P2]"), |
| 29539 | /* 125 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29540 | /* 126 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29541 | /* 127 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29542 | /* 128 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29543 | /* 129 */ "Destroy" OpHelp(""), |
| 29544 | /* 130 */ "Clear" OpHelp(""), |
| 29545 | /* 131 */ "ResetSorter" OpHelp(""), |
| 29546 | /* 132 */ "Real" OpHelp("r[P2]=P4"), |
| 29547 | /* 133 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 29548 | /* 134 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 29549 | /* 135 */ "ParseSchema" OpHelp(""), |
| 29550 | /* 136 */ "LoadAnalysis" OpHelp(""), |
| 29551 | /* 137 */ "DropTable" OpHelp(""), |
| 29552 | /* 138 */ "DropIndex" OpHelp(""), |
| 29553 | /* 139 */ "DropTrigger" OpHelp(""), |
| 29554 | /* 140 */ "IntegrityCk" OpHelp(""), |
| 29555 | /* 141 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), |
| 29556 | /* 142 */ "Param" OpHelp(""), |
| 29557 | /* 143 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), |
| 29558 | /* 144 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), |
| 29559 | /* 145 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), |
| 29560 | /* 146 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 29561 | /* 147 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 29562 | /* 148 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), |
| 29563 | /* 149 */ "Expire" OpHelp(""), |
| 29564 | /* 150 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), |
| 29565 | /* 151 */ "VBegin" OpHelp(""), |
| 29566 | /* 152 */ "VCreate" OpHelp(""), |
| 29567 | /* 153 */ "VDestroy" OpHelp(""), |
| 29568 | /* 154 */ "VOpen" OpHelp(""), |
| 29569 | /* 155 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), |
| 29570 | /* 156 */ "VRename" OpHelp(""), |
| 29571 | /* 157 */ "Pagecount" OpHelp(""), |
| 29572 | /* 158 */ "MaxPgcnt" OpHelp(""), |
| 29573 | /* 159 */ "CursorHint" OpHelp(""), |
| 29574 | /* 160 */ "Noop" OpHelp(""), |
| 29575 | /* 161 */ "Explain" OpHelp(""), |
| 29576 | }; |
| 29577 | return azName[i]; |
| 29578 | } |
| 29579 | #endif |
| 29580 | |
| @@ -37952,46 +38003,84 @@ | |
| 37952 | * be freed immediately and any attempt to access any of that freed |
| 37953 | * data will almost certainly result in an immediate access violation. |
| 37954 | ****************************************************************************** |
| 37955 | */ |
| 37956 | #ifndef SQLITE_WIN32_HEAP_CREATE |
| 37957 | # define SQLITE_WIN32_HEAP_CREATE (TRUE) |
| 37958 | #endif |
| 37959 | |
| 37960 | /* |
| 37961 | * This is cache size used in the calculation of the initial size of the |
| 37962 | * Win32-specific heap. It cannot be negative. |
| 37963 | */ |
| 37964 | #ifndef SQLITE_WIN32_CACHE_SIZE |
| 37965 | # if SQLITE_DEFAULT_CACHE_SIZE>=0 |
| 37966 | # define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) |
| 37967 | # else |
| 37968 | # define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) |
| 37969 | # endif |
| 37970 | #endif |
| 37971 | |
| 37972 | /* |
| 37973 | * The initial size of the Win32-specific heap. This value may be zero. |
| 37974 | */ |
| 37975 | #ifndef SQLITE_WIN32_HEAP_INIT_SIZE |
| 37976 | # define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ |
| 37977 | (SQLITE_DEFAULT_PAGE_SIZE) + 4194304) |
| 37978 | #endif |
| 37979 | |
| 37980 | /* |
| 37981 | * The maximum size of the Win32-specific heap. This value may be zero. |
| 37982 | */ |
| 37983 | #ifndef SQLITE_WIN32_HEAP_MAX_SIZE |
| 37984 | # define SQLITE_WIN32_HEAP_MAX_SIZE (0) |
| 37985 | #endif |
| 37986 | |
| 37987 | /* |
| 37988 | * The extra flags to use in calls to the Win32 heap APIs. This value may be |
| 37989 | * zero for the default behavior. |
| 37990 | */ |
| 37991 | #ifndef SQLITE_WIN32_HEAP_FLAGS |
| 37992 | # define SQLITE_WIN32_HEAP_FLAGS (0) |
| 37993 | #endif |
| 37994 | |
| 37995 | |
| 37996 | /* |
| 37997 | ** The winMemData structure stores information required by the Win32-specific |
| @@ -44084,11 +44173,11 @@ | |
| 44084 | ** This routine is for use inside of assert() statements only. For |
| 44085 | ** example: |
| 44086 | ** |
| 44087 | ** assert( sqlite3PcachePageSanity(pPg) ); |
| 44088 | */ |
| 44089 | #if SQLITE_DEBUG |
| 44090 | SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ |
| 44091 | PCache *pCache; |
| 44092 | assert( pPg!=0 ); |
| 44093 | assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */ |
| 44094 | pCache = pPg->pCache; |
| @@ -60177,21 +60266,22 @@ | |
| 60177 | } |
| 60178 | #endif |
| 60179 | |
| 60180 | |
| 60181 | /* |
| 60182 | ** Defragment the page given. All Cells are moved to the |
| 60183 | ** end of the page and all free space is collected into one |
| 60184 | ** big FreeBlk that occurs in between the header and cell |
| 60185 | ** pointer array and the cell content area. |
| 60186 | ** |
| 60187 | ** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a |
| 60188 | ** b-tree page so that there are no freeblocks or fragment bytes, all |
| 60189 | ** unused bytes are contained in the unallocated space region, and all |
| 60190 | ** cells are packed tightly at the end of the page. |
| 60191 | */ |
| 60192 | static int defragmentPage(MemPage *pPage){ |
| 60193 | int i; /* Loop counter */ |
| 60194 | int pc; /* Address of the i-th cell */ |
| 60195 | int hdr; /* Offset to the page header */ |
| 60196 | int size; /* Size of a cell */ |
| 60197 | int usableSize; /* Number of usable bytes on a page */ |
| @@ -60202,11 +60292,10 @@ | |
| 60202 | unsigned char *temp; /* Temp area for cell content */ |
| 60203 | unsigned char *src; /* Source of content */ |
| 60204 | int iCellFirst; /* First allowable cell index */ |
| 60205 | int iCellLast; /* Last possible cell index */ |
| 60206 | |
| 60207 | |
| 60208 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 60209 | assert( pPage->pBt!=0 ); |
| 60210 | assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); |
| 60211 | assert( pPage->nOverflow==0 ); |
| 60212 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| @@ -60214,13 +60303,60 @@ | |
| 60214 | src = data = pPage->aData; |
| 60215 | hdr = pPage->hdrOffset; |
| 60216 | cellOffset = pPage->cellOffset; |
| 60217 | nCell = pPage->nCell; |
| 60218 | assert( nCell==get2byte(&data[hdr+3]) ); |
| 60219 | usableSize = pPage->pBt->usableSize; |
| 60220 | cbrk = usableSize; |
| 60221 | iCellFirst = cellOffset + 2*nCell; |
| 60222 | iCellLast = usableSize - 4; |
| 60223 | for(i=0; i<nCell; i++){ |
| 60224 | u8 *pAddr; /* The i-th cell pointer */ |
| 60225 | pAddr = &data[cellOffset + i*2]; |
| 60226 | pc = get2byte(pAddr); |
| @@ -60250,20 +60386,22 @@ | |
| 60250 | memcpy(&temp[x], &data[x], (cbrk+size) - x); |
| 60251 | src = temp; |
| 60252 | } |
| 60253 | memcpy(&data[cbrk], &src[pc], size); |
| 60254 | } |
| 60255 | assert( cbrk>=iCellFirst ); |
| 60256 | put2byte(&data[hdr+5], cbrk); |
| 60257 | data[hdr+1] = 0; |
| 60258 | data[hdr+2] = 0; |
| 60259 | data[hdr+7] = 0; |
| 60260 | memset(&data[iCellFirst], 0, cbrk-iCellFirst); |
| 60261 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 60262 | if( cbrk-iCellFirst!=pPage->nFree ){ |
| 60263 | return SQLITE_CORRUPT_BKPT; |
| 60264 | } |
| 60265 | return SQLITE_OK; |
| 60266 | } |
| 60267 | |
| 60268 | /* |
| 60269 | ** Search the free-list on page pPg for space to store a cell nByte bytes in |
| @@ -60397,14 +60535,14 @@ | |
| 60397 | ** to see if defragmentation is necessary. |
| 60398 | */ |
| 60399 | testcase( gap+2+nByte==top ); |
| 60400 | if( gap+2+nByte>top ){ |
| 60401 | assert( pPage->nCell>0 || CORRUPT_DB ); |
| 60402 | rc = defragmentPage(pPage); |
| 60403 | if( rc ) return rc; |
| 60404 | top = get2byteNotZero(&data[hdr+5]); |
| 60405 | assert( gap+nByte<=top ); |
| 60406 | } |
| 60407 | |
| 60408 | |
| 60409 | /* Allocate memory from the gap in between the cell pointer array |
| 60410 | ** and the cell content area. The btreeInitPage() call has already |
| @@ -63636,11 +63774,11 @@ | |
| 63636 | pCur->aiIdx[pCur->iPage] = 0; |
| 63637 | return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], |
| 63638 | pCur, pCur->curPagerFlags); |
| 63639 | } |
| 63640 | |
| 63641 | #if SQLITE_DEBUG |
| 63642 | /* |
| 63643 | ** Page pParent is an internal (non-leaf) tree page. This function |
| 63644 | ** asserts that page number iChild is the left-child if the iIdx'th |
| 63645 | ** cell in page pParent. Or, if iIdx is equal to the total number of |
| 63646 | ** cells in pParent, that page number iChild is the right-child of |
| @@ -64178,10 +64316,34 @@ | |
| 64178 | ** have been deleted? This API will need to change to return an error code |
| 64179 | ** as well as the boolean result value. |
| 64180 | */ |
| 64181 | return (CURSOR_VALID!=pCur->eState); |
| 64182 | } |
| 64183 | |
| 64184 | /* |
| 64185 | ** Advance the cursor to the next entry in the database. If |
| 64186 | ** successful then set *pRes=0. If the cursor |
| 64187 | ** was already pointing to the last entry in the database before |
| @@ -65023,11 +65185,11 @@ | |
| 65023 | ** pPrior Where to write the pgno of the first overflow page |
| 65024 | ** |
| 65025 | ** Use a call to btreeParseCellPtr() to verify that the values above |
| 65026 | ** were computed correctly. |
| 65027 | */ |
| 65028 | #if SQLITE_DEBUG |
| 65029 | { |
| 65030 | CellInfo info; |
| 65031 | pPage->xParseCell(pPage, pCell, &info); |
| 65032 | assert( nHeader==(int)(info.pPayload - pCell) ); |
| 65033 | assert( info.nKey==pX->nKey ); |
| @@ -66549,11 +66711,11 @@ | |
| 66549 | ** copied into the parent, because if the parent is page 1 then it will |
| 66550 | ** by smaller than the child due to the database header, and so all the |
| 66551 | ** free space needs to be up front. |
| 66552 | */ |
| 66553 | assert( nNew==1 || CORRUPT_DB ); |
| 66554 | rc = defragmentPage(apNew[0]); |
| 66555 | testcase( rc!=SQLITE_OK ); |
| 66556 | assert( apNew[0]->nFree == |
| 66557 | (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) |
| 66558 | || rc!=SQLITE_OK |
| 66559 | ); |
| @@ -71201,10 +71363,11 @@ | |
| 71201 | ** Remember the SQL string for a prepared statement. |
| 71202 | */ |
| 71203 | SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ |
| 71204 | assert( isPrepareV2==1 || isPrepareV2==0 ); |
| 71205 | if( p==0 ) return; |
| 71206 | #if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) |
| 71207 | if( !isPrepareV2 ) return; |
| 71208 | #endif |
| 71209 | assert( p->zSql==0 ); |
| 71210 | p->zSql = sqlite3DbStrNDup(p->db, z, n); |
| @@ -71229,10 +71392,11 @@ | |
| 71229 | pB->pPrev = pTmp; |
| 71230 | zTmp = pA->zSql; |
| 71231 | pA->zSql = pB->zSql; |
| 71232 | pB->zSql = zTmp; |
| 71233 | pB->isPrepareV2 = pA->isPrepareV2; |
| 71234 | } |
| 71235 | |
| 71236 | /* |
| 71237 | ** Resize the Vdbe.aOp array so that it is at least nOp elements larger |
| 71238 | ** than its current size. nOp is guaranteed to be less than or equal |
| @@ -73753,17 +73917,17 @@ | |
| 73753 | ** Then the internal cache might have been left in an inconsistent |
| 73754 | ** state. We need to rollback the statement transaction, if there is |
| 73755 | ** one, or the complete transaction if there is no statement transaction. |
| 73756 | */ |
| 73757 | |
| 73758 | if( db->mallocFailed ){ |
| 73759 | p->rc = SQLITE_NOMEM_BKPT; |
| 73760 | } |
| 73761 | closeAllCursors(p); |
| 73762 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| 73763 | return SQLITE_OK; |
| 73764 | } |
| 73765 | checkActiveVdbeCnt(db); |
| 73766 | |
| 73767 | /* No commit or rollback needed if the program never started or if the |
| 73768 | ** SQL statement does not read or write a database file. */ |
| 73769 | if( p->pc>=0 && p->bIsReader ){ |
| @@ -74706,11 +74870,11 @@ | |
| 74706 | } |
| 74707 | assert( u<=pKeyInfo->nField + 1 ); |
| 74708 | p->nField = u; |
| 74709 | } |
| 74710 | |
| 74711 | #if SQLITE_DEBUG |
| 74712 | /* |
| 74713 | ** This function compares two index or table record keys in the same way |
| 74714 | ** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), |
| 74715 | ** this function deserializes and compares values using the |
| 74716 | ** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used |
| @@ -74811,11 +74975,11 @@ | |
| 74811 | if( pKeyInfo->db->mallocFailed ) return 1; |
| 74812 | return 0; |
| 74813 | } |
| 74814 | #endif |
| 74815 | |
| 74816 | #if SQLITE_DEBUG |
| 74817 | /* |
| 74818 | ** Count the number of fields (a.k.a. columns) in the record given by |
| 74819 | ** pKey,nKey. The verify that this count is less than or equal to the |
| 74820 | ** limit given by pKeyInfo->nField + pKeyInfo->nXField. |
| 74821 | ** |
| @@ -75694,12 +75858,12 @@ | |
| 75694 | ** to sqlite3_reoptimize() that re-preparing the statement may result |
| 75695 | ** in a better query plan. |
| 75696 | */ |
| 75697 | SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ |
| 75698 | assert( iVar>0 ); |
| 75699 | if( iVar>32 ){ |
| 75700 | v->expmask = 0xffffffff; |
| 75701 | }else{ |
| 75702 | v->expmask |= ((u32)1 << (iVar-1)); |
| 75703 | } |
| 75704 | } |
| 75705 | |
| @@ -75965,11 +76129,12 @@ | |
| 75965 | sqlite3_mutex_enter(mutex); |
| 75966 | for(i=0; i<p->nVar; i++){ |
| 75967 | sqlite3VdbeMemRelease(&p->aVar[i]); |
| 75968 | p->aVar[i].flags = MEM_Null; |
| 75969 | } |
| 75970 | if( p->isPrepareV2 && p->expmask ){ |
| 75971 | p->expired = 1; |
| 75972 | } |
| 75973 | sqlite3_mutex_leave(mutex); |
| 75974 | return rc; |
| 75975 | } |
| @@ -77069,13 +77234,12 @@ | |
| 77069 | ** parameter in the WHERE clause might influence the choice of query plan |
| 77070 | ** for a statement, then the statement will be automatically recompiled, |
| 77071 | ** as if there had been a schema change, on the first sqlite3_step() call |
| 77072 | ** following any change to the bindings of that parameter. |
| 77073 | */ |
| 77074 | if( p->isPrepareV2 && |
| 77075 | ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) |
| 77076 | ){ |
| 77077 | p->expired = 1; |
| 77078 | } |
| 77079 | return SQLITE_OK; |
| 77080 | } |
| 77081 | |
| @@ -77334,14 +77498,16 @@ | |
| 77334 | Vdbe *pFrom = (Vdbe*)pFromStmt; |
| 77335 | Vdbe *pTo = (Vdbe*)pToStmt; |
| 77336 | if( pFrom->nVar!=pTo->nVar ){ |
| 77337 | return SQLITE_ERROR; |
| 77338 | } |
| 77339 | if( pTo->isPrepareV2 && pTo->expmask ){ |
| 77340 | pTo->expired = 1; |
| 77341 | } |
| 77342 | if( pFrom->isPrepareV2 && pFrom->expmask ){ |
| 77343 | pFrom->expired = 1; |
| 77344 | } |
| 77345 | return sqlite3TransferBindings(pFromStmt, pToStmt); |
| 77346 | } |
| 77347 | #endif |
| @@ -79658,39 +79824,39 @@ | |
| 79658 | if( pCtx->pOut != pOut ){ |
| 79659 | pCtx->pOut = pOut; |
| 79660 | for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; |
| 79661 | } |
| 79662 | |
| 79663 | memAboutToChange(p, pCtx->pOut); |
| 79664 | #ifdef SQLITE_DEBUG |
| 79665 | for(i=0; i<pCtx->argc; i++){ |
| 79666 | assert( memIsValid(pCtx->argv[i]) ); |
| 79667 | REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); |
| 79668 | } |
| 79669 | #endif |
| 79670 | MemSetTypeFlag(pCtx->pOut, MEM_Null); |
| 79671 | pCtx->fErrorOrAux = 0; |
| 79672 | (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ |
| 79673 | |
| 79674 | /* If the function returned an error, throw an exception */ |
| 79675 | if( pCtx->fErrorOrAux ){ |
| 79676 | if( pCtx->isError ){ |
| 79677 | sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); |
| 79678 | rc = pCtx->isError; |
| 79679 | } |
| 79680 | sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); |
| 79681 | if( rc ) goto abort_due_to_error; |
| 79682 | } |
| 79683 | |
| 79684 | /* Copy the result of the function into register P3 */ |
| 79685 | if( pOut->flags & (MEM_Str|MEM_Blob) ){ |
| 79686 | sqlite3VdbeChangeEncoding(pCtx->pOut, encoding); |
| 79687 | if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big; |
| 79688 | } |
| 79689 | |
| 79690 | REGISTER_TRACE(pOp->p3, pCtx->pOut); |
| 79691 | UPDATE_MAX_BLOBSIZE(pCtx->pOut); |
| 79692 | break; |
| 79693 | } |
| 79694 | |
| 79695 | /* Opcode: BitAnd P1 P2 P3 * * |
| 79696 | ** Synopsis: r[P3]=r[P1]&r[P2] |
| @@ -80187,11 +80353,11 @@ | |
| 80187 | pKeyInfo = pOp->p4.pKeyInfo; |
| 80188 | assert( n>0 ); |
| 80189 | assert( pKeyInfo!=0 ); |
| 80190 | p1 = pOp->p1; |
| 80191 | p2 = pOp->p2; |
| 80192 | #if SQLITE_DEBUG |
| 80193 | if( aPermute ){ |
| 80194 | int k, mx = 0; |
| 80195 | for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k]; |
| 80196 | assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); |
| 80197 | assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 ); |
| @@ -82836,10 +83002,37 @@ | |
| 82836 | assert( pOp->p2==0 ); |
| 82837 | } |
| 82838 | break; |
| 82839 | } |
| 82840 | |
| 82841 | |
| 82842 | /* Opcode: SorterSort P1 P2 * * * |
| 82843 | ** |
| 82844 | ** After all records have been inserted into the Sorter object |
| 82845 | ** identified by P1, invoke this opcode to actually do the sorting. |
| @@ -83479,10 +83672,22 @@ | |
| 83479 | rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); |
| 83480 | if( rc ) goto abort_due_to_error; |
| 83481 | pOut->u.i = pgno; |
| 83482 | break; |
| 83483 | } |
| 83484 | |
| 83485 | /* Opcode: ParseSchema P1 * * P4 * |
| 83486 | ** |
| 83487 | ** Read and parse all entries from the SQLITE_MASTER table of database P1 |
| 83488 | ** that match the WHERE clause P4. |
| @@ -83600,11 +83805,11 @@ | |
| 83600 | ** |
| 83601 | ** Do an analysis of the currently open database. Store in |
| 83602 | ** register P1 the text of an error message describing any problems. |
| 83603 | ** If no problems are found, store a NULL in register P1. |
| 83604 | ** |
| 83605 | ** The register P3 contains the maximum number of allowed errors. |
| 83606 | ** At most reg(P3) errors will be reported. |
| 83607 | ** In other words, the analysis stops as soon as reg(P1) errors are |
| 83608 | ** seen. Reg(P1) is updated with the number of errors remaining. |
| 83609 | ** |
| 83610 | ** The root page numbers of all tables in the database are integers |
| @@ -83633,18 +83838,18 @@ | |
| 83633 | assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); |
| 83634 | pIn1 = &aMem[pOp->p1]; |
| 83635 | assert( pOp->p5<db->nDb ); |
| 83636 | assert( DbMaskTest(p->btreeMask, pOp->p5) ); |
| 83637 | z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, |
| 83638 | (int)pnErr->u.i, &nErr); |
| 83639 | pnErr->u.i -= nErr; |
| 83640 | sqlite3VdbeMemSetNull(pIn1); |
| 83641 | if( nErr==0 ){ |
| 83642 | assert( z==0 ); |
| 83643 | }else if( z==0 ){ |
| 83644 | goto no_mem; |
| 83645 | }else{ |
| 83646 | sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); |
| 83647 | } |
| 83648 | UPDATE_MAX_BLOBSIZE(pIn1); |
| 83649 | sqlite3VdbeChangeEncoding(pIn1, encoding); |
| 83650 | break; |
| @@ -88787,15 +88992,15 @@ | |
| 88787 | ** The return value from the callback should be one of the WRC_* |
| 88788 | ** constants to specify how to proceed with the walk. |
| 88789 | ** |
| 88790 | ** WRC_Continue Continue descending down the tree. |
| 88791 | ** |
| 88792 | ** WRC_Prune Do not descend into child nodes. But allow |
| 88793 | ** the walk to continue with sibling nodes. |
| 88794 | ** |
| 88795 | ** WRC_Abort Do no more callbacks. Unwind the stack and |
| 88796 | ** return the top-level walk call. |
| 88797 | ** |
| 88798 | ** The return value from this routine is WRC_Abort to abandon the tree walk |
| 88799 | ** and WRC_Continue to continue. |
| 88800 | */ |
| 88801 | static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ |
| @@ -89153,11 +89358,12 @@ | |
| 89153 | } |
| 89154 | } |
| 89155 | } |
| 89156 | |
| 89157 | /* Start at the inner-most context and move outward until a match is found */ |
| 89158 | while( pNC && cnt==0 ){ |
| 89159 | ExprList *pEList; |
| 89160 | SrcList *pSrcList = pNC->pSrcList; |
| 89161 | |
| 89162 | if( pSrcList ){ |
| 89163 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| @@ -89338,15 +89544,15 @@ | |
| 89338 | } |
| 89339 | |
| 89340 | /* Advance to the next name context. The loop will exit when either |
| 89341 | ** we have a match (cnt>0) or when we run out of name contexts. |
| 89342 | */ |
| 89343 | if( cnt==0 ){ |
| 89344 | pNC = pNC->pNext; |
| 89345 | nSubquery++; |
| 89346 | } |
| 89347 | } |
| 89348 | |
| 89349 | /* |
| 89350 | ** If X and Y are NULL (in other words if only the column name Z is |
| 89351 | ** supplied) and the value of Z is enclosed in double-quotes, then |
| 89352 | ** Z is a string literal if it doesn't match any column names. In that |
| @@ -89532,37 +89738,42 @@ | |
| 89532 | break; |
| 89533 | } |
| 89534 | #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) |
| 89535 | && !defined(SQLITE_OMIT_SUBQUERY) */ |
| 89536 | |
| 89537 | /* A lone identifier is the name of a column. |
| 89538 | */ |
| 89539 | case TK_ID: { |
| 89540 | return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); |
| 89541 | } |
| 89542 | |
| 89543 | /* A table name and column name: ID.ID |
| 89544 | ** Or a database, table and column: ID.ID.ID |
| 89545 | */ |
| 89546 | case TK_DOT: { |
| 89547 | const char *zColumn; |
| 89548 | const char *zTable; |
| 89549 | const char *zDb; |
| 89550 | Expr *pRight; |
| 89551 | |
| 89552 | /* if( pSrcList==0 ) break; */ |
| 89553 | notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); |
| 89554 | pRight = pExpr->pRight; |
| 89555 | if( pRight->op==TK_ID ){ |
| 89556 | zDb = 0; |
| 89557 | zTable = pExpr->pLeft->u.zToken; |
| 89558 | zColumn = pRight->u.zToken; |
| 89559 | }else{ |
| 89560 | assert( pRight->op==TK_DOT ); |
| 89561 | zDb = pExpr->pLeft->u.zToken; |
| 89562 | zTable = pRight->pLeft->u.zToken; |
| 89563 | zColumn = pRight->pRight->u.zToken; |
| 89564 | } |
| 89565 | return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); |
| 89566 | } |
| 89567 | |
| 89568 | /* Resolve function names |
| @@ -92833,11 +93044,11 @@ | |
| 92833 | int nVal = sqlite3ExprVectorSize(pLeft); |
| 92834 | Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; |
| 92835 | char *zRet; |
| 92836 | |
| 92837 | assert( pExpr->op==TK_IN ); |
| 92838 | zRet = sqlite3DbMallocZero(pParse->db, nVal+1); |
| 92839 | if( zRet ){ |
| 92840 | int i; |
| 92841 | for(i=0; i<nVal; i++){ |
| 92842 | Expr *pA = sqlite3VectorFieldSubexpr(pLeft, i); |
| 92843 | char a = sqlite3ExprAffinity(pA); |
| @@ -93738,11 +93949,11 @@ | |
| 93738 | ** Clear all column cache entries. |
| 93739 | */ |
| 93740 | SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ |
| 93741 | int i; |
| 93742 | |
| 93743 | #if SQLITE_DEBUG |
| 93744 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 93745 | printf("CLEAR\n"); |
| 93746 | } |
| 93747 | #endif |
| 93748 | for(i=0; i<pParse->nColCache; i++){ |
| @@ -95145,10 +95356,21 @@ | |
| 95145 | if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; |
| 95146 | if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1; |
| 95147 | } |
| 95148 | return 0; |
| 95149 | } |
| 95150 | |
| 95151 | /* |
| 95152 | ** Return true if we can prove the pE2 will always be true if pE1 is |
| 95153 | ** true. Return false if we cannot complete the proof or if pE2 might |
| 95154 | ** be false. Examples: |
| @@ -96698,10 +96920,11 @@ | |
| 96698 | Stat4Sample current; /* Current row as a Stat4Sample */ |
| 96699 | u32 iPrn; /* Pseudo-random number used for sampling */ |
| 96700 | Stat4Sample *aBest; /* Array of nCol best samples */ |
| 96701 | int iMin; /* Index in a[] of entry with minimum score */ |
| 96702 | int nSample; /* Current number of samples */ |
| 96703 | int iGet; /* Index of current sample accessed by stat_get() */ |
| 96704 | Stat4Sample *a; /* Array of mxSample Stat4Sample objects */ |
| 96705 | sqlite3 *db; /* Database connection, for malloc() */ |
| 96706 | }; |
| 96707 | |
| @@ -96962,10 +97185,17 @@ | |
| 96962 | int i; |
| 96963 | |
| 96964 | assert( IsStat4 || nEqZero==0 ); |
| 96965 | |
| 96966 | #ifdef SQLITE_ENABLE_STAT4 |
| 96967 | if( pNew->isPSample==0 ){ |
| 96968 | Stat4Sample *pUpgrade = 0; |
| 96969 | assert( pNew->anEq[pNew->iCol]>0 ); |
| 96970 | |
| 96971 | /* This sample is being added because the prefix that ends in column |
| @@ -97059,16 +97289,26 @@ | |
| 97059 | if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ |
| 97060 | sampleInsert(p, pBest, i); |
| 97061 | } |
| 97062 | } |
| 97063 | |
| 97064 | /* Update the anEq[] fields of any samples already collected. */ |
| 97065 | for(i=p->nSample-1; i>=0; i--){ |
| 97066 | int j; |
| 97067 | for(j=iChng; j<p->nCol; j++){ |
| 97068 | if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; |
| 97069 | } |
| 97070 | } |
| 97071 | #endif |
| 97072 | |
| 97073 | #if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) |
| 97074 | if( iChng==0 ){ |
| @@ -97778,44 +98018,32 @@ | |
| 97778 | /* Form 1: Analyze everything */ |
| 97779 | for(i=0; i<db->nDb; i++){ |
| 97780 | if( i==1 ) continue; /* Do not analyze the TEMP database */ |
| 97781 | analyzeDatabase(pParse, i); |
| 97782 | } |
| 97783 | }else if( pName2->n==0 ){ |
| 97784 | /* Form 2: Analyze the database or table named */ |
| 97785 | iDb = sqlite3FindDb(db, pName1); |
| 97786 | if( iDb>=0 ){ |
| 97787 | analyzeDatabase(pParse, iDb); |
| 97788 | }else{ |
| 97789 | z = sqlite3NameFromToken(db, pName1); |
| 97790 | if( z ){ |
| 97791 | if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){ |
| 97792 | analyzeTable(pParse, pIdx->pTable, pIdx); |
| 97793 | }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){ |
| 97794 | analyzeTable(pParse, pTab, 0); |
| 97795 | } |
| 97796 | sqlite3DbFree(db, z); |
| 97797 | } |
| 97798 | } |
| 97799 | }else{ |
| 97800 | /* Form 3: Analyze the fully qualified table name */ |
| 97801 | iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); |
| 97802 | if( iDb>=0 ){ |
| 97803 | zDb = db->aDb[iDb].zDbSName; |
| 97804 | z = sqlite3NameFromToken(db, pTableName); |
| 97805 | if( z ){ |
| 97806 | if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ |
| 97807 | analyzeTable(pParse, pIdx->pTable, pIdx); |
| 97808 | }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ |
| 97809 | analyzeTable(pParse, pTab, 0); |
| 97810 | } |
| 97811 | sqlite3DbFree(db, z); |
| 97812 | } |
| 97813 | } |
| 97814 | } |
| 97815 | v = sqlite3GetVdbe(pParse); |
| 97816 | if( v ) sqlite3VdbeAddOp0(v, OP_Expire); |
| 97817 | } |
| 97818 | |
| 97819 | /* |
| 97820 | ** Used to pass information from the analyzer reader through to the |
| 97821 | ** callback routine. |
| @@ -97940,19 +98168,24 @@ | |
| 97940 | } |
| 97941 | aiRowEst = pIndex->aiRowEst; |
| 97942 | #endif |
| 97943 | pIndex->bUnordered = 0; |
| 97944 | decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); |
| 97945 | if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0]; |
| 97946 | }else{ |
| 97947 | Index fakeIdx; |
| 97948 | fakeIdx.szIdxRow = pTable->szTabRow; |
| 97949 | #ifdef SQLITE_ENABLE_COSTMULT |
| 97950 | fakeIdx.pTable = pTable; |
| 97951 | #endif |
| 97952 | decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); |
| 97953 | pTable->szTabRow = fakeIdx.szIdxRow; |
| 97954 | } |
| 97955 | |
| 97956 | return 0; |
| 97957 | } |
| 97958 | |
| @@ -98243,19 +98476,24 @@ | |
| 98243 | SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ |
| 98244 | analysisInfo sInfo; |
| 98245 | HashElem *i; |
| 98246 | char *zSql; |
| 98247 | int rc = SQLITE_OK; |
| 98248 | |
| 98249 | assert( iDb>=0 && iDb<db->nDb ); |
| 98250 | assert( db->aDb[iDb].pBt!=0 ); |
| 98251 | |
| 98252 | /* Clear any prior statistics */ |
| 98253 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 98254 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 98255 | Index *pIdx = sqliteHashData(i); |
| 98256 | pIdx->aiRowLogEst[0] = 0; |
| 98257 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 98258 | sqlite3DeleteIndexSamples(db, pIdx); |
| 98259 | pIdx->aSample = 0; |
| 98260 | #endif |
| 98261 | } |
| @@ -98274,23 +98512,23 @@ | |
| 98274 | } |
| 98275 | } |
| 98276 | |
| 98277 | /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */ |
| 98278 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 98279 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 98280 | Index *pIdx = sqliteHashData(i); |
| 98281 | if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx); |
| 98282 | } |
| 98283 | |
| 98284 | /* Load the statistics from the sqlite_stat4 table. */ |
| 98285 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 98286 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 98287 | db->lookaside.bDisable++; |
| 98288 | rc = loadStat4(db, sInfo.zDatabase); |
| 98289 | db->lookaside.bDisable--; |
| 98290 | } |
| 98291 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 98292 | Index *pIdx = sqliteHashData(i); |
| 98293 | sqlite3_free(pIdx->aiRowEst); |
| 98294 | pIdx->aiRowEst = 0; |
| 98295 | } |
| 98296 | #endif |
| @@ -100271,10 +100509,11 @@ | |
| 100271 | SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ |
| 100272 | Table *p; |
| 100273 | p = pParse->pNewTable; |
| 100274 | if( p==0 || NEVER(p->nCol<1) ) return; |
| 100275 | p->aCol[p->nCol-1].notNull = (u8)onError; |
| 100276 | } |
| 100277 | |
| 100278 | /* |
| 100279 | ** Scan the column type name zType (length nType) and return the |
| 100280 | ** associated affinity type. |
| @@ -102609,10 +102848,13 @@ | |
| 102609 | /* 10, 9, 8, 7, 6 */ |
| 102610 | LogEst aVal[] = { 33, 32, 30, 28, 26 }; |
| 102611 | LogEst *a = pIdx->aiRowLogEst; |
| 102612 | int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol); |
| 102613 | int i; |
| 102614 | |
| 102615 | /* Set the first entry (number of rows in the index) to the estimated |
| 102616 | ** number of rows in the table, or half the number of rows in the table |
| 102617 | ** for a partial index. But do not let the estimate drop below 10. */ |
| 102618 | a[0] = pIdx->pTable->nRowLogEst; |
| @@ -109798,10 +110040,13 @@ | |
| 109798 | VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); |
| 109799 | } |
| 109800 | } |
| 109801 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); |
| 109802 | VdbeComment((v, "for %s", pIdx->zName)); |
| 109803 | |
| 109804 | /* In an UPDATE operation, if this index is the PRIMARY KEY index |
| 109805 | ** of a WITHOUT ROWID table and there has been no change the |
| 109806 | ** primary key, then no collision is possible. The collision detection |
| 109807 | ** logic below can all be skipped. */ |
| @@ -109953,12 +110198,15 @@ | |
| 109953 | |
| 109954 | /* Records with omitted columns are only allowed for schema format |
| 109955 | ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ |
| 109956 | if( pTab->pSchema->file_format<2 ) return; |
| 109957 | |
| 109958 | for(i=pTab->nCol; i>1 && pTab->aCol[i-1].pDflt==0; i--){} |
| 109959 | sqlite3VdbeChangeP5(v, i); |
| 109960 | } |
| 109961 | #endif |
| 109962 | |
| 109963 | /* |
| 109964 | ** This routine generates code to finish the INSERT or UPDATE operation |
| @@ -110244,11 +110492,11 @@ | |
| 110244 | } |
| 110245 | if( sqlite3TriggerList(pParse, pDest) ){ |
| 110246 | return 0; /* tab1 must not have triggers */ |
| 110247 | } |
| 110248 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 110249 | if( pDest->tabFlags & TF_Virtual ){ |
| 110250 | return 0; /* tab1 must not be a virtual table */ |
| 110251 | } |
| 110252 | #endif |
| 110253 | if( onError==OE_Default ){ |
| 110254 | if( pDest->iPKey>=0 ) onError = pDest->keyConf; |
| @@ -110306,11 +110554,11 @@ | |
| 110306 | } |
| 110307 | if( HasRowid(pDest)!=HasRowid(pSrc) ){ |
| 110308 | return 0; /* source and destination must both be WITHOUT ROWID or not */ |
| 110309 | } |
| 110310 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 110311 | if( pSrc->tabFlags & TF_Virtual ){ |
| 110312 | return 0; /* tab2 must not be a virtual table */ |
| 110313 | } |
| 110314 | #endif |
| 110315 | if( pSrc->pSelect ){ |
| 110316 | return 0; /* tab2 may not be a view */ |
| @@ -110603,11 +110851,11 @@ | |
| 110603 | /* Invoke the callback function if required */ |
| 110604 | if( xCallback && (SQLITE_ROW==rc || |
| 110605 | (SQLITE_DONE==rc && !callbackIsInit |
| 110606 | && db->flags&SQLITE_NullCallback)) ){ |
| 110607 | if( !callbackIsInit ){ |
| 110608 | azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); |
| 110609 | if( azCols==0 ){ |
| 110610 | goto exec_out; |
| 110611 | } |
| 110612 | for(i=0; i<nCol; i++){ |
| 110613 | azCols[i] = (char *)sqlite3_column_name(pStmt, i); |
| @@ -110624,10 +110872,11 @@ | |
| 110624 | if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 110625 | sqlite3OomFault(db); |
| 110626 | goto exec_out; |
| 110627 | } |
| 110628 | } |
| 110629 | } |
| 110630 | if( xCallback(pArg, nCol, azVals, azCols) ){ |
| 110631 | /* EVIDENCE-OF: R-38229-40159 If the callback function to |
| 110632 | ** sqlite3_exec() returns non-zero, then sqlite3_exec() will |
| 110633 | ** return SQLITE_ABORT. */ |
| @@ -112094,15 +112343,15 @@ | |
| 112094 | #define PragTyp_JOURNAL_SIZE_LIMIT 20 |
| 112095 | #define PragTyp_LOCK_PROXY_FILE 21 |
| 112096 | #define PragTyp_LOCKING_MODE 22 |
| 112097 | #define PragTyp_PAGE_COUNT 23 |
| 112098 | #define PragTyp_MMAP_SIZE 24 |
| 112099 | #define PragTyp_PAGE_SIZE 25 |
| 112100 | #define PragTyp_SECURE_DELETE 26 |
| 112101 | #define PragTyp_SHRINK_MEMORY 27 |
| 112102 | #define PragTyp_SOFT_HEAP_LIMIT 28 |
| 112103 | #define PragTyp_STATS 29 |
| 112104 | #define PragTyp_SYNCHRONOUS 30 |
| 112105 | #define PragTyp_TABLE_INFO 31 |
| 112106 | #define PragTyp_TEMP_STORE 32 |
| 112107 | #define PragTyp_TEMP_STORE_DIRECTORY 33 |
| 112108 | #define PragTyp_THREADS 34 |
| @@ -112112,10 +112361,11 @@ | |
| 112112 | #define PragTyp_HEXKEY 38 |
| 112113 | #define PragTyp_KEY 39 |
| 112114 | #define PragTyp_REKEY 40 |
| 112115 | #define PragTyp_LOCK_STATUS 41 |
| 112116 | #define PragTyp_PARSER_TRACE 42 |
| 112117 | |
| 112118 | /* Property flags associated with various pragma. */ |
| 112119 | #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ |
| 112120 | #define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ |
| 112121 | #define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ |
| @@ -112135,51 +112385,52 @@ | |
| 112135 | /* 2 */ "name", |
| 112136 | /* 3 */ "type", |
| 112137 | /* 4 */ "notnull", |
| 112138 | /* 5 */ "dflt_value", |
| 112139 | /* 6 */ "pk", |
| 112140 | /* 7 */ "table", /* Used by: stats */ |
| 112141 | /* 8 */ "index", |
| 112142 | /* 9 */ "width", |
| 112143 | /* 10 */ "height", |
| 112144 | /* 11 */ "seqno", /* Used by: index_info */ |
| 112145 | /* 12 */ "cid", |
| 112146 | /* 13 */ "name", |
| 112147 | /* 14 */ "seqno", /* Used by: index_xinfo */ |
| 112148 | /* 15 */ "cid", |
| 112149 | /* 16 */ "name", |
| 112150 | /* 17 */ "desc", |
| 112151 | /* 18 */ "coll", |
| 112152 | /* 19 */ "key", |
| 112153 | /* 20 */ "seq", /* Used by: index_list */ |
| 112154 | /* 21 */ "name", |
| 112155 | /* 22 */ "unique", |
| 112156 | /* 23 */ "origin", |
| 112157 | /* 24 */ "partial", |
| 112158 | /* 25 */ "seq", /* Used by: database_list */ |
| 112159 | /* 26 */ "name", |
| 112160 | /* 27 */ "file", |
| 112161 | /* 28 */ "seq", /* Used by: collation_list */ |
| 112162 | /* 29 */ "name", |
| 112163 | /* 30 */ "id", /* Used by: foreign_key_list */ |
| 112164 | /* 31 */ "seq", |
| 112165 | /* 32 */ "table", |
| 112166 | /* 33 */ "from", |
| 112167 | /* 34 */ "to", |
| 112168 | /* 35 */ "on_update", |
| 112169 | /* 36 */ "on_delete", |
| 112170 | /* 37 */ "match", |
| 112171 | /* 38 */ "table", /* Used by: foreign_key_check */ |
| 112172 | /* 39 */ "rowid", |
| 112173 | /* 40 */ "parent", |
| 112174 | /* 41 */ "fkid", |
| 112175 | /* 42 */ "busy", /* Used by: wal_checkpoint */ |
| 112176 | /* 43 */ "log", |
| 112177 | /* 44 */ "checkpointed", |
| 112178 | /* 45 */ "timeout", /* Used by: busy_timeout */ |
| 112179 | /* 46 */ "database", /* Used by: lock_status */ |
| 112180 | /* 47 */ "status", |
| 112181 | }; |
| 112182 | |
| 112183 | /* Definitions of all built-in pragmas */ |
| 112184 | typedef struct PragmaName { |
| 112185 | const char *const zName; /* Name of pragma */ |
| @@ -112221,11 +112472,11 @@ | |
| 112221 | #endif |
| 112222 | #endif |
| 112223 | {/* zName: */ "busy_timeout", |
| 112224 | /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, |
| 112225 | /* ePragFlg: */ PragFlg_Result0, |
| 112226 | /* ColNames: */ 45, 1, |
| 112227 | /* iArg: */ 0 }, |
| 112228 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112229 | {/* zName: */ "cache_size", |
| 112230 | /* ePragTyp: */ PragTyp_CACHE_SIZE, |
| 112231 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
| @@ -112258,11 +112509,11 @@ | |
| 112258 | #endif |
| 112259 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112260 | {/* zName: */ "collation_list", |
| 112261 | /* ePragTyp: */ PragTyp_COLLATION_LIST, |
| 112262 | /* ePragFlg: */ PragFlg_Result0, |
| 112263 | /* ColNames: */ 28, 2, |
| 112264 | /* iArg: */ 0 }, |
| 112265 | #endif |
| 112266 | #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) |
| 112267 | {/* zName: */ "compile_options", |
| 112268 | /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, |
| @@ -112293,11 +112544,11 @@ | |
| 112293 | #endif |
| 112294 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112295 | {/* zName: */ "database_list", |
| 112296 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 112297 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, |
| 112298 | /* ColNames: */ 25, 3, |
| 112299 | /* iArg: */ 0 }, |
| 112300 | #endif |
| 112301 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
| 112302 | {/* zName: */ "default_cache_size", |
| 112303 | /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, |
| @@ -112330,18 +112581,18 @@ | |
| 112330 | #endif |
| 112331 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 112332 | {/* zName: */ "foreign_key_check", |
| 112333 | /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, |
| 112334 | /* ePragFlg: */ PragFlg_NeedSchema, |
| 112335 | /* ColNames: */ 38, 4, |
| 112336 | /* iArg: */ 0 }, |
| 112337 | #endif |
| 112338 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) |
| 112339 | {/* zName: */ "foreign_key_list", |
| 112340 | /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, |
| 112341 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112342 | /* ColNames: */ 30, 8, |
| 112343 | /* iArg: */ 0 }, |
| 112344 | #endif |
| 112345 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 112346 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 112347 | {/* zName: */ "foreign_keys", |
| @@ -112400,21 +112651,21 @@ | |
| 112400 | #endif |
| 112401 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112402 | {/* zName: */ "index_info", |
| 112403 | /* ePragTyp: */ PragTyp_INDEX_INFO, |
| 112404 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112405 | /* ColNames: */ 11, 3, |
| 112406 | /* iArg: */ 0 }, |
| 112407 | {/* zName: */ "index_list", |
| 112408 | /* ePragTyp: */ PragTyp_INDEX_LIST, |
| 112409 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112410 | /* ColNames: */ 20, 5, |
| 112411 | /* iArg: */ 0 }, |
| 112412 | {/* zName: */ "index_xinfo", |
| 112413 | /* ePragTyp: */ PragTyp_INDEX_INFO, |
| 112414 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112415 | /* ColNames: */ 14, 6, |
| 112416 | /* iArg: */ 1 }, |
| 112417 | #endif |
| 112418 | #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) |
| 112419 | {/* zName: */ "integrity_check", |
| 112420 | /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, |
| @@ -112457,11 +112708,11 @@ | |
| 112457 | #endif |
| 112458 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| 112459 | {/* zName: */ "lock_status", |
| 112460 | /* ePragTyp: */ PragTyp_LOCK_STATUS, |
| 112461 | /* ePragFlg: */ PragFlg_Result0, |
| 112462 | /* ColNames: */ 46, 2, |
| 112463 | /* iArg: */ 0 }, |
| 112464 | #endif |
| 112465 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112466 | {/* zName: */ "locking_mode", |
| 112467 | /* ePragTyp: */ PragTyp_LOCKING_MODE, |
| @@ -112476,10 +112727,17 @@ | |
| 112476 | {/* zName: */ "mmap_size", |
| 112477 | /* ePragTyp: */ PragTyp_MMAP_SIZE, |
| 112478 | /* ePragFlg: */ 0, |
| 112479 | /* ColNames: */ 0, 0, |
| 112480 | /* iArg: */ 0 }, |
| 112481 | {/* zName: */ "page_count", |
| 112482 | /* ePragTyp: */ PragTyp_PAGE_COUNT, |
| 112483 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
| 112484 | /* ColNames: */ 0, 0, |
| 112485 | /* iArg: */ 0 }, |
| @@ -112574,15 +112832,15 @@ | |
| 112574 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
| 112575 | /* ColNames: */ 0, 0, |
| 112576 | /* iArg: */ SQLITE_SqlTrace }, |
| 112577 | #endif |
| 112578 | #endif |
| 112579 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112580 | {/* zName: */ "stats", |
| 112581 | /* ePragTyp: */ PragTyp_STATS, |
| 112582 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
| 112583 | /* ColNames: */ 7, 4, |
| 112584 | /* iArg: */ 0 }, |
| 112585 | #endif |
| 112586 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112587 | {/* zName: */ "synchronous", |
| 112588 | /* ePragTyp: */ PragTyp_SYNCHRONOUS, |
| @@ -112657,11 +112915,11 @@ | |
| 112657 | /* ColNames: */ 0, 0, |
| 112658 | /* iArg: */ 0 }, |
| 112659 | {/* zName: */ "wal_checkpoint", |
| 112660 | /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, |
| 112661 | /* ePragFlg: */ PragFlg_NeedSchema, |
| 112662 | /* ColNames: */ 42, 3, |
| 112663 | /* iArg: */ 0 }, |
| 112664 | #endif |
| 112665 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 112666 | {/* zName: */ "writable_schema", |
| 112667 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -112668,11 +112926,11 @@ | |
| 112668 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
| 112669 | /* ColNames: */ 0, 0, |
| 112670 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 112671 | #endif |
| 112672 | }; |
| 112673 | /* Number of pragmas: 60 on by default, 73 total. */ |
| 112674 | |
| 112675 | /************** End of pragma.h **********************************************/ |
| 112676 | /************** Continuing where we left off in pragma.c *********************/ |
| 112677 | |
| 112678 | /* |
| @@ -112937,10 +113195,26 @@ | |
| 112937 | lwr = mid + 1; |
| 112938 | } |
| 112939 | } |
| 112940 | return lwr>upr ? 0 : &aPragmaName[mid]; |
| 112941 | } |
| 112942 | |
| 112943 | /* |
| 112944 | ** Process a pragma statement. |
| 112945 | ** |
| 112946 | ** Pragmas are of this form: |
| @@ -113741,33 +114015,37 @@ | |
| 113741 | } |
| 113742 | } |
| 113743 | } |
| 113744 | break; |
| 113745 | |
| 113746 | case PragTyp_STATS: { |
| 113747 | Index *pIdx; |
| 113748 | HashElem *i; |
| 113749 | pParse->nMem = 4; |
| 113750 | sqlite3CodeVerifySchema(pParse, iDb); |
| 113751 | for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ |
| 113752 | Table *pTab = sqliteHashData(i); |
| 113753 | sqlite3VdbeMultiLoad(v, 1, "ssii", |
| 113754 | pTab->zName, |
| 113755 | 0, |
| 113756 | pTab->szTabRow, |
| 113757 | pTab->nRowLogEst); |
| 113758 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 113759 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 113760 | sqlite3VdbeMultiLoad(v, 2, "sii", |
| 113761 | pIdx->zName, |
| 113762 | pIdx->szIdxRow, |
| 113763 | pIdx->aiRowLogEst[0]); |
| 113764 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 113765 | } |
| 113766 | } |
| 113767 | } |
| 113768 | break; |
| 113769 | |
| 113770 | case PragTyp_INDEX_INFO: if( zRight ){ |
| 113771 | Index *pIdx; |
| 113772 | Table *pTab; |
| 113773 | pIdx = sqlite3FindIndex(db, zRight, zDb); |
| @@ -114020,13 +114298,21 @@ | |
| 114020 | #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
| 114021 | # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 |
| 114022 | #endif |
| 114023 | |
| 114024 | #ifndef SQLITE_OMIT_INTEGRITY_CHECK |
| 114025 | /* Pragma "quick_check" is reduced version of |
| 114026 | ** integrity_check designed to detect most database corruption |
| 114027 | ** without most of the overhead of a full integrity-check. |
| 114028 | */ |
| 114029 | case PragTyp_INTEGRITY_CHECK: { |
| 114030 | int i, j, addr, mxErr; |
| 114031 | |
| 114032 | int isQuick = (sqlite3Tolower(zLeft[0])=='q'); |
| @@ -114053,11 +114339,11 @@ | |
| 114053 | sqlite3GetInt32(zRight, &mxErr); |
| 114054 | if( mxErr<=0 ){ |
| 114055 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 114056 | } |
| 114057 | } |
| 114058 | sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ |
| 114059 | |
| 114060 | /* Do an integrity check on each database file */ |
| 114061 | for(i=0; i<db->nDb; i++){ |
| 114062 | HashElem *x; |
| 114063 | Hash *pTbls; |
| @@ -114068,14 +114354,10 @@ | |
| 114068 | |
| 114069 | if( OMIT_TEMPDB && i==1 ) continue; |
| 114070 | if( iDb>=0 && i!=iDb ) continue; |
| 114071 | |
| 114072 | sqlite3CodeVerifySchema(pParse, i); |
| 114073 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ |
| 114074 | VdbeCoverage(v); |
| 114075 | sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
| 114076 | sqlite3VdbeJumpHere(v, addr); |
| 114077 | |
| 114078 | /* Do an integrity check of the B-Tree |
| 114079 | ** |
| 114080 | ** Begin by finding the root pages numbers |
| 114081 | ** for all tables and indices in the database. |
| @@ -114111,29 +114393,30 @@ | |
| 114111 | sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, |
| 114112 | sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), |
| 114113 | P4_DYNAMIC); |
| 114114 | sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); |
| 114115 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); |
| 114116 | sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); |
| 114117 | sqlite3VdbeJumpHere(v, addr); |
| 114118 | |
| 114119 | /* Make sure all the indices are constructed correctly. |
| 114120 | */ |
| 114121 | for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ |
| 114122 | Table *pTab = sqliteHashData(x); |
| 114123 | Index *pIdx, *pPk; |
| 114124 | Index *pPrior = 0; |
| 114125 | int loopTop; |
| 114126 | int iDataCur, iIdxCur; |
| 114127 | int r1 = -1; |
| 114128 | |
| 114129 | if( pTab->pIndex==0 ) continue; |
| 114130 | pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
| 114131 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ |
| 114132 | VdbeCoverage(v); |
| 114133 | sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
| 114134 | sqlite3VdbeJumpHere(v, addr); |
| 114135 | sqlite3ExprCacheClear(pParse); |
| 114136 | sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, |
| 114137 | 1, 0, &iDataCur, &iIdxCur); |
| 114138 | sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); |
| 114139 | for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
| @@ -114144,28 +114427,46 @@ | |
| 114144 | sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); |
| 114145 | loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); |
| 114146 | /* Verify that all NOT NULL columns really are NOT NULL */ |
| 114147 | for(j=0; j<pTab->nCol; j++){ |
| 114148 | char *zErr; |
| 114149 | int jmp2, jmp3; |
| 114150 | if( j==pTab->iPKey ) continue; |
| 114151 | if( pTab->aCol[j].notNull==0 ) continue; |
| 114152 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); |
| 114153 | sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); |
| 114154 | jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); |
| 114155 | sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
| 114156 | zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, |
| 114157 | pTab->aCol[j].zName); |
| 114158 | sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); |
| 114159 | sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); |
| 114160 | jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); |
| 114161 | sqlite3VdbeAddOp0(v, OP_Halt); |
| 114162 | sqlite3VdbeJumpHere(v, jmp2); |
| 114163 | sqlite3VdbeJumpHere(v, jmp3); |
| 114164 | } |
| 114165 | /* Validate index entries for the current row */ |
| 114166 | for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
| 114167 | int jmp2, jmp3, jmp4, jmp5; |
| 114168 | int ckUniq = sqlite3VdbeMakeLabel(v); |
| 114169 | if( pPk==pIdx ) continue; |
| 114170 | r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, |
| 114171 | pPrior, r1); |
| @@ -114172,20 +114473,17 @@ | |
| 114172 | pPrior = pIdx; |
| 114173 | sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ |
| 114174 | /* Verify that an index entry exists for the current table row */ |
| 114175 | jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, |
| 114176 | pIdx->nColumn); VdbeCoverage(v); |
| 114177 | sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
| 114178 | sqlite3VdbeLoadString(v, 3, "row "); |
| 114179 | sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); |
| 114180 | sqlite3VdbeLoadString(v, 4, " missing from index "); |
| 114181 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
| 114182 | jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); |
| 114183 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
| 114184 | sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); |
| 114185 | jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); |
| 114186 | sqlite3VdbeAddOp0(v, OP_Halt); |
| 114187 | sqlite3VdbeJumpHere(v, jmp2); |
| 114188 | /* For UNIQUE indexes, verify that only one entry exists with the |
| 114189 | ** current key. The entry is unique if (1) any column is NULL |
| 114190 | ** or (2) the next entry has a different key */ |
| 114191 | if( IsUniqueIndex(pIdx) ){ |
| @@ -114202,11 +114500,10 @@ | |
| 114202 | jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
| 114203 | sqlite3VdbeGoto(v, uniqOk); |
| 114204 | sqlite3VdbeJumpHere(v, jmp6); |
| 114205 | sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, |
| 114206 | pIdx->nKeyCol); VdbeCoverage(v); |
| 114207 | sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
| 114208 | sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); |
| 114209 | sqlite3VdbeGoto(v, jmp5); |
| 114210 | sqlite3VdbeResolveLabel(v, uniqOk); |
| 114211 | } |
| 114212 | sqlite3VdbeJumpHere(v, jmp4); |
| @@ -114213,40 +114510,39 @@ | |
| 114213 | sqlite3ResolvePartIdxLabel(pParse, jmp3); |
| 114214 | } |
| 114215 | sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); |
| 114216 | sqlite3VdbeJumpHere(v, loopTop-1); |
| 114217 | #ifndef SQLITE_OMIT_BTREECOUNT |
| 114218 | sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); |
| 114219 | for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
| 114220 | if( pPk==pIdx ) continue; |
| 114221 | addr = sqlite3VdbeCurrentAddr(v); |
| 114222 | sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); |
| 114223 | sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
| 114224 | sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); |
| 114225 | sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); |
| 114226 | sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
| 114227 | sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); |
| 114228 | sqlite3VdbeLoadString(v, 3, pIdx->zName); |
| 114229 | sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); |
| 114230 | sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1); |
| 114231 | } |
| 114232 | #endif /* SQLITE_OMIT_BTREECOUNT */ |
| 114233 | } |
| 114234 | } |
| 114235 | { |
| 114236 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 114237 | static const VdbeOpList endCode[] = { |
| 114238 | { OP_AddImm, 1, 0, 0}, /* 0 */ |
| 114239 | { OP_If, 1, 4, 0}, /* 1 */ |
| 114240 | { OP_String8, 0, 3, 0}, /* 2 */ |
| 114241 | { OP_ResultRow, 3, 1, 0}, /* 3 */ |
| 114242 | }; |
| 114243 | VdbeOp *aOp; |
| 114244 | |
| 114245 | aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
| 114246 | if( aOp ){ |
| 114247 | aOp[0].p2 = -mxErr; |
| 114248 | aOp[2].p4type = P4_STATIC; |
| 114249 | aOp[2].p4.z = "ok"; |
| 114250 | } |
| 114251 | } |
| 114252 | } |
| @@ -114466,10 +114762,122 @@ | |
| 114466 | */ |
| 114467 | case PragTyp_SHRINK_MEMORY: { |
| 114468 | sqlite3_db_release_memory(db); |
| 114469 | break; |
| 114470 | } |
| 114471 | |
| 114472 | /* |
| 114473 | ** PRAGMA busy_timeout |
| 114474 | ** PRAGMA busy_timeout = N |
| 114475 | ** |
| @@ -123782,12 +124190,29 @@ | |
| 123782 | ** transient would cause the database file to appear to be deleted |
| 123783 | ** following reboot. |
| 123784 | */ |
| 123785 | SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ |
| 123786 | Vdbe *v = sqlite3GetVdbe(pParse); |
| 123787 | int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0; |
| 123788 | if( v && (iDb>=2 || iDb==0) ){ |
| 123789 | sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); |
| 123790 | sqlite3VdbeUsesBtree(v, iDb); |
| 123791 | } |
| 123792 | return; |
| 123793 | } |
| @@ -124377,12 +124802,11 @@ | |
| 124377 | |
| 124378 | db = pParse->db; |
| 124379 | iDb = sqlite3SchemaToIndex(db, pTable->pSchema); |
| 124380 | assert( iDb>=0 ); |
| 124381 | |
| 124382 | pTable->tabFlags |= TF_Virtual; |
| 124383 | pTable->nModuleArg = 0; |
| 124384 | addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); |
| 124385 | addModuleArgument(db, pTable, 0); |
| 124386 | addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); |
| 124387 | assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) |
| 124388 | || (pParse->sNameToken.z==pName1->z && pName2->z==0) |
| @@ -124666,11 +125090,11 @@ | |
| 124666 | const char *zMod; |
| 124667 | Module *pMod; |
| 124668 | int rc; |
| 124669 | |
| 124670 | assert( pTab ); |
| 124671 | if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){ |
| 124672 | return SQLITE_OK; |
| 124673 | } |
| 124674 | |
| 124675 | /* Locate the required virtual table module */ |
| 124676 | zMod = pTab->azModuleArg[0]; |
| @@ -124736,11 +125160,11 @@ | |
| 124736 | Table *pTab; |
| 124737 | Module *pMod; |
| 124738 | const char *zMod; |
| 124739 | |
| 124740 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); |
| 124741 | assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); |
| 124742 | |
| 124743 | /* Locate the required virtual table module */ |
| 124744 | zMod = pTab->azModuleArg[0]; |
| 124745 | pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); |
| 124746 | |
| @@ -124790,11 +125214,11 @@ | |
| 124790 | sqlite3Error(db, SQLITE_MISUSE); |
| 124791 | sqlite3_mutex_leave(db->mutex); |
| 124792 | return SQLITE_MISUSE_BKPT; |
| 124793 | } |
| 124794 | pTab = pCtx->pTab; |
| 124795 | assert( (pTab->tabFlags & TF_Virtual)!=0 ); |
| 124796 | |
| 124797 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 124798 | if( pParse==0 ){ |
| 124799 | rc = SQLITE_NOMEM_BKPT; |
| 124800 | }else{ |
| @@ -124804,11 +125228,11 @@ | |
| 124804 | |
| 124805 | if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) |
| 124806 | && pParse->pNewTable |
| 124807 | && !db->mallocFailed |
| 124808 | && !pParse->pNewTable->pSelect |
| 124809 | && (pParse->pNewTable->tabFlags & TF_Virtual)==0 |
| 124810 | ){ |
| 124811 | if( !pTab->aCol ){ |
| 124812 | Table *pNew = pParse->pNewTable; |
| 124813 | Index *pIdx; |
| 124814 | pTab->aCol = pNew->aCol; |
| @@ -125093,11 +125517,11 @@ | |
| 125093 | /* Check to see the left operand is a column in a virtual table */ |
| 125094 | if( NEVER(pExpr==0) ) return pDef; |
| 125095 | if( pExpr->op!=TK_COLUMN ) return pDef; |
| 125096 | pTab = pExpr->pTab; |
| 125097 | if( NEVER(pTab==0) ) return pDef; |
| 125098 | if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef; |
| 125099 | pVtab = sqlite3GetVTable(db, pTab)->pVtab; |
| 125100 | assert( pVtab!=0 ); |
| 125101 | assert( pVtab->pModule!=0 ); |
| 125102 | pMod = (sqlite3_module *)pVtab->pModule; |
| 125103 | if( pMod->xFindFunction==0 ) return pDef; |
| @@ -125188,12 +125612,11 @@ | |
| 125188 | return 0; |
| 125189 | } |
| 125190 | pMod->pEpoTab = pTab; |
| 125191 | pTab->nTabRef = 1; |
| 125192 | pTab->pSchema = db->aDb[0].pSchema; |
| 125193 | pTab->tabFlags |= TF_Virtual; |
| 125194 | pTab->nModuleArg = 0; |
| 125195 | pTab->iPKey = -1; |
| 125196 | addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
| 125197 | addModuleArgument(db, pTab, 0); |
| 125198 | addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
| 125199 | rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); |
| @@ -125260,11 +125683,11 @@ | |
| 125260 | case SQLITE_VTAB_CONSTRAINT_SUPPORT: { |
| 125261 | VtabCtx *p = db->pVtabCtx; |
| 125262 | if( !p ){ |
| 125263 | rc = SQLITE_MISUSE_BKPT; |
| 125264 | }else{ |
| 125265 | assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 ); |
| 125266 | p->pVTable->bConstraint = (u8)va_arg(ap, int); |
| 125267 | } |
| 125268 | break; |
| 125269 | } |
| 125270 | default: |
| @@ -125699,12 +126122,17 @@ | |
| 125699 | WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ |
| 125700 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 125701 | UnpackedRecord *pRec; /* Probe for stat4 (if required) */ |
| 125702 | int nRecValid; /* Number of valid fields currently in pRec */ |
| 125703 | #endif |
| 125704 | }; |
| 125705 | |
| 125706 | /* |
| 125707 | ** The WHERE clause processing routine has two halves. The |
| 125708 | ** first part does the start of the WHERE loop and the second |
| 125709 | ** half does the tail of the WHERE loop. An instance of |
| 125710 | ** this structure is returned by the first half and passed |
| @@ -125715,11 +126143,11 @@ | |
| 125715 | */ |
| 125716 | struct WhereInfo { |
| 125717 | Parse *pParse; /* Parsing and code generating context */ |
| 125718 | SrcList *pTabList; /* List of tables in the join */ |
| 125719 | ExprList *pOrderBy; /* The ORDER BY clause or NULL */ |
| 125720 | ExprList *pDistinctSet; /* DISTINCT over all these values */ |
| 125721 | LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ |
| 125722 | int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ |
| 125723 | int iContinue; /* Jump here to continue with next record */ |
| 125724 | int iBreak; /* Jump here to break out of the loop */ |
| 125725 | int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ |
| @@ -126899,10 +127327,11 @@ | |
| 126899 | Parse *pParse; /* Parsing context */ |
| 126900 | sqlite3 *db; /* Database connection */ |
| 126901 | Vdbe *v; /* The prepared stmt under constructions */ |
| 126902 | struct SrcList_item *pTabItem; /* FROM clause term being coded */ |
| 126903 | int addrBrk; /* Jump here to break out of the loop */ |
| 126904 | int addrCont; /* Jump here to continue with next cycle */ |
| 126905 | int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ |
| 126906 | int iReleaseReg = 0; /* Temp register to free before returning */ |
| 126907 | |
| 126908 | pParse = pWInfo->pParse; |
| @@ -126939,10 +127368,15 @@ | |
| 126939 | if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ |
| 126940 | pLevel->iLeftJoin = ++pParse->nMem; |
| 126941 | sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); |
| 126942 | VdbeComment((v, "init LEFT JOIN no-match flag")); |
| 126943 | } |
| 126944 | |
| 126945 | /* Special case of a FROM clause subquery implemented as a co-routine */ |
| 126946 | if( pTabItem->fg.viaCoroutine ){ |
| 126947 | int regYield = pTabItem->regReturn; |
| 126948 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); |
| @@ -127124,11 +127558,11 @@ | |
| 127124 | VdbeCoverageIf(v, pX->op==TK_LT); |
| 127125 | VdbeCoverageIf(v, pX->op==TK_GE); |
| 127126 | sqlite3ExprCacheAffinityChange(pParse, r1, 1); |
| 127127 | sqlite3ReleaseTempReg(pParse, rTemp); |
| 127128 | }else{ |
| 127129 | sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); |
| 127130 | VdbeCoverageIf(v, bRev==0); |
| 127131 | VdbeCoverageIf(v, bRev!=0); |
| 127132 | } |
| 127133 | if( pEnd ){ |
| 127134 | Expr *pX; |
| @@ -127770,11 +128204,11 @@ | |
| 127770 | pLevel->op = OP_Noop; |
| 127771 | }else{ |
| 127772 | codeCursorHint(pTabItem, pWInfo, pLevel, 0); |
| 127773 | pLevel->op = aStep[bRev]; |
| 127774 | pLevel->p1 = iCur; |
| 127775 | pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); |
| 127776 | VdbeCoverageIf(v, bRev==0); |
| 127777 | VdbeCoverageIf(v, bRev!=0); |
| 127778 | pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; |
| 127779 | } |
| 127780 | } |
| @@ -128095,19 +128529,10 @@ | |
| 128095 | #ifdef SQLITE_EBCDIC |
| 128096 | if( *pnoCase ) return 0; |
| 128097 | #endif |
| 128098 | pList = pExpr->x.pList; |
| 128099 | pLeft = pList->a[1].pExpr; |
| 128100 | if( pLeft->op!=TK_COLUMN |
| 128101 | || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT |
| 128102 | || IsVirtual(pLeft->pTab) /* Value might be numeric */ |
| 128103 | ){ |
| 128104 | /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must |
| 128105 | ** be the name of an indexed column with TEXT affinity. */ |
| 128106 | return 0; |
| 128107 | } |
| 128108 | assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ |
| 128109 | |
| 128110 | pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); |
| 128111 | op = pRight->op; |
| 128112 | if( op==TK_VARIABLE ){ |
| 128113 | Vdbe *pReprepare = pParse->pReprepare; |
| @@ -128120,10 +128545,27 @@ | |
| 128120 | assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); |
| 128121 | }else if( op==TK_STRING ){ |
| 128122 | z = pRight->u.zToken; |
| 128123 | } |
| 128124 | if( z ){ |
| 128125 | cnt = 0; |
| 128126 | while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ |
| 128127 | cnt++; |
| 128128 | } |
| 128129 | if( cnt!=0 && 255!=(u8)z[cnt-1] ){ |
| @@ -128748,11 +129190,11 @@ | |
| 128748 | iCur = pFrom->a[i].iCursor; |
| 128749 | for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 128750 | if( pIdx->aColExpr==0 ) continue; |
| 128751 | for(i=0; i<pIdx->nKeyCol; i++){ |
| 128752 | if( pIdx->aiColumn[i]!=XN_EXPR ) continue; |
| 128753 | if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ |
| 128754 | *piCur = iCur; |
| 128755 | *piColumn = XN_EXPR; |
| 128756 | return 1; |
| 128757 | } |
| 128758 | } |
| @@ -129539,11 +129981,12 @@ | |
| 129539 | do{ |
| 129540 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 129541 | if( pTerm->leftCursor==iCur |
| 129542 | && pTerm->u.leftColumn==iColumn |
| 129543 | && (iColumn!=XN_EXPR |
| 129544 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| 129545 | && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) |
| 129546 | ){ |
| 129547 | if( (pTerm->eOperator & WO_EQUIV)!=0 |
| 129548 | && pScan->nEquiv<ArraySize(pScan->aiCur) |
| 129549 | && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN |
| @@ -131716,10 +132159,15 @@ | |
| 131716 | testcase( eOp & WO_IS ); |
| 131717 | testcase( eOp & WO_ISNULL ); |
| 131718 | continue; |
| 131719 | } |
| 131720 | |
| 131721 | pNew->wsFlags = saved_wsFlags; |
| 131722 | pNew->u.btree.nEq = saved_nEq; |
| 131723 | pNew->u.btree.nBtm = saved_nBtm; |
| 131724 | pNew->u.btree.nTop = saved_nTop; |
| 131725 | pNew->nLTerm = saved_nLTerm; |
| @@ -132263,11 +132711,19 @@ | |
| 132263 | pNew->nOut = rSize; |
| 132264 | if( rc ) break; |
| 132265 | } |
| 132266 | } |
| 132267 | |
| 132268 | rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); |
| 132269 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 132270 | sqlite3Stat4ProbeFree(pBuilder->pRec); |
| 132271 | pBuilder->nRecValid = 0; |
| 132272 | pBuilder->pRec = 0; |
| 132273 | #endif |
| @@ -133443,13 +133899,13 @@ | |
| 133443 | && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 |
| 133444 | && pWInfo->eDistinct==WHERE_DISTINCT_NOOP |
| 133445 | && nRowEst |
| 133446 | ){ |
| 133447 | Bitmask notUsed; |
| 133448 | int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom, |
| 133449 | WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); |
| 133450 | if( rc==pWInfo->pDistinctSet->nExpr ){ |
| 133451 | pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; |
| 133452 | } |
| 133453 | } |
| 133454 | if( pWInfo->pOrderBy ){ |
| 133455 | if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ |
| @@ -133682,11 +134138,11 @@ | |
| 133682 | SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( |
| 133683 | Parse *pParse, /* The parser context */ |
| 133684 | SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ |
| 133685 | Expr *pWhere, /* The WHERE clause */ |
| 133686 | ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ |
| 133687 | ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */ |
| 133688 | u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ |
| 133689 | int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number |
| 133690 | ** If WHERE_USE_LIMIT, then the limit amount */ |
| 133691 | ){ |
| 133692 | int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ |
| @@ -133758,11 +134214,11 @@ | |
| 133758 | goto whereBeginError; |
| 133759 | } |
| 133760 | pWInfo->pParse = pParse; |
| 133761 | pWInfo->pTabList = pTabList; |
| 133762 | pWInfo->pOrderBy = pOrderBy; |
| 133763 | pWInfo->pDistinctSet = pDistinctSet; |
| 133764 | pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; |
| 133765 | pWInfo->nLevel = nTabList; |
| 133766 | pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); |
| 133767 | pWInfo->wctrlFlags = wctrlFlags; |
| 133768 | pWInfo->iLimit = iAuxArg; |
| @@ -133836,17 +134292,17 @@ | |
| 133836 | /* Analyze all of the subexpressions. */ |
| 133837 | sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); |
| 133838 | if( db->mallocFailed ) goto whereBeginError; |
| 133839 | |
| 133840 | if( wctrlFlags & WHERE_WANT_DISTINCT ){ |
| 133841 | if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){ |
| 133842 | /* The DISTINCT marking is pointless. Ignore it. */ |
| 133843 | pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; |
| 133844 | }else if( pOrderBy==0 ){ |
| 133845 | /* Try to ORDER BY the result set to make distinct processing easier */ |
| 133846 | pWInfo->wctrlFlags |= WHERE_DISTINCTBY; |
| 133847 | pWInfo->pOrderBy = pDistinctSet; |
| 133848 | } |
| 133849 | } |
| 133850 | |
| 133851 | /* Construct the WhereLoop objects */ |
| 133852 | #if defined(WHERETRACE_ENABLED) |
| @@ -133918,14 +134374,14 @@ | |
| 133918 | } |
| 133919 | } |
| 133920 | #endif |
| 133921 | /* Attempt to omit tables from the join that do not effect the result */ |
| 133922 | if( pWInfo->nLevel>=2 |
| 133923 | && pDistinctSet!=0 |
| 133924 | && OptimizationEnabled(db, SQLITE_OmitNoopJoin) |
| 133925 | ){ |
| 133926 | Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet); |
| 133927 | if( sWLB.pOrderBy ){ |
| 133928 | tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); |
| 133929 | } |
| 133930 | while( pWInfo->nLevel>=2 ){ |
| 133931 | WhereTerm *pTerm, *pEnd; |
| @@ -134704,166 +135160,166 @@ | |
| 134704 | ** |
| 134705 | *********** Begin parsing tables **********************************************/ |
| 134706 | #define YY_ACTTAB_COUNT (1567) |
| 134707 | static const YYACTIONTYPE yy_action[] = { |
| 134708 | /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100, |
| 134709 | /* 10 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, |
| 134710 | /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, |
| 134711 | /* 30 */ 94, 94, 94, 93, 351, 325, 977, 977, 824, 824, |
| 134712 | /* 40 */ 826, 947, 354, 99, 100, 90, 842, 842, 854, 857, |
| 134713 | /* 50 */ 846, 846, 97, 97, 98, 98, 98, 98, 338, 96, |
| 134714 | /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 134715 | /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 977, 977, |
| 134716 | /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100, |
| 134717 | /* 90 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, |
| 134718 | /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, |
| 134719 | /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325, |
| 134720 | /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, |
| 134721 | /* 130 */ 842, 842, 854, 857, 846, 846, 97, 97, 98, 98, |
| 134722 | /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, |
| 134723 | /* 150 */ 94, 94, 93, 351, 958, 958, 325, 268, 428, 413, |
| 134724 | /* 160 */ 411, 61, 752, 752, 99, 100, 90, 842, 842, 854, |
| 134725 | /* 170 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 60, |
| 134726 | /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134727 | /* 190 */ 351, 325, 270, 329, 273, 277, 959, 960, 250, 99, |
| 134728 | /* 200 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 134729 | /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, |
| 134730 | /* 220 */ 95, 94, 94, 94, 93, 351, 325, 938, 1326, 698, |
| 134731 | /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 842, 842, 854, |
| 134732 | /* 240 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 347, |
| 134733 | /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134734 | /* 260 */ 351, 325, 938, 1327, 384, 699, 1327, 381, 379, 99, |
| 134735 | /* 270 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 134736 | /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95, |
| 134737 | /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, |
| 134738 | /* 300 */ 833, 936, 373, 700, 99, 100, 90, 842, 842, 854, |
| 134739 | /* 310 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 375, |
| 134740 | /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134741 | /* 330 */ 351, 325, 1276, 947, 354, 818, 936, 739, 739, 99, |
| 134742 | /* 340 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 134743 | /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, |
| 134744 | /* 360 */ 95, 94, 94, 94, 93, 351, 325, 969, 227, 92, |
| 134745 | /* 370 */ 89, 178, 373, 300, 99, 100, 90, 842, 842, 854, |
| 134746 | /* 380 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 921, |
| 134747 | /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134748 | /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99, |
| 134749 | /* 410 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 134750 | /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, |
| 134751 | /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 958, |
| 134752 | /* 440 */ 958, 158, 25, 422, 99, 100, 90, 842, 842, 854, |
| 134753 | /* 450 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 450, |
| 134754 | /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134755 | /* 470 */ 351, 443, 224, 224, 420, 958, 958, 962, 325, 52, |
| 134756 | /* 480 */ 52, 959, 960, 176, 415, 78, 99, 100, 90, 842, |
| 134757 | /* 490 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, |
| 134758 | /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, |
| 134759 | /* 510 */ 94, 93, 351, 325, 428, 418, 298, 959, 960, 962, |
| 134760 | /* 520 */ 81, 99, 88, 90, 842, 842, 854, 857, 846, 846, |
| 134761 | /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96, |
| 134762 | /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 843, |
| 134763 | /* 550 */ 843, 855, 858, 996, 318, 343, 379, 100, 90, 842, |
| 134764 | /* 560 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, |
| 134765 | /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, |
| 134766 | /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, |
| 134767 | /* 590 */ 929, 52, 52, 90, 842, 842, 854, 857, 846, 846, |
| 134768 | /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, |
| 134769 | /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, |
| 134770 | /* 620 */ 847, 3, 1203, 361, 360, 378, 344, 813, 958, 958, |
| 134771 | /* 630 */ 1300, 86, 445, 729, 3, 212, 169, 287, 405, 282, |
| 134772 | /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245, |
| 134773 | /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, |
| 134774 | /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, |
| 134775 | /* 670 */ 959, 960, 194, 455, 670, 402, 399, 398, 448, 243, |
| 134776 | /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224, |
| 134777 | /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427, |
| 134778 | /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452, |
| 134779 | /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1271, |
| 134780 | /* 720 */ 1271, 23, 958, 958, 86, 445, 397, 3, 228, 429, |
| 134781 | /* 730 */ 895, 824, 824, 826, 827, 19, 203, 720, 52, 52, |
| 134782 | /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229, |
| 134783 | /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85, |
| 134784 | /* 760 */ 352, 352, 120, 157, 959, 960, 58, 977, 409, 355, |
| 134785 | /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86, |
| 134786 | /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96, |
| 134787 | /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 134788 | /* 800 */ 832, 120, 452, 451, 813, 887, 819, 83, 84, 977, |
| 134789 | /* 810 */ 813, 132, 410, 920, 85, 352, 352, 132, 407, 789, |
| 134790 | /* 820 */ 958, 958, 92, 89, 178, 917, 448, 262, 370, 261, |
| 134791 | /* 830 */ 82, 914, 80, 262, 370, 261, 776, 824, 824, 826, |
| 134792 | /* 840 */ 827, 19, 934, 434, 96, 96, 96, 96, 95, 95, |
| 134793 | /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 958, |
| 134794 | /* 860 */ 958, 819, 959, 960, 120, 92, 89, 178, 945, 2, |
| 134795 | /* 870 */ 918, 965, 268, 1, 976, 76, 445, 762, 3, 708, |
| 134796 | /* 880 */ 901, 901, 387, 958, 958, 757, 919, 371, 740, 778, |
| 134797 | /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450, |
| 134798 | /* 900 */ 24, 959, 960, 83, 84, 369, 958, 958, 177, 226, |
| 134799 | /* 910 */ 85, 352, 352, 885, 315, 314, 313, 215, 311, 10, |
| 134800 | /* 920 */ 10, 683, 448, 349, 348, 959, 960, 909, 777, 157, |
| 134801 | /* 930 */ 120, 958, 958, 337, 776, 416, 711, 310, 450, 434, |
| 134802 | /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 959, 960, |
| 134803 | /* 950 */ 908, 832, 792, 452, 451, 9, 9, 819, 10, 10, |
| 134804 | /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171, |
| 134805 | /* 970 */ 170, 167, 339, 959, 960, 247, 984, 702, 702, 450, |
| 134806 | /* 980 */ 715, 233, 686, 982, 889, 983, 182, 914, 824, 824, |
| 134807 | /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10, |
| 134808 | /* 1000 */ 10, 889, 891, 749, 958, 958, 917, 268, 985, 198, |
| 134809 | /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825, |
| 134810 | /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91, |
| 134811 | /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 134812 | /* 1040 */ 351, 157, 810, 371, 382, 359, 959, 960, 358, 268, |
| 134813 | /* 1050 */ 450, 918, 368, 324, 824, 824, 826, 450, 709, 450, |
| 134814 | /* 1060 */ 264, 380, 889, 450, 877, 746, 253, 919, 255, 433, |
| 134815 | /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12, |
| 134816 | /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162, |
| 134817 | /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450, |
| 134818 | /* 1100 */ 709, 1210, 450, 132, 450, 39, 39, 450, 40, 40, |
| 134819 | /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28, |
| 134820 | /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450, |
| 134821 | /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767, |
| 134822 | /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47, |
| 134823 | /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172, |
| 134824 | /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122, |
| 134825 | /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 898, 56, 56, |
| 134826 | /* 1180 */ 450, 897, 35, 35, 450, 267, 450, 817, 450, 817, |
| 134827 | /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817, |
| 134828 | /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119, |
| 134829 | /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111, |
| 134830 | /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 912, |
| 134831 | /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331, |
| 134832 | /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 937, 197, |
| 134833 | /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436, |
| 134834 | /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 933, |
| 134835 | /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202, |
| 134836 | /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 884, |
| 134837 | /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74, |
| 134838 | /* 1300 */ 726, 727, 785, 783, 880, 202, 999, 208, 894, 893, |
| 134839 | /* 1310 */ 894, 893, 694, 816, 763, 116, 774, 1290, 431, 432, |
| 134840 | /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289, |
| 134841 | /* 1330 */ 679, 884, 681, 952, 291, 218, 293, 7, 316, 828, |
| 134842 | /* 1340 */ 173, 805, 259, 364, 252, 911, 376, 713, 295, 435, |
| 134843 | /* 1350 */ 308, 168, 955, 993, 135, 400, 990, 284, 882, 881, |
| 134844 | /* 1360 */ 205, 928, 926, 59, 333, 62, 144, 156, 130, 72, |
| 134845 | /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383, |
| 134846 | /* 1380 */ 67, 896, 140, 141, 142, 148, 389, 812, 775, 266, |
| 134847 | /* 1390 */ 219, 190, 154, 391, 913, 876, 271, 406, 191, 322, |
| 134848 | /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421, |
| 134849 | /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346, |
| 134850 | /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 967, 239, |
| 134851 | /* 1430 */ 769, 102, 862, 438, 426, 240, 424, 442, 73, 213, |
| 134852 | /* 1440 */ 688, 238, 22, 453, 953, 214, 217, 216, 454, 677, |
| 134853 | /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166, |
| 134854 | /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 892, |
| 134855 | /* 1470 */ 327, 890, 811, 328, 134, 128, 136, 138, 743, 258, |
| 134856 | /* 1480 */ 907, 184, 143, 129, 910, 186, 63, 64, 145, 187, |
| 134857 | /* 1490 */ 906, 65, 8, 66, 13, 188, 202, 899, 265, 149, |
| 134858 | /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396, |
| 134859 | /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131, |
| 134860 | /* 1520 */ 830, 860, 70, 751, 16, 414, 755, 4, 174, 220, |
| 134861 | /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 875, |
| 134862 | /* 1540 */ 861, 859, 916, 864, 915, 207, 206, 942, 163, 437, |
| 134863 | /* 1550 */ 948, 943, 164, 209, 1002, 441, 863, 165, 210, 829, |
| 134864 | /* 1560 */ 695, 87, 312, 211, 1292, 1291, 309, |
| 134865 | }; |
| 134866 | static const YYCODETYPE yy_lookahead[] = { |
| 134867 | /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, |
| 134868 | /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
| 134869 | /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, |
| @@ -135112,55 +135568,55 @@ | |
| 135112 | /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278, |
| 135113 | /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228, |
| 135114 | /* 320 */ 1288, 1291, 1276, 1277, 1295, |
| 135115 | }; |
| 135116 | static const YYACTIONTYPE yy_default[] = { |
| 135117 | /* 0 */ 1281, 1271, 1271, 1271, 1203, 1203, 1203, 1203, 1271, 1096, |
| 135118 | /* 10 */ 1125, 1125, 1255, 1332, 1332, 1332, 1332, 1332, 1332, 1202, |
| 135119 | /* 20 */ 1332, 1332, 1332, 1332, 1271, 1100, 1131, 1332, 1332, 1332, |
| 135120 | /* 30 */ 1332, 1204, 1205, 1332, 1332, 1332, 1254, 1256, 1141, 1140, |
| 135121 | /* 40 */ 1139, 1138, 1237, 1112, 1136, 1129, 1133, 1204, 1198, 1199, |
| 135122 | /* 50 */ 1197, 1201, 1205, 1332, 1132, 1167, 1182, 1166, 1332, 1332, |
| 135123 | /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135124 | /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135125 | /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135126 | /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135127 | /* 100 */ 1332, 1332, 1332, 1332, 1176, 1181, 1188, 1180, 1177, 1169, |
| 135128 | /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, |
| 135129 | /* 120 */ 1332, 1173, 1185, 1184, 1183, 1262, 1289, 1288, 1332, 1332, |
| 135130 | /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135131 | /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135132 | /* 150 */ 1332, 1332, 1332, 1332, 1332, 1281, 1271, 1025, 1025, 1332, |
| 135133 | /* 160 */ 1271, 1271, 1271, 1271, 1271, 1271, 1267, 1100, 1091, 1332, |
| 135134 | /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135135 | /* 180 */ 1259, 1257, 1332, 1218, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135136 | /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135137 | /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, |
| 135138 | /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1283, 1332, 1232, |
| 135139 | /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, |
| 135140 | /* 230 */ 1321, 1135, 1321, 1042, 1303, 1039, 1125, 1114, 1200, 1125, |
| 135141 | /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, |
| 135142 | /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, |
| 135143 | /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1236, 1318, 1105, 1105, |
| 135144 | /* 270 */ 1016, 1211, 1105, 1016, 1105, 1016, 1211, 1068, 1068, 1068, |
| 135145 | /* 280 */ 1057, 1211, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, |
| 135146 | /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1206, 1105, 1332, |
| 135147 | /* 300 */ 1211, 1215, 1215, 1211, 1130, 1119, 1128, 1126, 1135, 1022, |
| 135148 | /* 310 */ 1060, 1286, 1286, 1282, 1282, 1282, 1282, 1329, 1329, 1267, |
| 135149 | /* 320 */ 1298, 1298, 1044, 1044, 1298, 1332, 1332, 1332, 1332, 1332, |
| 135150 | /* 330 */ 1332, 1293, 1332, 1220, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135151 | /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135152 | /* 350 */ 1332, 1332, 1152, 1332, 1000, 1264, 1332, 1332, 1263, 1332, |
| 135153 | /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135154 | /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, |
| 135155 | /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1235, 1234, 1332, 1332, |
| 135156 | /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135157 | /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135158 | /* 410 */ 1332, 1082, 1332, 1332, 1332, 1307, 1332, 1332, 1332, 1332, |
| 135159 | /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, |
| 135160 | /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1273, |
| 135161 | /* 440 */ 1332, 1332, 1332, 1272, 1332, 1332, 1332, 1332, 1332, 1154, |
| 135162 | /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, |
| 135163 | }; |
| 135164 | /********** End of lemon-generated parsing tables *****************************/ |
| 135165 | |
| 135166 | /* The next table maps tokens (terminal symbols) into fallback tokens. |
| @@ -135602,147 +136058,147 @@ | |
| 135602 | /* 169 */ "expr ::= expr EQ|NE expr", |
| 135603 | /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", |
| 135604 | /* 171 */ "expr ::= expr PLUS|MINUS expr", |
| 135605 | /* 172 */ "expr ::= expr STAR|SLASH|REM expr", |
| 135606 | /* 173 */ "expr ::= expr CONCAT expr", |
| 135607 | /* 174 */ "likeop ::= LIKE_KW|MATCH", |
| 135608 | /* 175 */ "likeop ::= NOT LIKE_KW|MATCH", |
| 135609 | /* 176 */ "expr ::= expr likeop expr", |
| 135610 | /* 177 */ "expr ::= expr likeop expr ESCAPE expr", |
| 135611 | /* 178 */ "expr ::= expr ISNULL|NOTNULL", |
| 135612 | /* 179 */ "expr ::= expr NOT NULL", |
| 135613 | /* 180 */ "expr ::= expr IS expr", |
| 135614 | /* 181 */ "expr ::= expr IS NOT expr", |
| 135615 | /* 182 */ "expr ::= NOT expr", |
| 135616 | /* 183 */ "expr ::= BITNOT expr", |
| 135617 | /* 184 */ "expr ::= MINUS expr", |
| 135618 | /* 185 */ "expr ::= PLUS expr", |
| 135619 | /* 186 */ "between_op ::= BETWEEN", |
| 135620 | /* 187 */ "between_op ::= NOT BETWEEN", |
| 135621 | /* 188 */ "expr ::= expr between_op expr AND expr", |
| 135622 | /* 189 */ "in_op ::= IN", |
| 135623 | /* 190 */ "in_op ::= NOT IN", |
| 135624 | /* 191 */ "expr ::= expr in_op LP exprlist RP", |
| 135625 | /* 192 */ "expr ::= LP select RP", |
| 135626 | /* 193 */ "expr ::= expr in_op LP select RP", |
| 135627 | /* 194 */ "expr ::= expr in_op nm dbnm paren_exprlist", |
| 135628 | /* 195 */ "expr ::= EXISTS LP select RP", |
| 135629 | /* 196 */ "expr ::= CASE case_operand case_exprlist case_else END", |
| 135630 | /* 197 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", |
| 135631 | /* 198 */ "case_exprlist ::= WHEN expr THEN expr", |
| 135632 | /* 199 */ "case_else ::= ELSE expr", |
| 135633 | /* 200 */ "case_else ::=", |
| 135634 | /* 201 */ "case_operand ::= expr", |
| 135635 | /* 202 */ "case_operand ::=", |
| 135636 | /* 203 */ "exprlist ::=", |
| 135637 | /* 204 */ "nexprlist ::= nexprlist COMMA expr", |
| 135638 | /* 205 */ "nexprlist ::= expr", |
| 135639 | /* 206 */ "paren_exprlist ::=", |
| 135640 | /* 207 */ "paren_exprlist ::= LP exprlist RP", |
| 135641 | /* 208 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", |
| 135642 | /* 209 */ "uniqueflag ::= UNIQUE", |
| 135643 | /* 210 */ "uniqueflag ::=", |
| 135644 | /* 211 */ "eidlist_opt ::=", |
| 135645 | /* 212 */ "eidlist_opt ::= LP eidlist RP", |
| 135646 | /* 213 */ "eidlist ::= eidlist COMMA nm collate sortorder", |
| 135647 | /* 214 */ "eidlist ::= nm collate sortorder", |
| 135648 | /* 215 */ "collate ::=", |
| 135649 | /* 216 */ "collate ::= COLLATE ID|STRING", |
| 135650 | /* 217 */ "cmd ::= DROP INDEX ifexists fullname", |
| 135651 | /* 218 */ "cmd ::= VACUUM", |
| 135652 | /* 219 */ "cmd ::= VACUUM nm", |
| 135653 | /* 220 */ "cmd ::= PRAGMA nm dbnm", |
| 135654 | /* 221 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", |
| 135655 | /* 222 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", |
| 135656 | /* 223 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", |
| 135657 | /* 224 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", |
| 135658 | /* 225 */ "plus_num ::= PLUS INTEGER|FLOAT", |
| 135659 | /* 226 */ "minus_num ::= MINUS INTEGER|FLOAT", |
| 135660 | /* 227 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", |
| 135661 | /* 228 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", |
| 135662 | /* 229 */ "trigger_time ::= BEFORE", |
| 135663 | /* 230 */ "trigger_time ::= AFTER", |
| 135664 | /* 231 */ "trigger_time ::= INSTEAD OF", |
| 135665 | /* 232 */ "trigger_time ::=", |
| 135666 | /* 233 */ "trigger_event ::= DELETE|INSERT", |
| 135667 | /* 234 */ "trigger_event ::= UPDATE", |
| 135668 | /* 235 */ "trigger_event ::= UPDATE OF idlist", |
| 135669 | /* 236 */ "when_clause ::=", |
| 135670 | /* 237 */ "when_clause ::= WHEN expr", |
| 135671 | /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", |
| 135672 | /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", |
| 135673 | /* 240 */ "trnm ::= nm DOT nm", |
| 135674 | /* 241 */ "tridxby ::= INDEXED BY nm", |
| 135675 | /* 242 */ "tridxby ::= NOT INDEXED", |
| 135676 | /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", |
| 135677 | /* 244 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", |
| 135678 | /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", |
| 135679 | /* 246 */ "trigger_cmd ::= select", |
| 135680 | /* 247 */ "expr ::= RAISE LP IGNORE RP", |
| 135681 | /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", |
| 135682 | /* 249 */ "raisetype ::= ROLLBACK", |
| 135683 | /* 250 */ "raisetype ::= ABORT", |
| 135684 | /* 251 */ "raisetype ::= FAIL", |
| 135685 | /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", |
| 135686 | /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", |
| 135687 | /* 254 */ "cmd ::= DETACH database_kw_opt expr", |
| 135688 | /* 255 */ "key_opt ::=", |
| 135689 | /* 256 */ "key_opt ::= KEY expr", |
| 135690 | /* 257 */ "cmd ::= REINDEX", |
| 135691 | /* 258 */ "cmd ::= REINDEX nm dbnm", |
| 135692 | /* 259 */ "cmd ::= ANALYZE", |
| 135693 | /* 260 */ "cmd ::= ANALYZE nm dbnm", |
| 135694 | /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", |
| 135695 | /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", |
| 135696 | /* 263 */ "add_column_fullname ::= fullname", |
| 135697 | /* 264 */ "cmd ::= create_vtab", |
| 135698 | /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", |
| 135699 | /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", |
| 135700 | /* 267 */ "vtabarg ::=", |
| 135701 | /* 268 */ "vtabargtoken ::= ANY", |
| 135702 | /* 269 */ "vtabargtoken ::= lp anylist RP", |
| 135703 | /* 270 */ "lp ::= LP", |
| 135704 | /* 271 */ "with ::=", |
| 135705 | /* 272 */ "with ::= WITH wqlist", |
| 135706 | /* 273 */ "with ::= WITH RECURSIVE wqlist", |
| 135707 | /* 274 */ "wqlist ::= nm eidlist_opt AS LP select RP", |
| 135708 | /* 275 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", |
| 135709 | /* 276 */ "input ::= cmdlist", |
| 135710 | /* 277 */ "cmdlist ::= cmdlist ecmd", |
| 135711 | /* 278 */ "cmdlist ::= ecmd", |
| 135712 | /* 279 */ "ecmd ::= SEMI", |
| 135713 | /* 280 */ "ecmd ::= explain cmdx SEMI", |
| 135714 | /* 281 */ "explain ::=", |
| 135715 | /* 282 */ "trans_opt ::=", |
| 135716 | /* 283 */ "trans_opt ::= TRANSACTION", |
| 135717 | /* 284 */ "trans_opt ::= TRANSACTION nm", |
| 135718 | /* 285 */ "savepoint_opt ::= SAVEPOINT", |
| 135719 | /* 286 */ "savepoint_opt ::=", |
| 135720 | /* 287 */ "cmd ::= create_table create_table_args", |
| 135721 | /* 288 */ "columnlist ::= columnlist COMMA columnname carglist", |
| 135722 | /* 289 */ "columnlist ::= columnname carglist", |
| 135723 | /* 290 */ "nm ::= ID|INDEXED", |
| 135724 | /* 291 */ "nm ::= STRING", |
| 135725 | /* 292 */ "nm ::= JOIN_KW", |
| 135726 | /* 293 */ "typetoken ::= typename", |
| 135727 | /* 294 */ "typename ::= ID|STRING", |
| 135728 | /* 295 */ "signed ::= plus_num", |
| 135729 | /* 296 */ "signed ::= minus_num", |
| 135730 | /* 297 */ "carglist ::= carglist ccons", |
| 135731 | /* 298 */ "carglist ::=", |
| 135732 | /* 299 */ "ccons ::= NULL onconf", |
| 135733 | /* 300 */ "conslist_opt ::= COMMA conslist", |
| 135734 | /* 301 */ "conslist ::= conslist tconscomma tcons", |
| 135735 | /* 302 */ "conslist ::= tcons", |
| 135736 | /* 303 */ "tconscomma ::=", |
| 135737 | /* 304 */ "defer_subclause_opt ::= defer_subclause", |
| 135738 | /* 305 */ "resolvetype ::= raisetype", |
| 135739 | /* 306 */ "selectnowith ::= oneselect", |
| 135740 | /* 307 */ "oneselect ::= values", |
| 135741 | /* 308 */ "sclp ::= selcollist COMMA", |
| 135742 | /* 309 */ "as ::= ID|STRING", |
| 135743 | /* 310 */ "expr ::= term", |
| 135744 | /* 311 */ "exprlist ::= nexprlist", |
| 135745 | /* 312 */ "nmnum ::= plus_num", |
| 135746 | /* 313 */ "nmnum ::= nm", |
| 135747 | /* 314 */ "nmnum ::= ON", |
| 135748 | /* 315 */ "nmnum ::= DELETE", |
| @@ -136375,11 +136831,10 @@ | |
| 136375 | { 173, 3 }, |
| 136376 | { 173, 3 }, |
| 136377 | { 173, 3 }, |
| 136378 | { 173, 3 }, |
| 136379 | { 173, 3 }, |
| 136380 | { 221, 1 }, |
| 136381 | { 221, 2 }, |
| 136382 | { 173, 3 }, |
| 136383 | { 173, 5 }, |
| 136384 | { 173, 2 }, |
| 136385 | { 173, 3 }, |
| @@ -136512,10 +136967,11 @@ | |
| 136512 | { 194, 1 }, |
| 136513 | { 195, 1 }, |
| 136514 | { 209, 2 }, |
| 136515 | { 210, 1 }, |
| 136516 | { 173, 1 }, |
| 136517 | { 208, 1 }, |
| 136518 | { 230, 1 }, |
| 136519 | { 230, 1 }, |
| 136520 | { 230, 1 }, |
| 136521 | { 230, 1 }, |
| @@ -136654,11 +137110,11 @@ | |
| 136654 | case 42: /* autoinc ::= */ yytestcase(yyruleno==42); |
| 136655 | case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); |
| 136656 | case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); |
| 136657 | case 76: /* ifexists ::= */ yytestcase(yyruleno==76); |
| 136658 | case 90: /* distinct ::= */ yytestcase(yyruleno==90); |
| 136659 | case 215: /* collate ::= */ yytestcase(yyruleno==215); |
| 136660 | {yymsp[1].minor.yy194 = 0;} |
| 136661 | break; |
| 136662 | case 17: /* ifnotexists ::= IF NOT EXISTS */ |
| 136663 | {yymsp[-2].minor.yy194 = 1;} |
| 136664 | break; |
| @@ -136798,13 +137254,13 @@ | |
| 136798 | case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); |
| 136799 | {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} |
| 136800 | break; |
| 136801 | case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ |
| 136802 | case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); |
| 136803 | case 187: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==187); |
| 136804 | case 190: /* in_op ::= NOT IN */ yytestcase(yyruleno==190); |
| 136805 | case 216: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==216); |
| 136806 | {yymsp[-1].minor.yy194 = 1;} |
| 136807 | break; |
| 136808 | case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ |
| 136809 | {yymsp[-1].minor.yy194 = 0;} |
| 136810 | break; |
| @@ -136964,13 +137420,13 @@ | |
| 136964 | {yymsp[0].minor.yy194 = SF_All;} |
| 136965 | break; |
| 136966 | case 91: /* sclp ::= */ |
| 136967 | case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); |
| 136968 | case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); |
| 136969 | case 203: /* exprlist ::= */ yytestcase(yyruleno==203); |
| 136970 | case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206); |
| 136971 | case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211); |
| 136972 | {yymsp[1].minor.yy148 = 0;} |
| 136973 | break; |
| 136974 | case 92: /* selcollist ::= sclp expr as */ |
| 136975 | { |
| 136976 | yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| @@ -136992,12 +137448,12 @@ | |
| 136992 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); |
| 136993 | } |
| 136994 | break; |
| 136995 | case 95: /* as ::= AS nm */ |
| 136996 | case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); |
| 136997 | case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225); |
| 136998 | case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226); |
| 136999 | {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} |
| 137000 | break; |
| 137001 | case 97: /* from ::= */ |
| 137002 | {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} |
| 137003 | break; |
| @@ -137076,18 +137532,18 @@ | |
| 137076 | {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} |
| 137077 | break; |
| 137078 | case 112: /* on_opt ::= ON expr */ |
| 137079 | case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); |
| 137080 | case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); |
| 137081 | case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199); |
| 137082 | {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} |
| 137083 | break; |
| 137084 | case 113: /* on_opt ::= */ |
| 137085 | case 128: /* having_opt ::= */ yytestcase(yyruleno==128); |
| 137086 | case 135: /* where_opt ::= */ yytestcase(yyruleno==135); |
| 137087 | case 200: /* case_else ::= */ yytestcase(yyruleno==200); |
| 137088 | case 202: /* case_operand ::= */ yytestcase(yyruleno==202); |
| 137089 | {yymsp[1].minor.yy72 = 0;} |
| 137090 | break; |
| 137091 | case 115: /* indexed_opt ::= INDEXED BY nm */ |
| 137092 | {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} |
| 137093 | break; |
| @@ -137230,11 +137686,11 @@ | |
| 137230 | case 158: /* term ::= INTEGER */ |
| 137231 | { |
| 137232 | yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); |
| 137233 | yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; |
| 137234 | yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; |
| 137235 | if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf; |
| 137236 | } |
| 137237 | yymsp[0].minor.yy190 = yylhsminor.yy190; |
| 137238 | break; |
| 137239 | case 159: /* expr ::= VARIABLE */ |
| 137240 | { |
| @@ -137320,17 +137776,14 @@ | |
| 137320 | case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); |
| 137321 | case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); |
| 137322 | case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); |
| 137323 | {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} |
| 137324 | break; |
| 137325 | case 174: /* likeop ::= LIKE_KW|MATCH */ |
| 137326 | {yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/} |
| 137327 | break; |
| 137328 | case 175: /* likeop ::= NOT LIKE_KW|MATCH */ |
| 137329 | {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} |
| 137330 | break; |
| 137331 | case 176: /* expr ::= expr likeop expr */ |
| 137332 | { |
| 137333 | ExprList *pList; |
| 137334 | int bNot = yymsp[-1].minor.yy0.n & 0x80000000; |
| 137335 | yymsp[-1].minor.yy0.n &= 0x7fffffff; |
| 137336 | pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); |
| @@ -137339,11 +137792,11 @@ | |
| 137339 | exprNot(pParse, bNot, &yymsp[-2].minor.yy190); |
| 137340 | yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137341 | if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 137342 | } |
| 137343 | break; |
| 137344 | case 177: /* expr ::= expr likeop expr ESCAPE expr */ |
| 137345 | { |
| 137346 | ExprList *pList; |
| 137347 | int bNot = yymsp[-3].minor.yy0.n & 0x80000000; |
| 137348 | yymsp[-3].minor.yy0.n &= 0x7fffffff; |
| 137349 | pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| @@ -137353,43 +137806,43 @@ | |
| 137353 | exprNot(pParse, bNot, &yymsp[-4].minor.yy190); |
| 137354 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137355 | if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 137356 | } |
| 137357 | break; |
| 137358 | case 178: /* expr ::= expr ISNULL|NOTNULL */ |
| 137359 | {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} |
| 137360 | break; |
| 137361 | case 179: /* expr ::= expr NOT NULL */ |
| 137362 | {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} |
| 137363 | break; |
| 137364 | case 180: /* expr ::= expr IS expr */ |
| 137365 | { |
| 137366 | spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); |
| 137367 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); |
| 137368 | } |
| 137369 | break; |
| 137370 | case 181: /* expr ::= expr IS NOT expr */ |
| 137371 | { |
| 137372 | spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); |
| 137373 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); |
| 137374 | } |
| 137375 | break; |
| 137376 | case 182: /* expr ::= NOT expr */ |
| 137377 | case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183); |
| 137378 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137379 | break; |
| 137380 | case 184: /* expr ::= MINUS expr */ |
| 137381 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137382 | break; |
| 137383 | case 185: /* expr ::= PLUS expr */ |
| 137384 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137385 | break; |
| 137386 | case 186: /* between_op ::= BETWEEN */ |
| 137387 | case 189: /* in_op ::= IN */ yytestcase(yyruleno==189); |
| 137388 | {yymsp[0].minor.yy194 = 0;} |
| 137389 | break; |
| 137390 | case 188: /* expr ::= expr between_op expr AND expr */ |
| 137391 | { |
| 137392 | ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 137393 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 137394 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); |
| 137395 | if( yymsp[-4].minor.yy190.pExpr ){ |
| @@ -137399,11 +137852,11 @@ | |
| 137399 | } |
| 137400 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137401 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137402 | } |
| 137403 | break; |
| 137404 | case 191: /* expr ::= expr in_op LP exprlist RP */ |
| 137405 | { |
| 137406 | if( yymsp[-1].minor.yy148==0 ){ |
| 137407 | /* Expressions of the form |
| 137408 | ** |
| 137409 | ** expr1 IN () |
| @@ -137452,26 +137905,26 @@ | |
| 137452 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137453 | } |
| 137454 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 137455 | } |
| 137456 | break; |
| 137457 | case 192: /* expr ::= LP select RP */ |
| 137458 | { |
| 137459 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 137460 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); |
| 137461 | sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 137462 | } |
| 137463 | break; |
| 137464 | case 193: /* expr ::= expr in_op LP select RP */ |
| 137465 | { |
| 137466 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); |
| 137467 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 137468 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137469 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 137470 | } |
| 137471 | break; |
| 137472 | case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */ |
| 137473 | { |
| 137474 | SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); |
| 137475 | Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); |
| 137476 | if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); |
| 137477 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); |
| @@ -137478,19 +137931,19 @@ | |
| 137478 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); |
| 137479 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137480 | yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; |
| 137481 | } |
| 137482 | break; |
| 137483 | case 195: /* expr ::= EXISTS LP select RP */ |
| 137484 | { |
| 137485 | Expr *p; |
| 137486 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 137487 | p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); |
| 137488 | sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); |
| 137489 | } |
| 137490 | break; |
| 137491 | case 196: /* expr ::= CASE case_operand case_exprlist case_else END */ |
| 137492 | { |
| 137493 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ |
| 137494 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); |
| 137495 | if( yymsp[-4].minor.yy190.pExpr ){ |
| 137496 | yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; |
| @@ -137499,313 +137952,314 @@ | |
| 137499 | sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); |
| 137500 | sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); |
| 137501 | } |
| 137502 | } |
| 137503 | break; |
| 137504 | case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ |
| 137505 | { |
| 137506 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); |
| 137507 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 137508 | } |
| 137509 | break; |
| 137510 | case 198: /* case_exprlist ::= WHEN expr THEN expr */ |
| 137511 | { |
| 137512 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 137513 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 137514 | } |
| 137515 | break; |
| 137516 | case 201: /* case_operand ::= expr */ |
| 137517 | {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} |
| 137518 | break; |
| 137519 | case 204: /* nexprlist ::= nexprlist COMMA expr */ |
| 137520 | {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} |
| 137521 | break; |
| 137522 | case 205: /* nexprlist ::= expr */ |
| 137523 | {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} |
| 137524 | break; |
| 137525 | case 207: /* paren_exprlist ::= LP exprlist RP */ |
| 137526 | case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212); |
| 137527 | {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} |
| 137528 | break; |
| 137529 | case 208: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ |
| 137530 | { |
| 137531 | sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, |
| 137532 | sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, |
| 137533 | &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); |
| 137534 | } |
| 137535 | break; |
| 137536 | case 209: /* uniqueflag ::= UNIQUE */ |
| 137537 | case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); |
| 137538 | {yymsp[0].minor.yy194 = OE_Abort;} |
| 137539 | break; |
| 137540 | case 210: /* uniqueflag ::= */ |
| 137541 | {yymsp[1].minor.yy194 = OE_None;} |
| 137542 | break; |
| 137543 | case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */ |
| 137544 | { |
| 137545 | yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); |
| 137546 | } |
| 137547 | break; |
| 137548 | case 214: /* eidlist ::= nm collate sortorder */ |
| 137549 | { |
| 137550 | yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ |
| 137551 | } |
| 137552 | break; |
| 137553 | case 217: /* cmd ::= DROP INDEX ifexists fullname */ |
| 137554 | {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} |
| 137555 | break; |
| 137556 | case 218: /* cmd ::= VACUUM */ |
| 137557 | {sqlite3Vacuum(pParse,0);} |
| 137558 | break; |
| 137559 | case 219: /* cmd ::= VACUUM nm */ |
| 137560 | {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} |
| 137561 | break; |
| 137562 | case 220: /* cmd ::= PRAGMA nm dbnm */ |
| 137563 | {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} |
| 137564 | break; |
| 137565 | case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ |
| 137566 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} |
| 137567 | break; |
| 137568 | case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ |
| 137569 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} |
| 137570 | break; |
| 137571 | case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ |
| 137572 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} |
| 137573 | break; |
| 137574 | case 224: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ |
| 137575 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} |
| 137576 | break; |
| 137577 | case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ |
| 137578 | { |
| 137579 | Token all; |
| 137580 | all.z = yymsp[-3].minor.yy0.z; |
| 137581 | all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; |
| 137582 | sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); |
| 137583 | } |
| 137584 | break; |
| 137585 | case 228: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ |
| 137586 | { |
| 137587 | sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); |
| 137588 | yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ |
| 137589 | } |
| 137590 | break; |
| 137591 | case 229: /* trigger_time ::= BEFORE */ |
| 137592 | { yymsp[0].minor.yy194 = TK_BEFORE; } |
| 137593 | break; |
| 137594 | case 230: /* trigger_time ::= AFTER */ |
| 137595 | { yymsp[0].minor.yy194 = TK_AFTER; } |
| 137596 | break; |
| 137597 | case 231: /* trigger_time ::= INSTEAD OF */ |
| 137598 | { yymsp[-1].minor.yy194 = TK_INSTEAD;} |
| 137599 | break; |
| 137600 | case 232: /* trigger_time ::= */ |
| 137601 | { yymsp[1].minor.yy194 = TK_BEFORE; } |
| 137602 | break; |
| 137603 | case 233: /* trigger_event ::= DELETE|INSERT */ |
| 137604 | case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); |
| 137605 | {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} |
| 137606 | break; |
| 137607 | case 235: /* trigger_event ::= UPDATE OF idlist */ |
| 137608 | {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} |
| 137609 | break; |
| 137610 | case 236: /* when_clause ::= */ |
| 137611 | case 255: /* key_opt ::= */ yytestcase(yyruleno==255); |
| 137612 | { yymsp[1].minor.yy72 = 0; } |
| 137613 | break; |
| 137614 | case 237: /* when_clause ::= WHEN expr */ |
| 137615 | case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); |
| 137616 | { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } |
| 137617 | break; |
| 137618 | case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ |
| 137619 | { |
| 137620 | assert( yymsp[-2].minor.yy145!=0 ); |
| 137621 | yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; |
| 137622 | yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 137623 | } |
| 137624 | break; |
| 137625 | case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ |
| 137626 | { |
| 137627 | assert( yymsp[-1].minor.yy145!=0 ); |
| 137628 | yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 137629 | } |
| 137630 | break; |
| 137631 | case 240: /* trnm ::= nm DOT nm */ |
| 137632 | { |
| 137633 | yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; |
| 137634 | sqlite3ErrorMsg(pParse, |
| 137635 | "qualified table names are not allowed on INSERT, UPDATE, and DELETE " |
| 137636 | "statements within triggers"); |
| 137637 | } |
| 137638 | break; |
| 137639 | case 241: /* tridxby ::= INDEXED BY nm */ |
| 137640 | { |
| 137641 | sqlite3ErrorMsg(pParse, |
| 137642 | "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " |
| 137643 | "within triggers"); |
| 137644 | } |
| 137645 | break; |
| 137646 | case 242: /* tridxby ::= NOT INDEXED */ |
| 137647 | { |
| 137648 | sqlite3ErrorMsg(pParse, |
| 137649 | "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " |
| 137650 | "within triggers"); |
| 137651 | } |
| 137652 | break; |
| 137653 | case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ |
| 137654 | {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} |
| 137655 | break; |
| 137656 | case 244: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ |
| 137657 | {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} |
| 137658 | break; |
| 137659 | case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ |
| 137660 | {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} |
| 137661 | break; |
| 137662 | case 246: /* trigger_cmd ::= select */ |
| 137663 | {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} |
| 137664 | break; |
| 137665 | case 247: /* expr ::= RAISE LP IGNORE RP */ |
| 137666 | { |
| 137667 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 137668 | yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); |
| 137669 | if( yymsp[-3].minor.yy190.pExpr ){ |
| 137670 | yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; |
| 137671 | } |
| 137672 | } |
| 137673 | break; |
| 137674 | case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ |
| 137675 | { |
| 137676 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 137677 | yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); |
| 137678 | if( yymsp[-5].minor.yy190.pExpr ) { |
| 137679 | yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; |
| 137680 | } |
| 137681 | } |
| 137682 | break; |
| 137683 | case 249: /* raisetype ::= ROLLBACK */ |
| 137684 | {yymsp[0].minor.yy194 = OE_Rollback;} |
| 137685 | break; |
| 137686 | case 251: /* raisetype ::= FAIL */ |
| 137687 | {yymsp[0].minor.yy194 = OE_Fail;} |
| 137688 | break; |
| 137689 | case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ |
| 137690 | { |
| 137691 | sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); |
| 137692 | } |
| 137693 | break; |
| 137694 | case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ |
| 137695 | { |
| 137696 | sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); |
| 137697 | } |
| 137698 | break; |
| 137699 | case 254: /* cmd ::= DETACH database_kw_opt expr */ |
| 137700 | { |
| 137701 | sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); |
| 137702 | } |
| 137703 | break; |
| 137704 | case 257: /* cmd ::= REINDEX */ |
| 137705 | {sqlite3Reindex(pParse, 0, 0);} |
| 137706 | break; |
| 137707 | case 258: /* cmd ::= REINDEX nm dbnm */ |
| 137708 | {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 137709 | break; |
| 137710 | case 259: /* cmd ::= ANALYZE */ |
| 137711 | {sqlite3Analyze(pParse, 0, 0);} |
| 137712 | break; |
| 137713 | case 260: /* cmd ::= ANALYZE nm dbnm */ |
| 137714 | {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 137715 | break; |
| 137716 | case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ |
| 137717 | { |
| 137718 | sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); |
| 137719 | } |
| 137720 | break; |
| 137721 | case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ |
| 137722 | { |
| 137723 | yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; |
| 137724 | sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); |
| 137725 | } |
| 137726 | break; |
| 137727 | case 263: /* add_column_fullname ::= fullname */ |
| 137728 | { |
| 137729 | disableLookaside(pParse); |
| 137730 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); |
| 137731 | } |
| 137732 | break; |
| 137733 | case 264: /* cmd ::= create_vtab */ |
| 137734 | {sqlite3VtabFinishParse(pParse,0);} |
| 137735 | break; |
| 137736 | case 265: /* cmd ::= create_vtab LP vtabarglist RP */ |
| 137737 | {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} |
| 137738 | break; |
| 137739 | case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ |
| 137740 | { |
| 137741 | sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); |
| 137742 | } |
| 137743 | break; |
| 137744 | case 267: /* vtabarg ::= */ |
| 137745 | {sqlite3VtabArgInit(pParse);} |
| 137746 | break; |
| 137747 | case 268: /* vtabargtoken ::= ANY */ |
| 137748 | case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); |
| 137749 | case 270: /* lp ::= LP */ yytestcase(yyruleno==270); |
| 137750 | {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} |
| 137751 | break; |
| 137752 | case 271: /* with ::= */ |
| 137753 | {yymsp[1].minor.yy285 = 0;} |
| 137754 | break; |
| 137755 | case 272: /* with ::= WITH wqlist */ |
| 137756 | { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } |
| 137757 | break; |
| 137758 | case 273: /* with ::= WITH RECURSIVE wqlist */ |
| 137759 | { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } |
| 137760 | break; |
| 137761 | case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */ |
| 137762 | { |
| 137763 | yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ |
| 137764 | } |
| 137765 | break; |
| 137766 | case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ |
| 137767 | { |
| 137768 | yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); |
| 137769 | } |
| 137770 | break; |
| 137771 | default: |
| 137772 | /* (276) input ::= cmdlist */ yytestcase(yyruleno==276); |
| 137773 | /* (277) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==277); |
| 137774 | /* (278) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=278); |
| 137775 | /* (279) ecmd ::= SEMI */ yytestcase(yyruleno==279); |
| 137776 | /* (280) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==280); |
| 137777 | /* (281) explain ::= */ yytestcase(yyruleno==281); |
| 137778 | /* (282) trans_opt ::= */ yytestcase(yyruleno==282); |
| 137779 | /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283); |
| 137780 | /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284); |
| 137781 | /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285); |
| 137782 | /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286); |
| 137783 | /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287); |
| 137784 | /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288); |
| 137785 | /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289); |
| 137786 | /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290); |
| 137787 | /* (291) nm ::= STRING */ yytestcase(yyruleno==291); |
| 137788 | /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292); |
| 137789 | /* (293) typetoken ::= typename */ yytestcase(yyruleno==293); |
| 137790 | /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294); |
| 137791 | /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); |
| 137792 | /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296); |
| 137793 | /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297); |
| 137794 | /* (298) carglist ::= */ yytestcase(yyruleno==298); |
| 137795 | /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299); |
| 137796 | /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300); |
| 137797 | /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301); |
| 137798 | /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302); |
| 137799 | /* (303) tconscomma ::= */ yytestcase(yyruleno==303); |
| 137800 | /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304); |
| 137801 | /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305); |
| 137802 | /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306); |
| 137803 | /* (307) oneselect ::= values */ yytestcase(yyruleno==307); |
| 137804 | /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308); |
| 137805 | /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309); |
| 137806 | /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310); |
| 137807 | /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); |
| 137808 | /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); |
| 137809 | /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); |
| 137810 | /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); |
| 137811 | /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); |
| @@ -138854,12 +139308,12 @@ | |
| 138854 | ** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that |
| 138855 | ** error message. |
| 138856 | */ |
| 138857 | SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ |
| 138858 | int nErr = 0; /* Number of errors encountered */ |
| 138859 | int i; /* Loop counter */ |
| 138860 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 138861 | int tokenType; /* type of the next token */ |
| 138862 | int lastTokenParsed = -1; /* type of the previous token */ |
| 138863 | sqlite3 *db = pParse->db; /* The database connection */ |
| 138864 | int mxSqlLen; /* Max length of an SQL string */ |
| 138865 | #ifdef sqlite3Parser_ENGINEALWAYSONSTACK |
| @@ -138871,11 +139325,10 @@ | |
| 138871 | if( db->nVdbeActive==0 ){ |
| 138872 | db->u1.isInterrupted = 0; |
| 138873 | } |
| 138874 | pParse->rc = SQLITE_OK; |
| 138875 | pParse->zTail = zSql; |
| 138876 | i = 0; |
| 138877 | assert( pzErrMsg!=0 ); |
| 138878 | /* sqlite3ParserTrace(stdout, "parser: "); */ |
| 138879 | #ifdef sqlite3Parser_ENGINEALWAYSONSTACK |
| 138880 | pEngine = zSpace; |
| 138881 | sqlite3ParserInit(pEngine); |
| @@ -138889,16 +139342,14 @@ | |
| 138889 | assert( pParse->pNewTable==0 ); |
| 138890 | assert( pParse->pNewTrigger==0 ); |
| 138891 | assert( pParse->nVar==0 ); |
| 138892 | assert( pParse->pVList==0 ); |
| 138893 | while( 1 ){ |
| 138894 | assert( i>=0 ); |
| 138895 | if( zSql[i]!=0 ){ |
| 138896 | pParse->sLastToken.z = &zSql[i]; |
| 138897 | pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType); |
| 138898 | i += pParse->sLastToken.n; |
| 138899 | if( i>mxSqlLen ){ |
| 138900 | pParse->rc = SQLITE_TOOBIG; |
| 138901 | break; |
| 138902 | } |
| 138903 | }else{ |
| 138904 | /* Upon reaching the end of input, call the parser two more times |
| @@ -138908,30 +139359,34 @@ | |
| 138908 | }else if( lastTokenParsed==0 ){ |
| 138909 | break; |
| 138910 | }else{ |
| 138911 | tokenType = TK_SEMI; |
| 138912 | } |
| 138913 | } |
| 138914 | if( tokenType>=TK_SPACE ){ |
| 138915 | assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); |
| 138916 | if( db->u1.isInterrupted ){ |
| 138917 | pParse->rc = SQLITE_INTERRUPT; |
| 138918 | break; |
| 138919 | } |
| 138920 | if( tokenType==TK_ILLEGAL ){ |
| 138921 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", |
| 138922 | &pParse->sLastToken); |
| 138923 | break; |
| 138924 | } |
| 138925 | }else{ |
| 138926 | sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); |
| 138927 | lastTokenParsed = tokenType; |
| 138928 | if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; |
| 138929 | } |
| 138930 | } |
| 138931 | assert( nErr==0 ); |
| 138932 | pParse->zTail = &zSql[i]; |
| 138933 | #ifdef YYTRACKMAXSTACKDEPTH |
| 138934 | sqlite3_mutex_enter(sqlite3MallocMutex()); |
| 138935 | sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, |
| 138936 | sqlite3ParserStackPeak(pEngine) |
| 138937 | ); |
| @@ -140301,10 +140756,25 @@ | |
| 140301 | return 0; |
| 140302 | } |
| 140303 | #endif |
| 140304 | return db->lastRowid; |
| 140305 | } |
| 140306 | |
| 140307 | /* |
| 140308 | ** Return the number of changes in the most recent call to sqlite3_exec(). |
| 140309 | */ |
| 140310 | SQLITE_API int sqlite3_changes(sqlite3 *db){ |
| @@ -148111,12 +148581,14 @@ | |
| 148111 | ** segments. |
| 148112 | */ |
| 148113 | const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ |
| 148114 | |
| 148115 | Fts3Table *p = (Fts3Table*)pVtab; |
| 148116 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 148117 | |
| 148118 | if( rc==SQLITE_OK |
| 148119 | && p->nLeafAdd>(nMinMerge/16) |
| 148120 | && p->nAutoincrmerge && p->nAutoincrmerge!=0xff |
| 148121 | ){ |
| 148122 | int mxLevel = 0; /* Maximum relative level value in db */ |
| @@ -148127,10 +148599,11 @@ | |
| 148127 | A = p->nLeafAdd * mxLevel; |
| 148128 | A += (A/2); |
| 148129 | if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); |
| 148130 | } |
| 148131 | sqlite3Fts3SegmentsClose(p); |
| 148132 | return rc; |
| 148133 | } |
| 148134 | |
| 148135 | /* |
| 148136 | ** If it is currently unknown whether or not the FTS table has an %_stat |
| @@ -168462,10 +168935,11 @@ | |
| 168462 | int nStep; /* Rows processed for current object */ |
| 168463 | int nProgress; /* Rows processed for all objects */ |
| 168464 | RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ |
| 168465 | const char *zVfsName; /* Name of automatically created rbu vfs */ |
| 168466 | rbu_file *pTargetFd; /* File handle open on target db */ |
| 168467 | i64 iOalSz; |
| 168468 | i64 nPhaseOneStep; |
| 168469 | |
| 168470 | /* The following state variables are used as part of the incremental |
| 168471 | ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding |
| @@ -170726,10 +171200,27 @@ | |
| 170726 | |
| 170727 | if( p->rc==SQLITE_OK ){ |
| 170728 | if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){ |
| 170729 | p->rc = SQLITE_DONE; |
| 170730 | p->eStage = RBU_STAGE_DONE; |
| 170731 | } |
| 170732 | } |
| 170733 | } |
| 170734 | |
| 170735 | /* |
| @@ -171381,13 +171872,30 @@ | |
| 171381 | if( p->rc==SQLITE_OK ){ |
| 171382 | p->eStage = RBU_STAGE_DONE; |
| 171383 | p->rc = SQLITE_DONE; |
| 171384 | } |
| 171385 | }else{ |
| 171386 | RbuFrame *pFrame = &p->aFrame[p->nStep]; |
| 171387 | rbuCheckpointFrame(p, pFrame); |
| 171388 | p->nStep++; |
| 171389 | } |
| 171390 | p->nProgress++; |
| 171391 | } |
| 171392 | break; |
| 171393 | } |
| @@ -171823,10 +172331,16 @@ | |
| 171823 | |
| 171824 | /* Commit the transaction to the *-oal file. */ |
| 171825 | if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ |
| 171826 | p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); |
| 171827 | } |
| 171828 | |
| 171829 | rbuSaveState(p, p->eStage); |
| 171830 | |
| 171831 | if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ |
| 171832 | p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); |
| @@ -171947,10 +172461,16 @@ | |
| 171947 | assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE ); |
| 171948 | if( p->eStage==RBU_STAGE_OAL ){ |
| 171949 | assert( rc!=SQLITE_DONE ); |
| 171950 | if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0); |
| 171951 | } |
| 171952 | |
| 171953 | p->rc = rc; |
| 171954 | rbuSaveState(p, p->eStage); |
| 171955 | rc = p->rc; |
| 171956 | |
| @@ -181079,11 +181599,13 @@ | |
| 181079 | typedef unsigned short u16; |
| 181080 | typedef short i16; |
| 181081 | typedef sqlite3_int64 i64; |
| 181082 | typedef sqlite3_uint64 u64; |
| 181083 | |
| 181084 | #define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) |
| 181085 | |
| 181086 | #define testcase(x) |
| 181087 | #define ALWAYS(x) 1 |
| 181088 | #define NEVER(x) 0 |
| 181089 | |
| @@ -186302,11 +186824,14 @@ | |
| 186302 | if( p1->bEof==0 ){ |
| 186303 | if( (p1->iRowid==iLast) |
| 186304 | || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) |
| 186305 | ){ |
| 186306 | int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); |
| 186307 | if( rc!=SQLITE_OK ) return rc; |
| 186308 | } |
| 186309 | } |
| 186310 | } |
| 186311 | |
| 186312 | fts5ExprNodeTest_OR(pExpr, pNode); |
| @@ -186333,11 +186858,14 @@ | |
| 186333 | Fts5ExprNode *pChild = pAnd->apChild[iChild]; |
| 186334 | int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); |
| 186335 | if( cmp>0 ){ |
| 186336 | /* Advance pChild until it points to iLast or laster */ |
| 186337 | rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); |
| 186338 | if( rc!=SQLITE_OK ) return rc; |
| 186339 | } |
| 186340 | |
| 186341 | /* If the child node is now at EOF, so is the parent AND node. Otherwise, |
| 186342 | ** the child node is guaranteed to have advanced at least as far as |
| 186343 | ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the |
| @@ -186372,10 +186900,12 @@ | |
| 186372 | i64 iFrom |
| 186373 | ){ |
| 186374 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 186375 | if( rc==SQLITE_OK ){ |
| 186376 | rc = fts5ExprNodeTest_AND(pExpr, pNode); |
| 186377 | } |
| 186378 | return rc; |
| 186379 | } |
| 186380 | |
| 186381 | static int fts5ExprNodeTest_NOT( |
| @@ -186414,10 +186944,13 @@ | |
| 186414 | ){ |
| 186415 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 186416 | if( rc==SQLITE_OK ){ |
| 186417 | rc = fts5ExprNodeTest_NOT(pExpr, pNode); |
| 186418 | } |
| 186419 | return rc; |
| 186420 | } |
| 186421 | |
| 186422 | /* |
| 186423 | ** If pNode currently points to a match, this function returns SQLITE_OK |
| @@ -197534,11 +198067,11 @@ | |
| 197534 | int nArg, /* Number of args */ |
| 197535 | sqlite3_value **apUnused /* Function arguments */ |
| 197536 | ){ |
| 197537 | assert( nArg==0 ); |
| 197538 | UNUSED_PARAM2(nArg, apUnused); |
| 197539 | sqlite3_result_text(pCtx, "fts5: 2017-02-13 16:02:40 ada05cfa86ad7f5645450ac7a2a21c9aa6e57d2c", -1, SQLITE_TRANSIENT); |
| 197540 | } |
| 197541 | |
| 197542 | static int fts5Init(sqlite3 *db){ |
| 197543 | static const sqlite3_module fts5Mod = { |
| 197544 | /* iVersion */ 2, |
| @@ -198197,15 +198730,10 @@ | |
| 198197 | sqlite3_step(pDel); |
| 198198 | rc = sqlite3_reset(pDel); |
| 198199 | } |
| 198200 | } |
| 198201 | |
| 198202 | /* Write the averages record */ |
| 198203 | if( rc==SQLITE_OK ){ |
| 198204 | rc = fts5StorageSaveTotals(p); |
| 198205 | } |
| 198206 | |
| 198207 | return rc; |
| 198208 | } |
| 198209 | |
| 198210 | /* |
| 198211 | ** Delete all entries in the FTS5 index. |
| @@ -198405,15 +198933,10 @@ | |
| 198405 | if( rc==SQLITE_OK ){ |
| 198406 | rc = fts5StorageInsertDocsize(p, iRowid, &buf); |
| 198407 | } |
| 198408 | sqlite3_free(buf.p); |
| 198409 | |
| 198410 | /* Write the averages record */ |
| 198411 | if( rc==SQLITE_OK ){ |
| 198412 | rc = fts5StorageSaveTotals(p); |
| 198413 | } |
| 198414 | |
| 198415 | return rc; |
| 198416 | } |
| 198417 | |
| 198418 | static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){ |
| 198419 | Fts5Config *pConfig = p->pConfig; |
| @@ -198744,16 +199267,21 @@ | |
| 198744 | |
| 198745 | /* |
| 198746 | ** Flush any data currently held in-memory to disk. |
| 198747 | */ |
| 198748 | static int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){ |
| 198749 | if( bCommit && p->bTotalsValid ){ |
| 198750 | int rc = fts5StorageSaveTotals(p); |
| 198751 | p->bTotalsValid = 0; |
| 198752 | if( rc!=SQLITE_OK ) return rc; |
| 198753 | } |
| 198754 | return sqlite3Fts5IndexSync(p->pIndex, bCommit); |
| 198755 | } |
| 198756 | |
| 198757 | static int sqlite3Fts5StorageRollback(Fts5Storage *p){ |
| 198758 | p->bTotalsValid = 0; |
| 198759 | return sqlite3Fts5IndexRollback(p->pIndex); |
| 198760 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.18.0. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -396,13 +396,13 @@ | |
| 396 | ** |
| 397 | ** See also: [sqlite3_libversion()], |
| 398 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 399 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 400 | */ |
| 401 | #define SQLITE_VERSION "3.18.0" |
| 402 | #define SQLITE_VERSION_NUMBER 3018000 |
| 403 | #define SQLITE_SOURCE_ID "2017-03-10 17:03:11 f8560c60d10c0365b33342ab05b5a953987b0471" |
| 404 | |
| 405 | /* |
| 406 | ** CAPI3REF: Run-Time Library Version Numbers |
| 407 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 408 | ** |
| @@ -2315,24 +2315,34 @@ | |
| 2315 | ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those |
| 2316 | ** names are not also used by explicitly declared columns. ^If |
| 2317 | ** the table has a column of type [INTEGER PRIMARY KEY] then that column |
| 2318 | ** is another alias for the rowid. |
| 2319 | ** |
| 2320 | ** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of |
| 2321 | ** the most recent successful [INSERT] into a rowid table or [virtual table] |
| 2322 | ** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not |
| 2323 | ** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred |
| 2324 | ** on the database connection D, then sqlite3_last_insert_rowid(D) returns |
| 2325 | ** zero. |
| 2326 | ** |
| 2327 | ** As well as being set automatically as rows are inserted into database |
| 2328 | ** tables, the value returned by this function may be set explicitly by |
| 2329 | ** [sqlite3_set_last_insert_rowid()] |
| 2330 | ** |
| 2331 | ** Some virtual table implementations may INSERT rows into rowid tables as |
| 2332 | ** part of committing a transaction (e.g. to flush data accumulated in memory |
| 2333 | ** to disk). In this case subsequent calls to this function return the rowid |
| 2334 | ** associated with these internal INSERT operations, which leads to |
| 2335 | ** unintuitive results. Virtual table implementations that do write to rowid |
| 2336 | ** tables in this way can avoid this problem by restoring the original |
| 2337 | ** rowid value using [sqlite3_set_last_insert_rowid()] before returning |
| 2338 | ** control to the user. |
| 2339 | ** |
| 2340 | ** ^(If an [INSERT] occurs within a trigger then this routine will |
| 2341 | ** return the [rowid] of the inserted row as long as the trigger is |
| 2342 | ** running. Once the trigger program ends, the value returned |
| 2343 | ** by this routine reverts to what it was before the trigger was fired.)^ |
| 2344 | ** |
| 2345 | ** ^An [INSERT] that fails due to a constraint violation is not a |
| 2346 | ** successful [INSERT] and does not change the value returned by this |
| 2347 | ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, |
| 2348 | ** and INSERT OR ABORT make no changes to the return value of this |
| @@ -2355,10 +2365,20 @@ | |
| 2365 | ** unpredictable and might not equal either the old or the new |
| 2366 | ** last insert [rowid]. |
| 2367 | */ |
| 2368 | SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); |
| 2369 | |
| 2370 | /* |
| 2371 | ** CAPI3REF: Set the Last Insert Rowid value. |
| 2372 | ** METHOD: sqlite3 |
| 2373 | ** |
| 2374 | ** The sqlite3_set_last_insert_rowid(D, R) method allows the application to |
| 2375 | ** set the value returned by calling sqlite3_last_insert_rowid(D) to R |
| 2376 | ** without inserting a row into the database. |
| 2377 | */ |
| 2378 | SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); |
| 2379 | |
| 2380 | /* |
| 2381 | ** CAPI3REF: Count The Number Of Rows Modified |
| 2382 | ** METHOD: sqlite3 |
| 2383 | ** |
| 2384 | ** ^This function returns the number of rows modified, inserted or |
| @@ -12457,10 +12477,11 @@ | |
| 12477 | SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); |
| 12478 | SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); |
| 12479 | |
| 12480 | SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); |
| 12481 | SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); |
| 12482 | SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*); |
| 12483 | |
| 12484 | #ifndef SQLITE_OMIT_INCRBLOB |
| 12485 | SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*); |
| 12486 | SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); |
| 12487 | SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); |
| @@ -12757,117 +12778,119 @@ | |
| 12778 | #define OP_Divide 50 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ |
| 12779 | #define OP_Remainder 51 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ |
| 12780 | #define OP_Concat 52 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ |
| 12781 | #define OP_Last 53 |
| 12782 | #define OP_BitNot 54 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ |
| 12783 | #define OP_IfSmaller 55 |
| 12784 | #define OP_SorterSort 56 |
| 12785 | #define OP_Sort 57 |
| 12786 | #define OP_Rewind 58 |
| 12787 | #define OP_IdxLE 59 /* synopsis: key=r[P3@P4] */ |
| 12788 | #define OP_IdxGT 60 /* synopsis: key=r[P3@P4] */ |
| 12789 | #define OP_IdxLT 61 /* synopsis: key=r[P3@P4] */ |
| 12790 | #define OP_IdxGE 62 /* synopsis: key=r[P3@P4] */ |
| 12791 | #define OP_RowSetRead 63 /* synopsis: r[P3]=rowset(P1) */ |
| 12792 | #define OP_RowSetTest 64 /* synopsis: if r[P3] in rowset(P1) goto P2 */ |
| 12793 | #define OP_Program 65 |
| 12794 | #define OP_FkIfZero 66 /* synopsis: if fkctr[P1]==0 goto P2 */ |
| 12795 | #define OP_IfPos 67 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ |
| 12796 | #define OP_IfNotZero 68 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ |
| 12797 | #define OP_DecrJumpZero 69 /* synopsis: if (--r[P1])==0 goto P2 */ |
| 12798 | #define OP_IncrVacuum 70 |
| 12799 | #define OP_VNext 71 |
| 12800 | #define OP_Init 72 /* synopsis: Start at P2 */ |
| 12801 | #define OP_Return 73 |
| 12802 | #define OP_EndCoroutine 74 |
| 12803 | #define OP_HaltIfNull 75 /* synopsis: if r[P3]=null halt */ |
| 12804 | #define OP_Halt 76 |
| 12805 | #define OP_Integer 77 /* synopsis: r[P2]=P1 */ |
| 12806 | #define OP_Int64 78 /* synopsis: r[P2]=P4 */ |
| 12807 | #define OP_String 79 /* synopsis: r[P2]='P4' (len=P1) */ |
| 12808 | #define OP_Null 80 /* synopsis: r[P2..P3]=NULL */ |
| 12809 | #define OP_SoftNull 81 /* synopsis: r[P1]=NULL */ |
| 12810 | #define OP_Blob 82 /* synopsis: r[P2]=P4 (len=P1) */ |
| 12811 | #define OP_Variable 83 /* synopsis: r[P2]=parameter(P1,P4) */ |
| 12812 | #define OP_Move 84 /* synopsis: r[P2@P3]=r[P1@P3] */ |
| 12813 | #define OP_Copy 85 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ |
| 12814 | #define OP_SCopy 86 /* synopsis: r[P2]=r[P1] */ |
| 12815 | #define OP_IntCopy 87 /* synopsis: r[P2]=r[P1] */ |
| 12816 | #define OP_ResultRow 88 /* synopsis: output=r[P1@P2] */ |
| 12817 | #define OP_CollSeq 89 |
| 12818 | #define OP_Function0 90 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 12819 | #define OP_Function 91 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 12820 | #define OP_AddImm 92 /* synopsis: r[P1]=r[P1]+P2 */ |
| 12821 | #define OP_RealAffinity 93 |
| 12822 | #define OP_Cast 94 /* synopsis: affinity(r[P1]) */ |
| 12823 | #define OP_Permutation 95 |
| 12824 | #define OP_Compare 96 /* synopsis: r[P1@P3] <-> r[P2@P3] */ |
| 12825 | #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ |
| 12826 | #define OP_Column 98 /* synopsis: r[P3]=PX */ |
| 12827 | #define OP_Affinity 99 /* synopsis: affinity(r[P1@P2]) */ |
| 12828 | #define OP_MakeRecord 100 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ |
| 12829 | #define OP_Count 101 /* synopsis: r[P2]=count() */ |
| 12830 | #define OP_ReadCookie 102 |
| 12831 | #define OP_SetCookie 103 |
| 12832 | #define OP_ReopenIdx 104 /* synopsis: root=P2 iDb=P3 */ |
| 12833 | #define OP_OpenRead 105 /* synopsis: root=P2 iDb=P3 */ |
| 12834 | #define OP_OpenWrite 106 /* synopsis: root=P2 iDb=P3 */ |
| 12835 | #define OP_OpenAutoindex 107 /* synopsis: nColumn=P2 */ |
| 12836 | #define OP_OpenEphemeral 108 /* synopsis: nColumn=P2 */ |
| 12837 | #define OP_SorterOpen 109 |
| 12838 | #define OP_SequenceTest 110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ |
| 12839 | #define OP_OpenPseudo 111 /* synopsis: P3 columns in r[P2] */ |
| 12840 | #define OP_Close 112 |
| 12841 | #define OP_ColumnsUsed 113 |
| 12842 | #define OP_Sequence 114 /* synopsis: r[P2]=cursor[P1].ctr++ */ |
| 12843 | #define OP_NewRowid 115 /* synopsis: r[P2]=rowid */ |
| 12844 | #define OP_Insert 116 /* synopsis: intkey=r[P3] data=r[P2] */ |
| 12845 | #define OP_InsertInt 117 /* synopsis: intkey=P3 data=r[P2] */ |
| 12846 | #define OP_Delete 118 |
| 12847 | #define OP_ResetCount 119 |
| 12848 | #define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ |
| 12849 | #define OP_SorterData 121 /* synopsis: r[P2]=data */ |
| 12850 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12851 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12852 | #define OP_NullRow 124 |
| 12853 | #define OP_SorterInsert 125 /* synopsis: key=r[P2] */ |
| 12854 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12855 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12856 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12857 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12858 | #define OP_Destroy 130 |
| 12859 | #define OP_Clear 131 |
| 12860 | #define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 12861 | #define OP_ResetSorter 133 |
| 12862 | #define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */ |
| 12863 | #define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */ |
| 12864 | #define OP_SqlExec 136 |
| 12865 | #define OP_ParseSchema 137 |
| 12866 | #define OP_LoadAnalysis 138 |
| 12867 | #define OP_DropTable 139 |
| 12868 | #define OP_DropIndex 140 |
| 12869 | #define OP_DropTrigger 141 |
| 12870 | #define OP_IntegrityCk 142 |
| 12871 | #define OP_RowSetAdd 143 /* synopsis: rowset(P1)=r[P2] */ |
| 12872 | #define OP_Param 144 |
| 12873 | #define OP_FkCounter 145 /* synopsis: fkctr[P1]+=P2 */ |
| 12874 | #define OP_MemMax 146 /* synopsis: r[P1]=max(r[P1],r[P2]) */ |
| 12875 | #define OP_OffsetLimit 147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ |
| 12876 | #define OP_AggStep0 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 12877 | #define OP_AggStep 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 12878 | #define OP_AggFinal 150 /* synopsis: accum=r[P1] N=P2 */ |
| 12879 | #define OP_Expire 151 |
| 12880 | #define OP_TableLock 152 /* synopsis: iDb=P1 root=P2 write=P3 */ |
| 12881 | #define OP_VBegin 153 |
| 12882 | #define OP_VCreate 154 |
| 12883 | #define OP_VDestroy 155 |
| 12884 | #define OP_VOpen 156 |
| 12885 | #define OP_VColumn 157 /* synopsis: r[P3]=vcolumn(P2) */ |
| 12886 | #define OP_VRename 158 |
| 12887 | #define OP_Pagecount 159 |
| 12888 | #define OP_MaxPgcnt 160 |
| 12889 | #define OP_CursorHint 161 |
| 12890 | #define OP_Noop 162 |
| 12891 | #define OP_Explain 163 |
| 12892 | |
| 12893 | /* Properties such as "out2" or "jump" that are specified in |
| 12894 | ** comments following the "case" for each opcode in the vdbe.c |
| 12895 | ** are encoded into bitvectors as follows: |
| 12896 | */ |
| @@ -12883,32 +12906,32 @@ | |
| 12906 | /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x09,\ |
| 12907 | /* 24 */ 0x09, 0x09, 0x09, 0x26, 0x26, 0x09, 0x09, 0x09,\ |
| 12908 | /* 32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ |
| 12909 | /* 40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\ |
| 12910 | /* 48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\ |
| 12911 | /* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23,\ |
| 12912 | /* 64 */ 0x0b, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01,\ |
| 12913 | /* 72 */ 0x01, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\ |
| 12914 | /* 80 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\ |
| 12915 | /* 88 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,\ |
| 12916 | /* 96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ |
| 12917 | /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12918 | /* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ |
| 12919 | /* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\ |
| 12920 | /* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\ |
| 12921 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\ |
| 12922 | /* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\ |
| 12923 | /* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ |
| 12924 | /* 160 */ 0x10, 0x00, 0x00, 0x00,} |
| 12925 | |
| 12926 | /* The sqlite3P2Values() routine is able to run faster if it knows |
| 12927 | ** the value of the largest JUMP opcode. The smaller the maximum |
| 12928 | ** JUMP opcode the better, so the mkopcodeh.tcl script that |
| 12929 | ** generated this include file strives to group all JUMP opcodes |
| 12930 | ** together near the beginning of the list. |
| 12931 | */ |
| 12932 | #define SQLITE_MX_JUMP_OPCODE 72 /* Maximum JUMP opcode */ |
| 12933 | |
| 12934 | /************** End of opcodes.h *********************************************/ |
| 12935 | /************** Continuing where we left off in vdbe.h ***********************/ |
| 12936 | |
| 12937 | /* |
| @@ -14074,10 +14097,11 @@ | |
| 14097 | u8 suppressErr; /* Do not issue error messages if true */ |
| 14098 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
| 14099 | u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ |
| 14100 | u8 mTrace; /* zero or more SQLITE_TRACE flags */ |
| 14101 | u8 skipBtreeMutex; /* True if no shared-cache backends */ |
| 14102 | u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ |
| 14103 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 14104 | u32 magic; /* Magic number for detect library misuse */ |
| 14105 | int nChange; /* Value returned by sqlite3_changes() */ |
| 14106 | int nTotalChange; /* Value returned by sqlite3_total_changes() */ |
| 14107 | int aLimit[SQLITE_N_LIMIT]; /* Limits */ |
| @@ -14589,18 +14613,18 @@ | |
| 14613 | char *zColAff; /* String defining the affinity of each column */ |
| 14614 | ExprList *pCheck; /* All CHECK constraints */ |
| 14615 | /* ... also used as column name list in a VIEW */ |
| 14616 | int tnum; /* Root BTree page for this table */ |
| 14617 | u32 nTabRef; /* Number of pointers to this Table */ |
| 14618 | u32 tabFlags; /* Mask of TF_* values */ |
| 14619 | i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ |
| 14620 | i16 nCol; /* Number of columns in this table */ |
| 14621 | LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ |
| 14622 | LogEst szTabRow; /* Estimated size of each table row in bytes */ |
| 14623 | #ifdef SQLITE_ENABLE_COSTMULT |
| 14624 | LogEst costMult; /* Cost multiplier for using this table */ |
| 14625 | #endif |
| 14626 | u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ |
| 14627 | #ifndef SQLITE_OMIT_ALTERTABLE |
| 14628 | int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ |
| 14629 | #endif |
| 14630 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| @@ -14620,27 +14644,29 @@ | |
| 14644 | ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING |
| 14645 | ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, |
| 14646 | ** the TF_OOOHidden attribute would apply in this case. Such tables require |
| 14647 | ** special handling during INSERT processing. |
| 14648 | */ |
| 14649 | #define TF_Readonly 0x0001 /* Read-only system table */ |
| 14650 | #define TF_Ephemeral 0x0002 /* An ephemeral table */ |
| 14651 | #define TF_HasPrimaryKey 0x0004 /* Table has a primary key */ |
| 14652 | #define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */ |
| 14653 | #define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ |
| 14654 | #define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */ |
| 14655 | #define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */ |
| 14656 | #define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */ |
| 14657 | #define TF_StatsUsed 0x0100 /* Query planner decisions affected by |
| 14658 | ** Index.aiRowLogEst[] values */ |
| 14659 | #define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ |
| 14660 | |
| 14661 | /* |
| 14662 | ** Test to see whether or not a table is a virtual table. This is |
| 14663 | ** done as a macro so that it will be optimized out when virtual |
| 14664 | ** table support is omitted from the build. |
| 14665 | */ |
| 14666 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 14667 | # define IsVirtual(X) ((X)->nModuleArg) |
| 14668 | #else |
| 14669 | # define IsVirtual(X) 0 |
| 14670 | #endif |
| 14671 | |
| 14672 | /* |
| @@ -14871,10 +14897,11 @@ | |
| 14897 | unsigned bUnordered:1; /* Use this index for == or IN queries only */ |
| 14898 | unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ |
| 14899 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ |
| 14900 | unsigned isCovering:1; /* True if this is a covering index */ |
| 14901 | unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ |
| 14902 | unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ |
| 14903 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 14904 | int nSample; /* Number of elements in aSample[] */ |
| 14905 | int nSampleCol; /* Size of IndexSample.anEq[] and so on */ |
| 14906 | tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ |
| 14907 | IndexSample *aSample; /* Samples of the left-most key */ |
| @@ -15181,11 +15208,11 @@ | |
| 15208 | ** form is used for name resolution with nested FROM clauses. |
| 15209 | */ |
| 15210 | struct ExprList { |
| 15211 | int nExpr; /* Number of expressions on the list */ |
| 15212 | struct ExprList_item { /* For each expression in the list */ |
| 15213 | Expr *pExpr; /* The parse tree for this expression */ |
| 15214 | char *zName; /* Token associated with this expression */ |
| 15215 | char *zSpan; /* Original text of the expression */ |
| 15216 | u8 sortOrder; /* 1 for DESC or 0 for ASC */ |
| 15217 | unsigned done :1; /* A flag to indicate when processing is finished */ |
| 15218 | unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ |
| @@ -16504,10 +16531,11 @@ | |
| 16531 | SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); |
| 16532 | SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*); |
| 16533 | SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int); |
| 16534 | SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); |
| 16535 | SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int); |
| 16536 | SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); |
| 16537 | SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); |
| 16538 | SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int); |
| 16539 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); |
| 16540 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); |
| 16541 | SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); |
| @@ -17450,11 +17478,11 @@ | |
| 17478 | "COMPILER=gcc-" __VERSION__, |
| 17479 | #endif |
| 17480 | #if SQLITE_COVERAGE_TEST |
| 17481 | "COVERAGE_TEST", |
| 17482 | #endif |
| 17483 | #ifdef SQLITE_DEBUG |
| 17484 | "DEBUG", |
| 17485 | #endif |
| 17486 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17487 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17488 | #endif |
| @@ -19505,22 +19533,23 @@ | |
| 19533 | ** |
| 19534 | ** Move the date backwards to the beginning of the current day, |
| 19535 | ** or month or year. |
| 19536 | */ |
| 19537 | if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break; |
| 19538 | if( !p->validJD && !p->validYMD && !p->validHMS ) break; |
| 19539 | z += 9; |
| 19540 | computeYMD(p); |
| 19541 | p->validHMS = 1; |
| 19542 | p->h = p->m = 0; |
| 19543 | p->s = 0.0; |
| 19544 | p->rawS = 0; |
| 19545 | p->validTZ = 0; |
| 19546 | p->validJD = 0; |
| 19547 | if( sqlite3_stricmp(z,"month")==0 ){ |
| 19548 | p->D = 1; |
| 19549 | rc = 0; |
| 19550 | }else if( sqlite3_stricmp(z,"year")==0 ){ |
| 19551 | p->M = 1; |
| 19552 | p->D = 1; |
| 19553 | rc = 0; |
| 19554 | }else if( sqlite3_stricmp(z,"day")==0 ){ |
| 19555 | rc = 0; |
| @@ -24050,12 +24079,12 @@ | |
| 24079 | #ifdef SQLITE_DEBUG |
| 24080 | assert( p->nRef>0 || p->owner==0 ); |
| 24081 | p->owner = tid; |
| 24082 | p->nRef++; |
| 24083 | if( p->trace ){ |
| 24084 | OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", |
| 24085 | tid, p->id, p, p->trace, p->nRef)); |
| 24086 | } |
| 24087 | #endif |
| 24088 | } |
| 24089 | |
| 24090 | static int winMutexTry(sqlite3_mutex *p){ |
| @@ -24093,12 +24122,12 @@ | |
| 24122 | #else |
| 24123 | UNUSED_PARAMETER(p); |
| 24124 | #endif |
| 24125 | #ifdef SQLITE_DEBUG |
| 24126 | if( p->trace ){ |
| 24127 | OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n", |
| 24128 | tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); |
| 24129 | } |
| 24130 | #endif |
| 24131 | return rc; |
| 24132 | } |
| 24133 | |
| @@ -24122,12 +24151,12 @@ | |
| 24151 | #endif |
| 24152 | assert( winMutex_isInit==1 ); |
| 24153 | LeaveCriticalSection(&p->mutex); |
| 24154 | #ifdef SQLITE_DEBUG |
| 24155 | if( p->trace ){ |
| 24156 | OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", |
| 24157 | tid, p->id, p, p->trace, p->nRef)); |
| 24158 | } |
| 24159 | #endif |
| 24160 | } |
| 24161 | |
| 24162 | SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ |
| @@ -24383,10 +24412,17 @@ | |
| 24412 | ** implementation of malloc_good_size(), which must be called in debug |
| 24413 | ** mode and specifically when the DMD "Dark Matter Detector" is enabled |
| 24414 | ** or else a crash results. Hence, do not attempt to optimize out the |
| 24415 | ** following xRoundup() call. */ |
| 24416 | nFull = sqlite3GlobalConfig.m.xRoundup(n); |
| 24417 | |
| 24418 | #ifdef SQLITE_MAX_MEMORY |
| 24419 | if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){ |
| 24420 | *pp = 0; |
| 24421 | return; |
| 24422 | } |
| 24423 | #endif |
| 24424 | |
| 24425 | sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); |
| 24426 | if( mem0.alarmThreshold>0 ){ |
| 24427 | sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); |
| 24428 | if( nUsed >= mem0.alarmThreshold - nFull ){ |
| @@ -24572,11 +24608,11 @@ | |
| 24608 | return sqlite3GlobalConfig.m.xSize(p); |
| 24609 | } |
| 24610 | SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ |
| 24611 | assert( p!=0 ); |
| 24612 | if( db==0 || !isLookaside(db,p) ){ |
| 24613 | #ifdef SQLITE_DEBUG |
| 24614 | if( db==0 ){ |
| 24615 | assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); |
| 24616 | assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); |
| 24617 | }else{ |
| 24618 | assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| @@ -24633,11 +24669,11 @@ | |
| 24669 | measureAllocationSize(db, p); |
| 24670 | return; |
| 24671 | } |
| 24672 | if( isLookaside(db, p) ){ |
| 24673 | LookasideSlot *pBuf = (LookasideSlot*)p; |
| 24674 | #ifdef SQLITE_DEBUG |
| 24675 | /* Trash all content in the buffer being freed */ |
| 24676 | memset(p, 0xaa, db->lookaside.sz); |
| 24677 | #endif |
| 24678 | pBuf->pNext = db->lookaside.pFree; |
| 24679 | db->lookaside.pFree = pBuf; |
| @@ -25002,11 +25038,11 @@ | |
| 25038 | |
| 25039 | /* |
| 25040 | ** Conversion types fall into various categories as defined by the |
| 25041 | ** following enumeration. |
| 25042 | */ |
| 25043 | #define etRADIX 0 /* non-decimal integer types. %x %o */ |
| 25044 | #define etFLOAT 1 /* Floating point. %f */ |
| 25045 | #define etEXP 2 /* Exponentional notation. %e and %E */ |
| 25046 | #define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ |
| 25047 | #define etSIZE 4 /* Return number of characters processed so far. %n */ |
| 25048 | #define etSTRING 5 /* Strings. %s */ |
| @@ -25020,12 +25056,13 @@ | |
| 25056 | #define etTOKEN 11 /* a pointer to a Token structure */ |
| 25057 | #define etSRCLIST 12 /* a pointer to a SrcList */ |
| 25058 | #define etPOINTER 13 /* The %p conversion */ |
| 25059 | #define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ |
| 25060 | #define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ |
| 25061 | #define etDECIMAL 16 /* %d or %u, but not %x, %o */ |
| 25062 | |
| 25063 | #define etINVALID 17 /* Any unrecognized conversion type */ |
| 25064 | |
| 25065 | |
| 25066 | /* |
| 25067 | ** An "etByte" is an 8-bit unsigned value. |
| 25068 | */ |
| @@ -25045,40 +25082,40 @@ | |
| 25082 | } et_info; |
| 25083 | |
| 25084 | /* |
| 25085 | ** Allowed values for et_info.flags |
| 25086 | */ |
| 25087 | #define FLAG_SIGNED 1 /* True if the value to convert is signed */ |
| 25088 | #define FLAG_STRING 4 /* Allow infinite precision */ |
| 25089 | |
| 25090 | |
| 25091 | /* |
| 25092 | ** The following table is searched linearly, so it is good to put the |
| 25093 | ** most frequently used conversion types first. |
| 25094 | */ |
| 25095 | static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; |
| 25096 | static const char aPrefix[] = "-x0\000X0"; |
| 25097 | static const et_info fmtinfo[] = { |
| 25098 | { 'd', 10, 1, etDECIMAL, 0, 0 }, |
| 25099 | { 's', 0, 4, etSTRING, 0, 0 }, |
| 25100 | { 'g', 0, 1, etGENERIC, 30, 0 }, |
| 25101 | { 'z', 0, 4, etDYNSTRING, 0, 0 }, |
| 25102 | { 'q', 0, 4, etSQLESCAPE, 0, 0 }, |
| 25103 | { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, |
| 25104 | { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, |
| 25105 | { 'c', 0, 0, etCHARX, 0, 0 }, |
| 25106 | { 'o', 8, 0, etRADIX, 0, 2 }, |
| 25107 | { 'u', 10, 0, etDECIMAL, 0, 0 }, |
| 25108 | { 'x', 16, 0, etRADIX, 16, 1 }, |
| 25109 | { 'X', 16, 0, etRADIX, 0, 4 }, |
| 25110 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 25111 | { 'f', 0, 1, etFLOAT, 0, 0 }, |
| 25112 | { 'e', 0, 1, etEXP, 30, 0 }, |
| 25113 | { 'E', 0, 1, etEXP, 14, 0 }, |
| 25114 | { 'G', 0, 1, etGENERIC, 14, 0 }, |
| 25115 | #endif |
| 25116 | { 'i', 10, 1, etDECIMAL, 0, 0 }, |
| 25117 | { 'n', 0, 0, etSIZE, 0, 0 }, |
| 25118 | { '%', 0, 0, etPERCENT, 0, 0 }, |
| 25119 | { 'p', 16, 0, etPOINTER, 0, 1 }, |
| 25120 | |
| 25121 | /* All the rest are undocumented and are for internal use only */ |
| @@ -25166,18 +25203,17 @@ | |
| 25203 | int precision; /* Precision of the current field */ |
| 25204 | int length; /* Length of the field */ |
| 25205 | int idx; /* A general purpose loop counter */ |
| 25206 | int width; /* Width of the current field */ |
| 25207 | etByte flag_leftjustify; /* True if "-" flag is present */ |
| 25208 | etByte flag_prefix; /* '+' or ' ' or 0 for prefix */ |
| 25209 | etByte flag_alternateform; /* True if "#" flag is present */ |
| 25210 | etByte flag_altform2; /* True if "!" flag is present */ |
| 25211 | etByte flag_zeropad; /* True if field width constant starts with zero */ |
| 25212 | etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */ |
| 25213 | etByte done; /* Loop termination flag */ |
| 25214 | etByte cThousand; /* Thousands separator for %d and %u */ |
| 25215 | etByte xtype = etINVALID; /* Conversion paradigm */ |
| 25216 | u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ |
| 25217 | char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ |
| 25218 | sqlite_uint64 longvalue; /* Value for integer types */ |
| 25219 | LONGDOUBLE_TYPE realvalue; /* Value for real types */ |
| @@ -25216,21 +25252,22 @@ | |
| 25252 | if( (c=(*++fmt))==0 ){ |
| 25253 | sqlite3StrAccumAppend(pAccum, "%", 1); |
| 25254 | break; |
| 25255 | } |
| 25256 | /* Find out what flags are present */ |
| 25257 | flag_leftjustify = flag_prefix = cThousand = |
| 25258 | flag_alternateform = flag_altform2 = flag_zeropad = 0; |
| 25259 | done = 0; |
| 25260 | do{ |
| 25261 | switch( c ){ |
| 25262 | case '-': flag_leftjustify = 1; break; |
| 25263 | case '+': flag_prefix = '+'; break; |
| 25264 | case ' ': flag_prefix = ' '; break; |
| 25265 | case '#': flag_alternateform = 1; break; |
| 25266 | case '!': flag_altform2 = 1; break; |
| 25267 | case '0': flag_zeropad = 1; break; |
| 25268 | case ',': cThousand = ','; break; |
| 25269 | default: done = 1; break; |
| 25270 | } |
| 25271 | }while( !done && (c=(*++fmt))!=0 ); |
| 25272 | /* Get the field width */ |
| 25273 | if( c=='*' ){ |
| @@ -25296,17 +25333,15 @@ | |
| 25333 | /* Get the conversion type modifier */ |
| 25334 | if( c=='l' ){ |
| 25335 | flag_long = 1; |
| 25336 | c = *++fmt; |
| 25337 | if( c=='l' ){ |
| 25338 | flag_long = 2; |
| 25339 | c = *++fmt; |
| 25340 | } |
| 25341 | }else{ |
| 25342 | flag_long = 0; |
| 25343 | } |
| 25344 | /* Fetch the info entry for the field */ |
| 25345 | infop = &fmtinfo[0]; |
| 25346 | xtype = etINVALID; |
| 25347 | for(idx=0; idx<ArraySize(fmtinfo); idx++){ |
| @@ -25320,41 +25355,42 @@ | |
| 25355 | /* |
| 25356 | ** At this point, variables are initialized as follows: |
| 25357 | ** |
| 25358 | ** flag_alternateform TRUE if a '#' is present. |
| 25359 | ** flag_altform2 TRUE if a '!' is present. |
| 25360 | ** flag_prefix '+' or ' ' or zero |
| 25361 | ** flag_leftjustify TRUE if a '-' is present or if the |
| 25362 | ** field width was negative. |
| 25363 | ** flag_zeropad TRUE if the width began with 0. |
| 25364 | ** flag_long 1 for "l", 2 for "ll" |
| 25365 | ** width The specified field width. This is |
| 25366 | ** always non-negative. Zero is the default. |
| 25367 | ** precision The specified precision. The default |
| 25368 | ** is -1. |
| 25369 | ** xtype The class of the conversion. |
| 25370 | ** infop Pointer to the appropriate info struct. |
| 25371 | */ |
| 25372 | switch( xtype ){ |
| 25373 | case etPOINTER: |
| 25374 | flag_long = sizeof(char*)==sizeof(i64) ? 2 : |
| 25375 | sizeof(char*)==sizeof(long int) ? 1 : 0; |
| 25376 | /* Fall through into the next case */ |
| 25377 | case etORDINAL: |
| 25378 | case etRADIX: |
| 25379 | cThousand = 0; |
| 25380 | /* Fall through into the next case */ |
| 25381 | case etDECIMAL: |
| 25382 | if( infop->flags & FLAG_SIGNED ){ |
| 25383 | i64 v; |
| 25384 | if( bArgList ){ |
| 25385 | v = getIntArg(pArgList); |
| 25386 | }else if( flag_long ){ |
| 25387 | if( flag_long==2 ){ |
| 25388 | v = va_arg(ap,i64) ; |
| 25389 | }else{ |
| 25390 | v = va_arg(ap,long int); |
| 25391 | } |
| 25392 | }else{ |
| 25393 | v = va_arg(ap,int); |
| 25394 | } |
| 25395 | if( v<0 ){ |
| 25396 | if( v==SMALLEST_INT64 ){ |
| @@ -25363,35 +25399,35 @@ | |
| 25399 | longvalue = -v; |
| 25400 | } |
| 25401 | prefix = '-'; |
| 25402 | }else{ |
| 25403 | longvalue = v; |
| 25404 | prefix = flag_prefix; |
| 25405 | } |
| 25406 | }else{ |
| 25407 | if( bArgList ){ |
| 25408 | longvalue = (u64)getIntArg(pArgList); |
| 25409 | }else if( flag_long ){ |
| 25410 | if( flag_long==2 ){ |
| 25411 | longvalue = va_arg(ap,u64); |
| 25412 | }else{ |
| 25413 | longvalue = va_arg(ap,unsigned long int); |
| 25414 | } |
| 25415 | }else{ |
| 25416 | longvalue = va_arg(ap,unsigned int); |
| 25417 | } |
| 25418 | prefix = 0; |
| 25419 | } |
| 25420 | if( longvalue==0 ) flag_alternateform = 0; |
| 25421 | if( flag_zeropad && precision<width-(prefix!=0) ){ |
| 25422 | precision = width-(prefix!=0); |
| 25423 | } |
| 25424 | if( precision<etBUFSIZE-10-etBUFSIZE/3 ){ |
| 25425 | nOut = etBUFSIZE; |
| 25426 | zOut = buf; |
| 25427 | }else{ |
| 25428 | nOut = precision + 10 + precision/3; |
| 25429 | zOut = zExtra = sqlite3Malloc( nOut ); |
| 25430 | if( zOut==0 ){ |
| 25431 | setStrAccumError(pAccum, STRACCUM_NOMEM); |
| 25432 | return; |
| 25433 | } |
| @@ -25413,12 +25449,27 @@ | |
| 25449 | *(--bufpt) = cset[longvalue%base]; |
| 25450 | longvalue = longvalue/base; |
| 25451 | }while( longvalue>0 ); |
| 25452 | } |
| 25453 | length = (int)(&zOut[nOut-1]-bufpt); |
| 25454 | while( precision>length ){ |
| 25455 | *(--bufpt) = '0'; /* Zero pad */ |
| 25456 | length++; |
| 25457 | } |
| 25458 | if( cThousand ){ |
| 25459 | int nn = (length - 1)/3; /* Number of "," to insert */ |
| 25460 | int ix = (length - 1)%3 + 1; |
| 25461 | bufpt -= nn; |
| 25462 | for(idx=0; nn>0; idx++){ |
| 25463 | bufpt[idx] = bufpt[idx+nn]; |
| 25464 | ix--; |
| 25465 | if( ix==0 ){ |
| 25466 | bufpt[++idx] = cThousand; |
| 25467 | nn--; |
| 25468 | ix = 3; |
| 25469 | } |
| 25470 | } |
| 25471 | } |
| 25472 | if( prefix ) *(--bufpt) = prefix; /* Add sign */ |
| 25473 | if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ |
| 25474 | const char *pre; |
| 25475 | char x; |
| @@ -25441,13 +25492,11 @@ | |
| 25492 | if( precision<0 ) precision = 6; /* Set default precision */ |
| 25493 | if( realvalue<0.0 ){ |
| 25494 | realvalue = -realvalue; |
| 25495 | prefix = '-'; |
| 25496 | }else{ |
| 25497 | prefix = flag_prefix; |
| 25498 | } |
| 25499 | if( xtype==etGENERIC && precision>0 ) precision--; |
| 25500 | testcase( precision>0xfff ); |
| 25501 | for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} |
| 25502 | if( xtype==etFLOAT ) realvalue += rounder; |
| @@ -29464,117 +29513,119 @@ | |
| 29513 | /* 50 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), |
| 29514 | /* 51 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), |
| 29515 | /* 52 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), |
| 29516 | /* 53 */ "Last" OpHelp(""), |
| 29517 | /* 54 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), |
| 29518 | /* 55 */ "IfSmaller" OpHelp(""), |
| 29519 | /* 56 */ "SorterSort" OpHelp(""), |
| 29520 | /* 57 */ "Sort" OpHelp(""), |
| 29521 | /* 58 */ "Rewind" OpHelp(""), |
| 29522 | /* 59 */ "IdxLE" OpHelp("key=r[P3@P4]"), |
| 29523 | /* 60 */ "IdxGT" OpHelp("key=r[P3@P4]"), |
| 29524 | /* 61 */ "IdxLT" OpHelp("key=r[P3@P4]"), |
| 29525 | /* 62 */ "IdxGE" OpHelp("key=r[P3@P4]"), |
| 29526 | /* 63 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), |
| 29527 | /* 64 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), |
| 29528 | /* 65 */ "Program" OpHelp(""), |
| 29529 | /* 66 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), |
| 29530 | /* 67 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), |
| 29531 | /* 68 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), |
| 29532 | /* 69 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), |
| 29533 | /* 70 */ "IncrVacuum" OpHelp(""), |
| 29534 | /* 71 */ "VNext" OpHelp(""), |
| 29535 | /* 72 */ "Init" OpHelp("Start at P2"), |
| 29536 | /* 73 */ "Return" OpHelp(""), |
| 29537 | /* 74 */ "EndCoroutine" OpHelp(""), |
| 29538 | /* 75 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), |
| 29539 | /* 76 */ "Halt" OpHelp(""), |
| 29540 | /* 77 */ "Integer" OpHelp("r[P2]=P1"), |
| 29541 | /* 78 */ "Int64" OpHelp("r[P2]=P4"), |
| 29542 | /* 79 */ "String" OpHelp("r[P2]='P4' (len=P1)"), |
| 29543 | /* 80 */ "Null" OpHelp("r[P2..P3]=NULL"), |
| 29544 | /* 81 */ "SoftNull" OpHelp("r[P1]=NULL"), |
| 29545 | /* 82 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), |
| 29546 | /* 83 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), |
| 29547 | /* 84 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), |
| 29548 | /* 85 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), |
| 29549 | /* 86 */ "SCopy" OpHelp("r[P2]=r[P1]"), |
| 29550 | /* 87 */ "IntCopy" OpHelp("r[P2]=r[P1]"), |
| 29551 | /* 88 */ "ResultRow" OpHelp("output=r[P1@P2]"), |
| 29552 | /* 89 */ "CollSeq" OpHelp(""), |
| 29553 | /* 90 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), |
| 29554 | /* 91 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), |
| 29555 | /* 92 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), |
| 29556 | /* 93 */ "RealAffinity" OpHelp(""), |
| 29557 | /* 94 */ "Cast" OpHelp("affinity(r[P1])"), |
| 29558 | /* 95 */ "Permutation" OpHelp(""), |
| 29559 | /* 96 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), |
| 29560 | /* 97 */ "String8" OpHelp("r[P2]='P4'"), |
| 29561 | /* 98 */ "Column" OpHelp("r[P3]=PX"), |
| 29562 | /* 99 */ "Affinity" OpHelp("affinity(r[P1@P2])"), |
| 29563 | /* 100 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), |
| 29564 | /* 101 */ "Count" OpHelp("r[P2]=count()"), |
| 29565 | /* 102 */ "ReadCookie" OpHelp(""), |
| 29566 | /* 103 */ "SetCookie" OpHelp(""), |
| 29567 | /* 104 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), |
| 29568 | /* 105 */ "OpenRead" OpHelp("root=P2 iDb=P3"), |
| 29569 | /* 106 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), |
| 29570 | /* 107 */ "OpenAutoindex" OpHelp("nColumn=P2"), |
| 29571 | /* 108 */ "OpenEphemeral" OpHelp("nColumn=P2"), |
| 29572 | /* 109 */ "SorterOpen" OpHelp(""), |
| 29573 | /* 110 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), |
| 29574 | /* 111 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), |
| 29575 | /* 112 */ "Close" OpHelp(""), |
| 29576 | /* 113 */ "ColumnsUsed" OpHelp(""), |
| 29577 | /* 114 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), |
| 29578 | /* 115 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 29579 | /* 116 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 29580 | /* 117 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), |
| 29581 | /* 118 */ "Delete" OpHelp(""), |
| 29582 | /* 119 */ "ResetCount" OpHelp(""), |
| 29583 | /* 120 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), |
| 29584 | /* 121 */ "SorterData" OpHelp("r[P2]=data"), |
| 29585 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29586 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29587 | /* 124 */ "NullRow" OpHelp(""), |
| 29588 | /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), |
| 29589 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29590 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29591 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29592 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29593 | /* 130 */ "Destroy" OpHelp(""), |
| 29594 | /* 131 */ "Clear" OpHelp(""), |
| 29595 | /* 132 */ "Real" OpHelp("r[P2]=P4"), |
| 29596 | /* 133 */ "ResetSorter" OpHelp(""), |
| 29597 | /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 29598 | /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 29599 | /* 136 */ "SqlExec" OpHelp(""), |
| 29600 | /* 137 */ "ParseSchema" OpHelp(""), |
| 29601 | /* 138 */ "LoadAnalysis" OpHelp(""), |
| 29602 | /* 139 */ "DropTable" OpHelp(""), |
| 29603 | /* 140 */ "DropIndex" OpHelp(""), |
| 29604 | /* 141 */ "DropTrigger" OpHelp(""), |
| 29605 | /* 142 */ "IntegrityCk" OpHelp(""), |
| 29606 | /* 143 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), |
| 29607 | /* 144 */ "Param" OpHelp(""), |
| 29608 | /* 145 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), |
| 29609 | /* 146 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), |
| 29610 | /* 147 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), |
| 29611 | /* 148 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 29612 | /* 149 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 29613 | /* 150 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), |
| 29614 | /* 151 */ "Expire" OpHelp(""), |
| 29615 | /* 152 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), |
| 29616 | /* 153 */ "VBegin" OpHelp(""), |
| 29617 | /* 154 */ "VCreate" OpHelp(""), |
| 29618 | /* 155 */ "VDestroy" OpHelp(""), |
| 29619 | /* 156 */ "VOpen" OpHelp(""), |
| 29620 | /* 157 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), |
| 29621 | /* 158 */ "VRename" OpHelp(""), |
| 29622 | /* 159 */ "Pagecount" OpHelp(""), |
| 29623 | /* 160 */ "MaxPgcnt" OpHelp(""), |
| 29624 | /* 161 */ "CursorHint" OpHelp(""), |
| 29625 | /* 162 */ "Noop" OpHelp(""), |
| 29626 | /* 163 */ "Explain" OpHelp(""), |
| 29627 | }; |
| 29628 | return azName[i]; |
| 29629 | } |
| 29630 | #endif |
| 29631 | |
| @@ -37952,46 +38003,84 @@ | |
| 38003 | * be freed immediately and any attempt to access any of that freed |
| 38004 | * data will almost certainly result in an immediate access violation. |
| 38005 | ****************************************************************************** |
| 38006 | */ |
| 38007 | #ifndef SQLITE_WIN32_HEAP_CREATE |
| 38008 | # define SQLITE_WIN32_HEAP_CREATE (TRUE) |
| 38009 | #endif |
| 38010 | |
| 38011 | /* |
| 38012 | * This is the maximum possible initial size of the Win32-specific heap, in |
| 38013 | * bytes. |
| 38014 | */ |
| 38015 | #ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE |
| 38016 | # define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U) |
| 38017 | #endif |
| 38018 | |
| 38019 | /* |
| 38020 | * This is the extra space for the initial size of the Win32-specific heap, |
| 38021 | * in bytes. This value may be zero. |
| 38022 | */ |
| 38023 | #ifndef SQLITE_WIN32_HEAP_INIT_EXTRA |
| 38024 | # define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304) |
| 38025 | #endif |
| 38026 | |
| 38027 | /* |
| 38028 | * Calculate the maximum legal cache size, in pages, based on the maximum |
| 38029 | * possible initial heap size and the default page size, setting aside the |
| 38030 | * needed extra space. |
| 38031 | */ |
| 38032 | #ifndef SQLITE_WIN32_MAX_CACHE_SIZE |
| 38033 | # define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \ |
| 38034 | (SQLITE_WIN32_HEAP_INIT_EXTRA)) / \ |
| 38035 | (SQLITE_DEFAULT_PAGE_SIZE)) |
| 38036 | #endif |
| 38037 | |
| 38038 | /* |
| 38039 | * This is cache size used in the calculation of the initial size of the |
| 38040 | * Win32-specific heap. It cannot be negative. |
| 38041 | */ |
| 38042 | #ifndef SQLITE_WIN32_CACHE_SIZE |
| 38043 | # if SQLITE_DEFAULT_CACHE_SIZE>=0 |
| 38044 | # define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) |
| 38045 | # else |
| 38046 | # define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) |
| 38047 | # endif |
| 38048 | #endif |
| 38049 | |
| 38050 | /* |
| 38051 | * Make sure that the calculated cache size, in pages, cannot cause the |
| 38052 | * initial size of the Win32-specific heap to exceed the maximum amount |
| 38053 | * of memory that can be specified in the call to HeapCreate. |
| 38054 | */ |
| 38055 | #if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE |
| 38056 | # undef SQLITE_WIN32_CACHE_SIZE |
| 38057 | # define SQLITE_WIN32_CACHE_SIZE (2000) |
| 38058 | #endif |
| 38059 | |
| 38060 | /* |
| 38061 | * The initial size of the Win32-specific heap. This value may be zero. |
| 38062 | */ |
| 38063 | #ifndef SQLITE_WIN32_HEAP_INIT_SIZE |
| 38064 | # define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ |
| 38065 | (SQLITE_DEFAULT_PAGE_SIZE) + \ |
| 38066 | (SQLITE_WIN32_HEAP_INIT_EXTRA)) |
| 38067 | #endif |
| 38068 | |
| 38069 | /* |
| 38070 | * The maximum size of the Win32-specific heap. This value may be zero. |
| 38071 | */ |
| 38072 | #ifndef SQLITE_WIN32_HEAP_MAX_SIZE |
| 38073 | # define SQLITE_WIN32_HEAP_MAX_SIZE (0) |
| 38074 | #endif |
| 38075 | |
| 38076 | /* |
| 38077 | * The extra flags to use in calls to the Win32 heap APIs. This value may be |
| 38078 | * zero for the default behavior. |
| 38079 | */ |
| 38080 | #ifndef SQLITE_WIN32_HEAP_FLAGS |
| 38081 | # define SQLITE_WIN32_HEAP_FLAGS (0) |
| 38082 | #endif |
| 38083 | |
| 38084 | |
| 38085 | /* |
| 38086 | ** The winMemData structure stores information required by the Win32-specific |
| @@ -44084,11 +44173,11 @@ | |
| 44173 | ** This routine is for use inside of assert() statements only. For |
| 44174 | ** example: |
| 44175 | ** |
| 44176 | ** assert( sqlite3PcachePageSanity(pPg) ); |
| 44177 | */ |
| 44178 | #ifdef SQLITE_DEBUG |
| 44179 | SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ |
| 44180 | PCache *pCache; |
| 44181 | assert( pPg!=0 ); |
| 44182 | assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */ |
| 44183 | pCache = pPg->pCache; |
| @@ -60177,21 +60266,22 @@ | |
| 60266 | } |
| 60267 | #endif |
| 60268 | |
| 60269 | |
| 60270 | /* |
| 60271 | ** Defragment the page given. This routine reorganizes cells within the |
| 60272 | ** page so that there are no free-blocks on the free-block list. |
| 60273 | ** |
| 60274 | ** Parameter nMaxFrag is the maximum amount of fragmented space that may be |
| 60275 | ** present in the page after this routine returns. |
| 60276 | ** |
| 60277 | ** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a |
| 60278 | ** b-tree page so that there are no freeblocks or fragment bytes, all |
| 60279 | ** unused bytes are contained in the unallocated space region, and all |
| 60280 | ** cells are packed tightly at the end of the page. |
| 60281 | */ |
| 60282 | static int defragmentPage(MemPage *pPage, int nMaxFrag){ |
| 60283 | int i; /* Loop counter */ |
| 60284 | int pc; /* Address of the i-th cell */ |
| 60285 | int hdr; /* Offset to the page header */ |
| 60286 | int size; /* Size of a cell */ |
| 60287 | int usableSize; /* Number of usable bytes on a page */ |
| @@ -60202,11 +60292,10 @@ | |
| 60292 | unsigned char *temp; /* Temp area for cell content */ |
| 60293 | unsigned char *src; /* Source of content */ |
| 60294 | int iCellFirst; /* First allowable cell index */ |
| 60295 | int iCellLast; /* Last possible cell index */ |
| 60296 | |
| 60297 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 60298 | assert( pPage->pBt!=0 ); |
| 60299 | assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); |
| 60300 | assert( pPage->nOverflow==0 ); |
| 60301 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| @@ -60214,13 +60303,60 @@ | |
| 60303 | src = data = pPage->aData; |
| 60304 | hdr = pPage->hdrOffset; |
| 60305 | cellOffset = pPage->cellOffset; |
| 60306 | nCell = pPage->nCell; |
| 60307 | assert( nCell==get2byte(&data[hdr+3]) ); |
| 60308 | iCellFirst = cellOffset + 2*nCell; |
| 60309 | usableSize = pPage->pBt->usableSize; |
| 60310 | |
| 60311 | /* This block handles pages with two or fewer free blocks and nMaxFrag |
| 60312 | ** or fewer fragmented bytes. In this case it is faster to move the |
| 60313 | ** two (or one) blocks of cells using memmove() and add the required |
| 60314 | ** offsets to each pointer in the cell-pointer array than it is to |
| 60315 | ** reconstruct the entire page. */ |
| 60316 | if( (int)data[hdr+7]<=nMaxFrag ){ |
| 60317 | int iFree = get2byte(&data[hdr+1]); |
| 60318 | if( iFree ){ |
| 60319 | int iFree2 = get2byte(&data[iFree]); |
| 60320 | |
| 60321 | /* pageFindSlot() has already verified that free blocks are sorted |
| 60322 | ** in order of offset within the page, and that no block extends |
| 60323 | ** past the end of the page. Provided the two free slots do not |
| 60324 | ** overlap, this guarantees that the memmove() calls below will not |
| 60325 | ** overwrite the usableSize byte buffer, even if the database page |
| 60326 | ** is corrupt. */ |
| 60327 | assert( iFree2==0 || iFree2>iFree ); |
| 60328 | assert( iFree+get2byte(&data[iFree+2]) <= usableSize ); |
| 60329 | assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize ); |
| 60330 | |
| 60331 | if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){ |
| 60332 | u8 *pEnd = &data[cellOffset + nCell*2]; |
| 60333 | u8 *pAddr; |
| 60334 | int sz2 = 0; |
| 60335 | int sz = get2byte(&data[iFree+2]); |
| 60336 | int top = get2byte(&data[hdr+5]); |
| 60337 | if( iFree2 ){ |
| 60338 | if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT; |
| 60339 | sz2 = get2byte(&data[iFree2+2]); |
| 60340 | assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); |
| 60341 | memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); |
| 60342 | sz += sz2; |
| 60343 | } |
| 60344 | cbrk = top+sz; |
| 60345 | assert( cbrk+(iFree-top) <= usableSize ); |
| 60346 | memmove(&data[cbrk], &data[top], iFree-top); |
| 60347 | for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){ |
| 60348 | pc = get2byte(pAddr); |
| 60349 | if( pc<iFree ){ put2byte(pAddr, pc+sz); } |
| 60350 | else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); } |
| 60351 | } |
| 60352 | goto defragment_out; |
| 60353 | } |
| 60354 | } |
| 60355 | } |
| 60356 | |
| 60357 | cbrk = usableSize; |
| 60358 | iCellLast = usableSize - 4; |
| 60359 | for(i=0; i<nCell; i++){ |
| 60360 | u8 *pAddr; /* The i-th cell pointer */ |
| 60361 | pAddr = &data[cellOffset + i*2]; |
| 60362 | pc = get2byte(pAddr); |
| @@ -60250,20 +60386,22 @@ | |
| 60386 | memcpy(&temp[x], &data[x], (cbrk+size) - x); |
| 60387 | src = temp; |
| 60388 | } |
| 60389 | memcpy(&data[cbrk], &src[pc], size); |
| 60390 | } |
| 60391 | data[hdr+7] = 0; |
| 60392 | |
| 60393 | defragment_out: |
| 60394 | if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ |
| 60395 | return SQLITE_CORRUPT_BKPT; |
| 60396 | } |
| 60397 | assert( cbrk>=iCellFirst ); |
| 60398 | put2byte(&data[hdr+5], cbrk); |
| 60399 | data[hdr+1] = 0; |
| 60400 | data[hdr+2] = 0; |
| 60401 | memset(&data[iCellFirst], 0, cbrk-iCellFirst); |
| 60402 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 60403 | return SQLITE_OK; |
| 60404 | } |
| 60405 | |
| 60406 | /* |
| 60407 | ** Search the free-list on page pPg for space to store a cell nByte bytes in |
| @@ -60397,14 +60535,14 @@ | |
| 60535 | ** to see if defragmentation is necessary. |
| 60536 | */ |
| 60537 | testcase( gap+2+nByte==top ); |
| 60538 | if( gap+2+nByte>top ){ |
| 60539 | assert( pPage->nCell>0 || CORRUPT_DB ); |
| 60540 | rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte))); |
| 60541 | if( rc ) return rc; |
| 60542 | top = get2byteNotZero(&data[hdr+5]); |
| 60543 | assert( gap+2+nByte<=top ); |
| 60544 | } |
| 60545 | |
| 60546 | |
| 60547 | /* Allocate memory from the gap in between the cell pointer array |
| 60548 | ** and the cell content area. The btreeInitPage() call has already |
| @@ -63636,11 +63774,11 @@ | |
| 63774 | pCur->aiIdx[pCur->iPage] = 0; |
| 63775 | return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], |
| 63776 | pCur, pCur->curPagerFlags); |
| 63777 | } |
| 63778 | |
| 63779 | #ifdef SQLITE_DEBUG |
| 63780 | /* |
| 63781 | ** Page pParent is an internal (non-leaf) tree page. This function |
| 63782 | ** asserts that page number iChild is the left-child if the iIdx'th |
| 63783 | ** cell in page pParent. Or, if iIdx is equal to the total number of |
| 63784 | ** cells in pParent, that page number iChild is the right-child of |
| @@ -64178,10 +64316,34 @@ | |
| 64316 | ** have been deleted? This API will need to change to return an error code |
| 64317 | ** as well as the boolean result value. |
| 64318 | */ |
| 64319 | return (CURSOR_VALID!=pCur->eState); |
| 64320 | } |
| 64321 | |
| 64322 | /* |
| 64323 | ** Return an estimate for the number of rows in the table that pCur is |
| 64324 | ** pointing to. Return a negative number if no estimate is currently |
| 64325 | ** available. |
| 64326 | */ |
| 64327 | SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ |
| 64328 | i64 n; |
| 64329 | u8 i; |
| 64330 | |
| 64331 | assert( cursorOwnsBtShared(pCur) ); |
| 64332 | assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); |
| 64333 | |
| 64334 | /* Currently this interface is only called by the OP_IfSmaller |
| 64335 | ** opcode, and it that case the cursor will always be valid and |
| 64336 | ** will always point to a leaf node. */ |
| 64337 | if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1; |
| 64338 | if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1; |
| 64339 | |
| 64340 | for(n=1, i=0; i<=pCur->iPage; i++){ |
| 64341 | n *= pCur->apPage[i]->nCell; |
| 64342 | } |
| 64343 | return n; |
| 64344 | } |
| 64345 | |
| 64346 | /* |
| 64347 | ** Advance the cursor to the next entry in the database. If |
| 64348 | ** successful then set *pRes=0. If the cursor |
| 64349 | ** was already pointing to the last entry in the database before |
| @@ -65023,11 +65185,11 @@ | |
| 65185 | ** pPrior Where to write the pgno of the first overflow page |
| 65186 | ** |
| 65187 | ** Use a call to btreeParseCellPtr() to verify that the values above |
| 65188 | ** were computed correctly. |
| 65189 | */ |
| 65190 | #ifdef SQLITE_DEBUG |
| 65191 | { |
| 65192 | CellInfo info; |
| 65193 | pPage->xParseCell(pPage, pCell, &info); |
| 65194 | assert( nHeader==(int)(info.pPayload - pCell) ); |
| 65195 | assert( info.nKey==pX->nKey ); |
| @@ -66549,11 +66711,11 @@ | |
| 66711 | ** copied into the parent, because if the parent is page 1 then it will |
| 66712 | ** by smaller than the child due to the database header, and so all the |
| 66713 | ** free space needs to be up front. |
| 66714 | */ |
| 66715 | assert( nNew==1 || CORRUPT_DB ); |
| 66716 | rc = defragmentPage(apNew[0], -1); |
| 66717 | testcase( rc!=SQLITE_OK ); |
| 66718 | assert( apNew[0]->nFree == |
| 66719 | (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) |
| 66720 | || rc!=SQLITE_OK |
| 66721 | ); |
| @@ -71201,10 +71363,11 @@ | |
| 71363 | ** Remember the SQL string for a prepared statement. |
| 71364 | */ |
| 71365 | SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ |
| 71366 | assert( isPrepareV2==1 || isPrepareV2==0 ); |
| 71367 | if( p==0 ) return; |
| 71368 | if( !isPrepareV2 ) p->expmask = 0; |
| 71369 | #if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) |
| 71370 | if( !isPrepareV2 ) return; |
| 71371 | #endif |
| 71372 | assert( p->zSql==0 ); |
| 71373 | p->zSql = sqlite3DbStrNDup(p->db, z, n); |
| @@ -71229,10 +71392,11 @@ | |
| 71392 | pB->pPrev = pTmp; |
| 71393 | zTmp = pA->zSql; |
| 71394 | pA->zSql = pB->zSql; |
| 71395 | pB->zSql = zTmp; |
| 71396 | pB->isPrepareV2 = pA->isPrepareV2; |
| 71397 | pB->expmask = pA->expmask; |
| 71398 | } |
| 71399 | |
| 71400 | /* |
| 71401 | ** Resize the Vdbe.aOp array so that it is at least nOp elements larger |
| 71402 | ** than its current size. nOp is guaranteed to be less than or equal |
| @@ -73753,17 +73917,17 @@ | |
| 73917 | ** Then the internal cache might have been left in an inconsistent |
| 73918 | ** state. We need to rollback the statement transaction, if there is |
| 73919 | ** one, or the complete transaction if there is no statement transaction. |
| 73920 | */ |
| 73921 | |
| 73922 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| 73923 | return SQLITE_OK; |
| 73924 | } |
| 73925 | if( db->mallocFailed ){ |
| 73926 | p->rc = SQLITE_NOMEM_BKPT; |
| 73927 | } |
| 73928 | closeAllCursors(p); |
| 73929 | checkActiveVdbeCnt(db); |
| 73930 | |
| 73931 | /* No commit or rollback needed if the program never started or if the |
| 73932 | ** SQL statement does not read or write a database file. */ |
| 73933 | if( p->pc>=0 && p->bIsReader ){ |
| @@ -74706,11 +74870,11 @@ | |
| 74870 | } |
| 74871 | assert( u<=pKeyInfo->nField + 1 ); |
| 74872 | p->nField = u; |
| 74873 | } |
| 74874 | |
| 74875 | #ifdef SQLITE_DEBUG |
| 74876 | /* |
| 74877 | ** This function compares two index or table record keys in the same way |
| 74878 | ** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), |
| 74879 | ** this function deserializes and compares values using the |
| 74880 | ** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used |
| @@ -74811,11 +74975,11 @@ | |
| 74975 | if( pKeyInfo->db->mallocFailed ) return 1; |
| 74976 | return 0; |
| 74977 | } |
| 74978 | #endif |
| 74979 | |
| 74980 | #ifdef SQLITE_DEBUG |
| 74981 | /* |
| 74982 | ** Count the number of fields (a.k.a. columns) in the record given by |
| 74983 | ** pKey,nKey. The verify that this count is less than or equal to the |
| 74984 | ** limit given by pKeyInfo->nField + pKeyInfo->nXField. |
| 74985 | ** |
| @@ -75694,12 +75858,12 @@ | |
| 75858 | ** to sqlite3_reoptimize() that re-preparing the statement may result |
| 75859 | ** in a better query plan. |
| 75860 | */ |
| 75861 | SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ |
| 75862 | assert( iVar>0 ); |
| 75863 | if( iVar>=32 ){ |
| 75864 | v->expmask |= 0x80000000; |
| 75865 | }else{ |
| 75866 | v->expmask |= ((u32)1 << (iVar-1)); |
| 75867 | } |
| 75868 | } |
| 75869 | |
| @@ -75965,11 +76129,12 @@ | |
| 76129 | sqlite3_mutex_enter(mutex); |
| 76130 | for(i=0; i<p->nVar; i++){ |
| 76131 | sqlite3VdbeMemRelease(&p->aVar[i]); |
| 76132 | p->aVar[i].flags = MEM_Null; |
| 76133 | } |
| 76134 | assert( p->isPrepareV2 || p->expmask==0 ); |
| 76135 | if( p->expmask ){ |
| 76136 | p->expired = 1; |
| 76137 | } |
| 76138 | sqlite3_mutex_leave(mutex); |
| 76139 | return rc; |
| 76140 | } |
| @@ -77069,13 +77234,12 @@ | |
| 77234 | ** parameter in the WHERE clause might influence the choice of query plan |
| 77235 | ** for a statement, then the statement will be automatically recompiled, |
| 77236 | ** as if there had been a schema change, on the first sqlite3_step() call |
| 77237 | ** following any change to the bindings of that parameter. |
| 77238 | */ |
| 77239 | assert( p->isPrepareV2 || p->expmask==0 ); |
| 77240 | if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){ |
| 77241 | p->expired = 1; |
| 77242 | } |
| 77243 | return SQLITE_OK; |
| 77244 | } |
| 77245 | |
| @@ -77334,14 +77498,16 @@ | |
| 77498 | Vdbe *pFrom = (Vdbe*)pFromStmt; |
| 77499 | Vdbe *pTo = (Vdbe*)pToStmt; |
| 77500 | if( pFrom->nVar!=pTo->nVar ){ |
| 77501 | return SQLITE_ERROR; |
| 77502 | } |
| 77503 | assert( pTo->isPrepareV2 || pTo->expmask==0 ); |
| 77504 | if( pTo->expmask ){ |
| 77505 | pTo->expired = 1; |
| 77506 | } |
| 77507 | assert( pFrom->isPrepareV2 || pFrom->expmask==0 ); |
| 77508 | if( pFrom->expmask ){ |
| 77509 | pFrom->expired = 1; |
| 77510 | } |
| 77511 | return sqlite3TransferBindings(pFromStmt, pToStmt); |
| 77512 | } |
| 77513 | #endif |
| @@ -79658,39 +79824,39 @@ | |
| 79824 | if( pCtx->pOut != pOut ){ |
| 79825 | pCtx->pOut = pOut; |
| 79826 | for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; |
| 79827 | } |
| 79828 | |
| 79829 | memAboutToChange(p, pOut); |
| 79830 | #ifdef SQLITE_DEBUG |
| 79831 | for(i=0; i<pCtx->argc; i++){ |
| 79832 | assert( memIsValid(pCtx->argv[i]) ); |
| 79833 | REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); |
| 79834 | } |
| 79835 | #endif |
| 79836 | MemSetTypeFlag(pOut, MEM_Null); |
| 79837 | pCtx->fErrorOrAux = 0; |
| 79838 | (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ |
| 79839 | |
| 79840 | /* If the function returned an error, throw an exception */ |
| 79841 | if( pCtx->fErrorOrAux ){ |
| 79842 | if( pCtx->isError ){ |
| 79843 | sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); |
| 79844 | rc = pCtx->isError; |
| 79845 | } |
| 79846 | sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); |
| 79847 | if( rc ) goto abort_due_to_error; |
| 79848 | } |
| 79849 | |
| 79850 | /* Copy the result of the function into register P3 */ |
| 79851 | if( pOut->flags & (MEM_Str|MEM_Blob) ){ |
| 79852 | sqlite3VdbeChangeEncoding(pOut, encoding); |
| 79853 | if( sqlite3VdbeMemTooBig(pOut) ) goto too_big; |
| 79854 | } |
| 79855 | |
| 79856 | REGISTER_TRACE(pOp->p3, pOut); |
| 79857 | UPDATE_MAX_BLOBSIZE(pOut); |
| 79858 | break; |
| 79859 | } |
| 79860 | |
| 79861 | /* Opcode: BitAnd P1 P2 P3 * * |
| 79862 | ** Synopsis: r[P3]=r[P1]&r[P2] |
| @@ -80187,11 +80353,11 @@ | |
| 80353 | pKeyInfo = pOp->p4.pKeyInfo; |
| 80354 | assert( n>0 ); |
| 80355 | assert( pKeyInfo!=0 ); |
| 80356 | p1 = pOp->p1; |
| 80357 | p2 = pOp->p2; |
| 80358 | #ifdef SQLITE_DEBUG |
| 80359 | if( aPermute ){ |
| 80360 | int k, mx = 0; |
| 80361 | for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k]; |
| 80362 | assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); |
| 80363 | assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 ); |
| @@ -82836,10 +83002,37 @@ | |
| 83002 | assert( pOp->p2==0 ); |
| 83003 | } |
| 83004 | break; |
| 83005 | } |
| 83006 | |
| 83007 | /* Opcode: IfSmaller P1 P2 P3 * * |
| 83008 | ** |
| 83009 | ** Estimate the number of rows in the table P1. Jump to P2 if that |
| 83010 | ** estimate is less than approximately 2**(0.1*P3). |
| 83011 | */ |
| 83012 | case OP_IfSmaller: { /* jump */ |
| 83013 | VdbeCursor *pC; |
| 83014 | BtCursor *pCrsr; |
| 83015 | int res; |
| 83016 | i64 sz; |
| 83017 | |
| 83018 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 83019 | pC = p->apCsr[pOp->p1]; |
| 83020 | assert( pC!=0 ); |
| 83021 | pCrsr = pC->uc.pCursor; |
| 83022 | assert( pCrsr ); |
| 83023 | rc = sqlite3BtreeFirst(pCrsr, &res); |
| 83024 | if( rc ) goto abort_due_to_error; |
| 83025 | if( res==0 ){ |
| 83026 | sz = sqlite3BtreeRowCountEst(pCrsr); |
| 83027 | if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)<pOp->p3 ) res = 1; |
| 83028 | } |
| 83029 | VdbeBranchTaken(res!=0,2); |
| 83030 | if( res ) goto jump_to_p2; |
| 83031 | break; |
| 83032 | } |
| 83033 | |
| 83034 | |
| 83035 | /* Opcode: SorterSort P1 P2 * * * |
| 83036 | ** |
| 83037 | ** After all records have been inserted into the Sorter object |
| 83038 | ** identified by P1, invoke this opcode to actually do the sorting. |
| @@ -83479,10 +83672,22 @@ | |
| 83672 | rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); |
| 83673 | if( rc ) goto abort_due_to_error; |
| 83674 | pOut->u.i = pgno; |
| 83675 | break; |
| 83676 | } |
| 83677 | |
| 83678 | /* Opcode: SqlExec * * * P4 * |
| 83679 | ** |
| 83680 | ** Run the SQL statement or statements specified in the P4 string. |
| 83681 | */ |
| 83682 | case OP_SqlExec: { |
| 83683 | db->nSqlExec++; |
| 83684 | rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); |
| 83685 | db->nSqlExec--; |
| 83686 | if( rc ) goto abort_due_to_error; |
| 83687 | break; |
| 83688 | } |
| 83689 | |
| 83690 | /* Opcode: ParseSchema P1 * * P4 * |
| 83691 | ** |
| 83692 | ** Read and parse all entries from the SQLITE_MASTER table of database P1 |
| 83693 | ** that match the WHERE clause P4. |
| @@ -83600,11 +83805,11 @@ | |
| 83805 | ** |
| 83806 | ** Do an analysis of the currently open database. Store in |
| 83807 | ** register P1 the text of an error message describing any problems. |
| 83808 | ** If no problems are found, store a NULL in register P1. |
| 83809 | ** |
| 83810 | ** The register P3 contains one less than the maximum number of allowed errors. |
| 83811 | ** At most reg(P3) errors will be reported. |
| 83812 | ** In other words, the analysis stops as soon as reg(P1) errors are |
| 83813 | ** seen. Reg(P1) is updated with the number of errors remaining. |
| 83814 | ** |
| 83815 | ** The root page numbers of all tables in the database are integers |
| @@ -83633,18 +83838,18 @@ | |
| 83838 | assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); |
| 83839 | pIn1 = &aMem[pOp->p1]; |
| 83840 | assert( pOp->p5<db->nDb ); |
| 83841 | assert( DbMaskTest(p->btreeMask, pOp->p5) ); |
| 83842 | z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, |
| 83843 | (int)pnErr->u.i+1, &nErr); |
| 83844 | sqlite3VdbeMemSetNull(pIn1); |
| 83845 | if( nErr==0 ){ |
| 83846 | assert( z==0 ); |
| 83847 | }else if( z==0 ){ |
| 83848 | goto no_mem; |
| 83849 | }else{ |
| 83850 | pnErr->u.i -= nErr-1; |
| 83851 | sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); |
| 83852 | } |
| 83853 | UPDATE_MAX_BLOBSIZE(pIn1); |
| 83854 | sqlite3VdbeChangeEncoding(pIn1, encoding); |
| 83855 | break; |
| @@ -88787,15 +88992,15 @@ | |
| 88992 | ** The return value from the callback should be one of the WRC_* |
| 88993 | ** constants to specify how to proceed with the walk. |
| 88994 | ** |
| 88995 | ** WRC_Continue Continue descending down the tree. |
| 88996 | ** |
| 88997 | ** WRC_Prune Do not descend into child nodes, but allow |
| 88998 | ** the walk to continue with sibling nodes. |
| 88999 | ** |
| 89000 | ** WRC_Abort Do no more callbacks. Unwind the stack and |
| 89001 | ** return from the top-level walk call. |
| 89002 | ** |
| 89003 | ** The return value from this routine is WRC_Abort to abandon the tree walk |
| 89004 | ** and WRC_Continue to continue. |
| 89005 | */ |
| 89006 | static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ |
| @@ -89153,11 +89358,12 @@ | |
| 89358 | } |
| 89359 | } |
| 89360 | } |
| 89361 | |
| 89362 | /* Start at the inner-most context and move outward until a match is found */ |
| 89363 | assert( pNC && cnt==0 ); |
| 89364 | do{ |
| 89365 | ExprList *pEList; |
| 89366 | SrcList *pSrcList = pNC->pSrcList; |
| 89367 | |
| 89368 | if( pSrcList ){ |
| 89369 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| @@ -89338,15 +89544,15 @@ | |
| 89544 | } |
| 89545 | |
| 89546 | /* Advance to the next name context. The loop will exit when either |
| 89547 | ** we have a match (cnt>0) or when we run out of name contexts. |
| 89548 | */ |
| 89549 | if( cnt ) break; |
| 89550 | pNC = pNC->pNext; |
| 89551 | nSubquery++; |
| 89552 | }while( pNC ); |
| 89553 | |
| 89554 | |
| 89555 | /* |
| 89556 | ** If X and Y are NULL (in other words if only the column name Z is |
| 89557 | ** supplied) and the value of Z is enclosed in double-quotes, then |
| 89558 | ** Z is a string literal if it doesn't match any column names. In that |
| @@ -89532,37 +89738,42 @@ | |
| 89738 | break; |
| 89739 | } |
| 89740 | #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) |
| 89741 | && !defined(SQLITE_OMIT_SUBQUERY) */ |
| 89742 | |
| 89743 | /* A column name: ID |
| 89744 | ** Or table name and column name: ID.ID |
| 89745 | ** Or a database, table and column: ID.ID.ID |
| 89746 | ** |
| 89747 | ** The TK_ID and TK_OUT cases are combined so that there will only |
| 89748 | ** be one call to lookupName(). Then the compiler will in-line |
| 89749 | ** lookupName() for a size reduction and performance increase. |
| 89750 | */ |
| 89751 | case TK_ID: |
| 89752 | case TK_DOT: { |
| 89753 | const char *zColumn; |
| 89754 | const char *zTable; |
| 89755 | const char *zDb; |
| 89756 | Expr *pRight; |
| 89757 | |
| 89758 | if( pExpr->op==TK_ID ){ |
| 89759 | zDb = 0; |
| 89760 | zTable = 0; |
| 89761 | zColumn = pExpr->u.zToken; |
| 89762 | }else{ |
| 89763 | notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); |
| 89764 | pRight = pExpr->pRight; |
| 89765 | if( pRight->op==TK_ID ){ |
| 89766 | zDb = 0; |
| 89767 | zTable = pExpr->pLeft->u.zToken; |
| 89768 | zColumn = pRight->u.zToken; |
| 89769 | }else{ |
| 89770 | assert( pRight->op==TK_DOT ); |
| 89771 | zDb = pExpr->pLeft->u.zToken; |
| 89772 | zTable = pRight->pLeft->u.zToken; |
| 89773 | zColumn = pRight->pRight->u.zToken; |
| 89774 | } |
| 89775 | } |
| 89776 | return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); |
| 89777 | } |
| 89778 | |
| 89779 | /* Resolve function names |
| @@ -92833,11 +93044,11 @@ | |
| 93044 | int nVal = sqlite3ExprVectorSize(pLeft); |
| 93045 | Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; |
| 93046 | char *zRet; |
| 93047 | |
| 93048 | assert( pExpr->op==TK_IN ); |
| 93049 | zRet = sqlite3DbMallocRaw(pParse->db, nVal+1); |
| 93050 | if( zRet ){ |
| 93051 | int i; |
| 93052 | for(i=0; i<nVal; i++){ |
| 93053 | Expr *pA = sqlite3VectorFieldSubexpr(pLeft, i); |
| 93054 | char a = sqlite3ExprAffinity(pA); |
| @@ -93738,11 +93949,11 @@ | |
| 93949 | ** Clear all column cache entries. |
| 93950 | */ |
| 93951 | SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ |
| 93952 | int i; |
| 93953 | |
| 93954 | #ifdef SQLITE_DEBUG |
| 93955 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 93956 | printf("CLEAR\n"); |
| 93957 | } |
| 93958 | #endif |
| 93959 | for(i=0; i<pParse->nColCache; i++){ |
| @@ -95145,10 +95356,21 @@ | |
| 95356 | if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; |
| 95357 | if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1; |
| 95358 | } |
| 95359 | return 0; |
| 95360 | } |
| 95361 | |
| 95362 | /* |
| 95363 | ** Like sqlite3ExprCompare() except COLLATE operators at the top-level |
| 95364 | ** are ignored. |
| 95365 | */ |
| 95366 | SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ |
| 95367 | return sqlite3ExprCompare( |
| 95368 | sqlite3ExprSkipCollate(pA), |
| 95369 | sqlite3ExprSkipCollate(pB), |
| 95370 | iTab); |
| 95371 | } |
| 95372 | |
| 95373 | /* |
| 95374 | ** Return true if we can prove the pE2 will always be true if pE1 is |
| 95375 | ** true. Return false if we cannot complete the proof or if pE2 might |
| 95376 | ** be false. Examples: |
| @@ -96698,10 +96920,11 @@ | |
| 96920 | Stat4Sample current; /* Current row as a Stat4Sample */ |
| 96921 | u32 iPrn; /* Pseudo-random number used for sampling */ |
| 96922 | Stat4Sample *aBest; /* Array of nCol best samples */ |
| 96923 | int iMin; /* Index in a[] of entry with minimum score */ |
| 96924 | int nSample; /* Current number of samples */ |
| 96925 | int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */ |
| 96926 | int iGet; /* Index of current sample accessed by stat_get() */ |
| 96927 | Stat4Sample *a; /* Array of mxSample Stat4Sample objects */ |
| 96928 | sqlite3 *db; /* Database connection, for malloc() */ |
| 96929 | }; |
| 96930 | |
| @@ -96962,10 +97185,17 @@ | |
| 97185 | int i; |
| 97186 | |
| 97187 | assert( IsStat4 || nEqZero==0 ); |
| 97188 | |
| 97189 | #ifdef SQLITE_ENABLE_STAT4 |
| 97190 | /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0 |
| 97191 | ** values in the anEq[] array of any sample in Stat4Accum.a[]. In |
| 97192 | ** other words, if nMaxEqZero is n, then it is guaranteed that there |
| 97193 | ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */ |
| 97194 | if( nEqZero>p->nMaxEqZero ){ |
| 97195 | p->nMaxEqZero = nEqZero; |
| 97196 | } |
| 97197 | if( pNew->isPSample==0 ){ |
| 97198 | Stat4Sample *pUpgrade = 0; |
| 97199 | assert( pNew->anEq[pNew->iCol]>0 ); |
| 97200 | |
| 97201 | /* This sample is being added because the prefix that ends in column |
| @@ -97059,16 +97289,26 @@ | |
| 97289 | if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ |
| 97290 | sampleInsert(p, pBest, i); |
| 97291 | } |
| 97292 | } |
| 97293 | |
| 97294 | /* Check that no sample contains an anEq[] entry with an index of |
| 97295 | ** p->nMaxEqZero or greater set to zero. */ |
| 97296 | for(i=p->nSample-1; i>=0; i--){ |
| 97297 | int j; |
| 97298 | for(j=p->nMaxEqZero; j<p->nCol; j++) assert( p->a[i].anEq[j]>0 ); |
| 97299 | } |
| 97300 | |
| 97301 | /* Update the anEq[] fields of any samples already collected. */ |
| 97302 | if( iChng<p->nMaxEqZero ){ |
| 97303 | for(i=p->nSample-1; i>=0; i--){ |
| 97304 | int j; |
| 97305 | for(j=iChng; j<p->nCol; j++){ |
| 97306 | if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; |
| 97307 | } |
| 97308 | } |
| 97309 | p->nMaxEqZero = iChng; |
| 97310 | } |
| 97311 | #endif |
| 97312 | |
| 97313 | #if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) |
| 97314 | if( iChng==0 ){ |
| @@ -97778,44 +98018,32 @@ | |
| 98018 | /* Form 1: Analyze everything */ |
| 98019 | for(i=0; i<db->nDb; i++){ |
| 98020 | if( i==1 ) continue; /* Do not analyze the TEMP database */ |
| 98021 | analyzeDatabase(pParse, i); |
| 98022 | } |
| 98023 | }else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){ |
| 98024 | /* Analyze the schema named as the argument */ |
| 98025 | analyzeDatabase(pParse, iDb); |
| 98026 | }else{ |
| 98027 | /* Form 3: Analyze the table or index named as an argument */ |
| 98028 | iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); |
| 98029 | if( iDb>=0 ){ |
| 98030 | zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; |
| 98031 | z = sqlite3NameFromToken(db, pTableName); |
| 98032 | if( z ){ |
| 98033 | if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ |
| 98034 | analyzeTable(pParse, pIdx->pTable, pIdx); |
| 98035 | }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ |
| 98036 | analyzeTable(pParse, pTab, 0); |
| 98037 | } |
| 98038 | sqlite3DbFree(db, z); |
| 98039 | } |
| 98040 | } |
| 98041 | } |
| 98042 | if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){ |
| 98043 | sqlite3VdbeAddOp0(v, OP_Expire); |
| 98044 | } |
| 98045 | } |
| 98046 | |
| 98047 | /* |
| 98048 | ** Used to pass information from the analyzer reader through to the |
| 98049 | ** callback routine. |
| @@ -97940,19 +98168,24 @@ | |
| 98168 | } |
| 98169 | aiRowEst = pIndex->aiRowEst; |
| 98170 | #endif |
| 98171 | pIndex->bUnordered = 0; |
| 98172 | decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); |
| 98173 | pIndex->hasStat1 = 1; |
| 98174 | if( pIndex->pPartIdxWhere==0 ){ |
| 98175 | pTable->nRowLogEst = pIndex->aiRowLogEst[0]; |
| 98176 | pTable->tabFlags |= TF_HasStat1; |
| 98177 | } |
| 98178 | }else{ |
| 98179 | Index fakeIdx; |
| 98180 | fakeIdx.szIdxRow = pTable->szTabRow; |
| 98181 | #ifdef SQLITE_ENABLE_COSTMULT |
| 98182 | fakeIdx.pTable = pTable; |
| 98183 | #endif |
| 98184 | decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); |
| 98185 | pTable->szTabRow = fakeIdx.szIdxRow; |
| 98186 | pTable->tabFlags |= TF_HasStat1; |
| 98187 | } |
| 98188 | |
| 98189 | return 0; |
| 98190 | } |
| 98191 | |
| @@ -98243,19 +98476,24 @@ | |
| 98476 | SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ |
| 98477 | analysisInfo sInfo; |
| 98478 | HashElem *i; |
| 98479 | char *zSql; |
| 98480 | int rc = SQLITE_OK; |
| 98481 | Schema *pSchema = db->aDb[iDb].pSchema; |
| 98482 | |
| 98483 | assert( iDb>=0 && iDb<db->nDb ); |
| 98484 | assert( db->aDb[iDb].pBt!=0 ); |
| 98485 | |
| 98486 | /* Clear any prior statistics */ |
| 98487 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 98488 | for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){ |
| 98489 | Table *pTab = sqliteHashData(i); |
| 98490 | pTab->tabFlags &= ~TF_HasStat1; |
| 98491 | } |
| 98492 | for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ |
| 98493 | Index *pIdx = sqliteHashData(i); |
| 98494 | pIdx->hasStat1 = 0; |
| 98495 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 98496 | sqlite3DeleteIndexSamples(db, pIdx); |
| 98497 | pIdx->aSample = 0; |
| 98498 | #endif |
| 98499 | } |
| @@ -98274,23 +98512,23 @@ | |
| 98512 | } |
| 98513 | } |
| 98514 | |
| 98515 | /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */ |
| 98516 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 98517 | for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ |
| 98518 | Index *pIdx = sqliteHashData(i); |
| 98519 | if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx); |
| 98520 | } |
| 98521 | |
| 98522 | /* Load the statistics from the sqlite_stat4 table. */ |
| 98523 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 98524 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 98525 | db->lookaside.bDisable++; |
| 98526 | rc = loadStat4(db, sInfo.zDatabase); |
| 98527 | db->lookaside.bDisable--; |
| 98528 | } |
| 98529 | for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ |
| 98530 | Index *pIdx = sqliteHashData(i); |
| 98531 | sqlite3_free(pIdx->aiRowEst); |
| 98532 | pIdx->aiRowEst = 0; |
| 98533 | } |
| 98534 | #endif |
| @@ -100271,10 +100509,11 @@ | |
| 100509 | SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ |
| 100510 | Table *p; |
| 100511 | p = pParse->pNewTable; |
| 100512 | if( p==0 || NEVER(p->nCol<1) ) return; |
| 100513 | p->aCol[p->nCol-1].notNull = (u8)onError; |
| 100514 | p->tabFlags |= TF_HasNotNull; |
| 100515 | } |
| 100516 | |
| 100517 | /* |
| 100518 | ** Scan the column type name zType (length nType) and return the |
| 100519 | ** associated affinity type. |
| @@ -102609,10 +102848,13 @@ | |
| 102848 | /* 10, 9, 8, 7, 6 */ |
| 102849 | LogEst aVal[] = { 33, 32, 30, 28, 26 }; |
| 102850 | LogEst *a = pIdx->aiRowLogEst; |
| 102851 | int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol); |
| 102852 | int i; |
| 102853 | |
| 102854 | /* Indexes with default row estimates should not have stat1 data */ |
| 102855 | assert( !pIdx->hasStat1 ); |
| 102856 | |
| 102857 | /* Set the first entry (number of rows in the index) to the estimated |
| 102858 | ** number of rows in the table, or half the number of rows in the table |
| 102859 | ** for a partial index. But do not let the estimate drop below 10. */ |
| 102860 | a[0] = pIdx->pTable->nRowLogEst; |
| @@ -109798,10 +110040,13 @@ | |
| 110040 | VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); |
| 110041 | } |
| 110042 | } |
| 110043 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); |
| 110044 | VdbeComment((v, "for %s", pIdx->zName)); |
| 110045 | #ifdef SQLITE_ENABLE_NULL_TRIM |
| 110046 | if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable); |
| 110047 | #endif |
| 110048 | |
| 110049 | /* In an UPDATE operation, if this index is the PRIMARY KEY index |
| 110050 | ** of a WITHOUT ROWID table and there has been no change the |
| 110051 | ** primary key, then no collision is possible. The collision detection |
| 110052 | ** logic below can all be skipped. */ |
| @@ -109953,12 +110198,15 @@ | |
| 110198 | |
| 110199 | /* Records with omitted columns are only allowed for schema format |
| 110200 | ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ |
| 110201 | if( pTab->pSchema->file_format<2 ) return; |
| 110202 | |
| 110203 | for(i=pTab->nCol-1; i>0; i--){ |
| 110204 | if( pTab->aCol[i].pDflt!=0 ) break; |
| 110205 | if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; |
| 110206 | } |
| 110207 | sqlite3VdbeChangeP5(v, i+1); |
| 110208 | } |
| 110209 | #endif |
| 110210 | |
| 110211 | /* |
| 110212 | ** This routine generates code to finish the INSERT or UPDATE operation |
| @@ -110244,11 +110492,11 @@ | |
| 110492 | } |
| 110493 | if( sqlite3TriggerList(pParse, pDest) ){ |
| 110494 | return 0; /* tab1 must not have triggers */ |
| 110495 | } |
| 110496 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 110497 | if( IsVirtual(pDest) ){ |
| 110498 | return 0; /* tab1 must not be a virtual table */ |
| 110499 | } |
| 110500 | #endif |
| 110501 | if( onError==OE_Default ){ |
| 110502 | if( pDest->iPKey>=0 ) onError = pDest->keyConf; |
| @@ -110306,11 +110554,11 @@ | |
| 110554 | } |
| 110555 | if( HasRowid(pDest)!=HasRowid(pSrc) ){ |
| 110556 | return 0; /* source and destination must both be WITHOUT ROWID or not */ |
| 110557 | } |
| 110558 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 110559 | if( IsVirtual(pSrc) ){ |
| 110560 | return 0; /* tab2 must not be a virtual table */ |
| 110561 | } |
| 110562 | #endif |
| 110563 | if( pSrc->pSelect ){ |
| 110564 | return 0; /* tab2 may not be a view */ |
| @@ -110603,11 +110851,11 @@ | |
| 110851 | /* Invoke the callback function if required */ |
| 110852 | if( xCallback && (SQLITE_ROW==rc || |
| 110853 | (SQLITE_DONE==rc && !callbackIsInit |
| 110854 | && db->flags&SQLITE_NullCallback)) ){ |
| 110855 | if( !callbackIsInit ){ |
| 110856 | azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*)); |
| 110857 | if( azCols==0 ){ |
| 110858 | goto exec_out; |
| 110859 | } |
| 110860 | for(i=0; i<nCol; i++){ |
| 110861 | azCols[i] = (char *)sqlite3_column_name(pStmt, i); |
| @@ -110624,10 +110872,11 @@ | |
| 110872 | if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 110873 | sqlite3OomFault(db); |
| 110874 | goto exec_out; |
| 110875 | } |
| 110876 | } |
| 110877 | azVals[i] = 0; |
| 110878 | } |
| 110879 | if( xCallback(pArg, nCol, azVals, azCols) ){ |
| 110880 | /* EVIDENCE-OF: R-38229-40159 If the callback function to |
| 110881 | ** sqlite3_exec() returns non-zero, then sqlite3_exec() will |
| 110882 | ** return SQLITE_ABORT. */ |
| @@ -112094,15 +112343,15 @@ | |
| 112343 | #define PragTyp_JOURNAL_SIZE_LIMIT 20 |
| 112344 | #define PragTyp_LOCK_PROXY_FILE 21 |
| 112345 | #define PragTyp_LOCKING_MODE 22 |
| 112346 | #define PragTyp_PAGE_COUNT 23 |
| 112347 | #define PragTyp_MMAP_SIZE 24 |
| 112348 | #define PragTyp_OPTIMIZE 25 |
| 112349 | #define PragTyp_PAGE_SIZE 26 |
| 112350 | #define PragTyp_SECURE_DELETE 27 |
| 112351 | #define PragTyp_SHRINK_MEMORY 28 |
| 112352 | #define PragTyp_SOFT_HEAP_LIMIT 29 |
| 112353 | #define PragTyp_SYNCHRONOUS 30 |
| 112354 | #define PragTyp_TABLE_INFO 31 |
| 112355 | #define PragTyp_TEMP_STORE 32 |
| 112356 | #define PragTyp_TEMP_STORE_DIRECTORY 33 |
| 112357 | #define PragTyp_THREADS 34 |
| @@ -112112,10 +112361,11 @@ | |
| 112361 | #define PragTyp_HEXKEY 38 |
| 112362 | #define PragTyp_KEY 39 |
| 112363 | #define PragTyp_REKEY 40 |
| 112364 | #define PragTyp_LOCK_STATUS 41 |
| 112365 | #define PragTyp_PARSER_TRACE 42 |
| 112366 | #define PragTyp_STATS 43 |
| 112367 | |
| 112368 | /* Property flags associated with various pragma. */ |
| 112369 | #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ |
| 112370 | #define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ |
| 112371 | #define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ |
| @@ -112135,51 +112385,52 @@ | |
| 112385 | /* 2 */ "name", |
| 112386 | /* 3 */ "type", |
| 112387 | /* 4 */ "notnull", |
| 112388 | /* 5 */ "dflt_value", |
| 112389 | /* 6 */ "pk", |
| 112390 | /* 7 */ "tbl", /* Used by: stats */ |
| 112391 | /* 8 */ "idx", |
| 112392 | /* 9 */ "wdth", |
| 112393 | /* 10 */ "hght", |
| 112394 | /* 11 */ "flgs", |
| 112395 | /* 12 */ "seqno", /* Used by: index_info */ |
| 112396 | /* 13 */ "cid", |
| 112397 | /* 14 */ "name", |
| 112398 | /* 15 */ "seqno", /* Used by: index_xinfo */ |
| 112399 | /* 16 */ "cid", |
| 112400 | /* 17 */ "name", |
| 112401 | /* 18 */ "desc", |
| 112402 | /* 19 */ "coll", |
| 112403 | /* 20 */ "key", |
| 112404 | /* 21 */ "seq", /* Used by: index_list */ |
| 112405 | /* 22 */ "name", |
| 112406 | /* 23 */ "unique", |
| 112407 | /* 24 */ "origin", |
| 112408 | /* 25 */ "partial", |
| 112409 | /* 26 */ "seq", /* Used by: database_list */ |
| 112410 | /* 27 */ "name", |
| 112411 | /* 28 */ "file", |
| 112412 | /* 29 */ "seq", /* Used by: collation_list */ |
| 112413 | /* 30 */ "name", |
| 112414 | /* 31 */ "id", /* Used by: foreign_key_list */ |
| 112415 | /* 32 */ "seq", |
| 112416 | /* 33 */ "table", |
| 112417 | /* 34 */ "from", |
| 112418 | /* 35 */ "to", |
| 112419 | /* 36 */ "on_update", |
| 112420 | /* 37 */ "on_delete", |
| 112421 | /* 38 */ "match", |
| 112422 | /* 39 */ "table", /* Used by: foreign_key_check */ |
| 112423 | /* 40 */ "rowid", |
| 112424 | /* 41 */ "parent", |
| 112425 | /* 42 */ "fkid", |
| 112426 | /* 43 */ "busy", /* Used by: wal_checkpoint */ |
| 112427 | /* 44 */ "log", |
| 112428 | /* 45 */ "checkpointed", |
| 112429 | /* 46 */ "timeout", /* Used by: busy_timeout */ |
| 112430 | /* 47 */ "database", /* Used by: lock_status */ |
| 112431 | /* 48 */ "status", |
| 112432 | }; |
| 112433 | |
| 112434 | /* Definitions of all built-in pragmas */ |
| 112435 | typedef struct PragmaName { |
| 112436 | const char *const zName; /* Name of pragma */ |
| @@ -112221,11 +112472,11 @@ | |
| 112472 | #endif |
| 112473 | #endif |
| 112474 | {/* zName: */ "busy_timeout", |
| 112475 | /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, |
| 112476 | /* ePragFlg: */ PragFlg_Result0, |
| 112477 | /* ColNames: */ 46, 1, |
| 112478 | /* iArg: */ 0 }, |
| 112479 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112480 | {/* zName: */ "cache_size", |
| 112481 | /* ePragTyp: */ PragTyp_CACHE_SIZE, |
| 112482 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
| @@ -112258,11 +112509,11 @@ | |
| 112509 | #endif |
| 112510 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112511 | {/* zName: */ "collation_list", |
| 112512 | /* ePragTyp: */ PragTyp_COLLATION_LIST, |
| 112513 | /* ePragFlg: */ PragFlg_Result0, |
| 112514 | /* ColNames: */ 29, 2, |
| 112515 | /* iArg: */ 0 }, |
| 112516 | #endif |
| 112517 | #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) |
| 112518 | {/* zName: */ "compile_options", |
| 112519 | /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, |
| @@ -112293,11 +112544,11 @@ | |
| 112544 | #endif |
| 112545 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112546 | {/* zName: */ "database_list", |
| 112547 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 112548 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, |
| 112549 | /* ColNames: */ 26, 3, |
| 112550 | /* iArg: */ 0 }, |
| 112551 | #endif |
| 112552 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
| 112553 | {/* zName: */ "default_cache_size", |
| 112554 | /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, |
| @@ -112330,18 +112581,18 @@ | |
| 112581 | #endif |
| 112582 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 112583 | {/* zName: */ "foreign_key_check", |
| 112584 | /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, |
| 112585 | /* ePragFlg: */ PragFlg_NeedSchema, |
| 112586 | /* ColNames: */ 39, 4, |
| 112587 | /* iArg: */ 0 }, |
| 112588 | #endif |
| 112589 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) |
| 112590 | {/* zName: */ "foreign_key_list", |
| 112591 | /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, |
| 112592 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112593 | /* ColNames: */ 31, 8, |
| 112594 | /* iArg: */ 0 }, |
| 112595 | #endif |
| 112596 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 112597 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 112598 | {/* zName: */ "foreign_keys", |
| @@ -112400,21 +112651,21 @@ | |
| 112651 | #endif |
| 112652 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 112653 | {/* zName: */ "index_info", |
| 112654 | /* ePragTyp: */ PragTyp_INDEX_INFO, |
| 112655 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112656 | /* ColNames: */ 12, 3, |
| 112657 | /* iArg: */ 0 }, |
| 112658 | {/* zName: */ "index_list", |
| 112659 | /* ePragTyp: */ PragTyp_INDEX_LIST, |
| 112660 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112661 | /* ColNames: */ 21, 5, |
| 112662 | /* iArg: */ 0 }, |
| 112663 | {/* zName: */ "index_xinfo", |
| 112664 | /* ePragTyp: */ PragTyp_INDEX_INFO, |
| 112665 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
| 112666 | /* ColNames: */ 15, 6, |
| 112667 | /* iArg: */ 1 }, |
| 112668 | #endif |
| 112669 | #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) |
| 112670 | {/* zName: */ "integrity_check", |
| 112671 | /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, |
| @@ -112457,11 +112708,11 @@ | |
| 112708 | #endif |
| 112709 | #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| 112710 | {/* zName: */ "lock_status", |
| 112711 | /* ePragTyp: */ PragTyp_LOCK_STATUS, |
| 112712 | /* ePragFlg: */ PragFlg_Result0, |
| 112713 | /* ColNames: */ 47, 2, |
| 112714 | /* iArg: */ 0 }, |
| 112715 | #endif |
| 112716 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112717 | {/* zName: */ "locking_mode", |
| 112718 | /* ePragTyp: */ PragTyp_LOCKING_MODE, |
| @@ -112476,10 +112727,17 @@ | |
| 112727 | {/* zName: */ "mmap_size", |
| 112728 | /* ePragTyp: */ PragTyp_MMAP_SIZE, |
| 112729 | /* ePragFlg: */ 0, |
| 112730 | /* ColNames: */ 0, 0, |
| 112731 | /* iArg: */ 0 }, |
| 112732 | #endif |
| 112733 | {/* zName: */ "optimize", |
| 112734 | /* ePragTyp: */ PragTyp_OPTIMIZE, |
| 112735 | /* ePragFlg: */ PragFlg_Result1, |
| 112736 | /* ColNames: */ 0, 0, |
| 112737 | /* iArg: */ 0 }, |
| 112738 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112739 | {/* zName: */ "page_count", |
| 112740 | /* ePragTyp: */ PragTyp_PAGE_COUNT, |
| 112741 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
| 112742 | /* ColNames: */ 0, 0, |
| 112743 | /* iArg: */ 0 }, |
| @@ -112574,15 +112832,15 @@ | |
| 112832 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
| 112833 | /* ColNames: */ 0, 0, |
| 112834 | /* iArg: */ SQLITE_SqlTrace }, |
| 112835 | #endif |
| 112836 | #endif |
| 112837 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG) |
| 112838 | {/* zName: */ "stats", |
| 112839 | /* ePragTyp: */ PragTyp_STATS, |
| 112840 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
| 112841 | /* ColNames: */ 7, 5, |
| 112842 | /* iArg: */ 0 }, |
| 112843 | #endif |
| 112844 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 112845 | {/* zName: */ "synchronous", |
| 112846 | /* ePragTyp: */ PragTyp_SYNCHRONOUS, |
| @@ -112657,11 +112915,11 @@ | |
| 112915 | /* ColNames: */ 0, 0, |
| 112916 | /* iArg: */ 0 }, |
| 112917 | {/* zName: */ "wal_checkpoint", |
| 112918 | /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, |
| 112919 | /* ePragFlg: */ PragFlg_NeedSchema, |
| 112920 | /* ColNames: */ 43, 3, |
| 112921 | /* iArg: */ 0 }, |
| 112922 | #endif |
| 112923 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 112924 | {/* zName: */ "writable_schema", |
| 112925 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -112668,11 +112926,11 @@ | |
| 112926 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
| 112927 | /* ColNames: */ 0, 0, |
| 112928 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 112929 | #endif |
| 112930 | }; |
| 112931 | /* Number of pragmas: 60 on by default, 74 total. */ |
| 112932 | |
| 112933 | /************** End of pragma.h **********************************************/ |
| 112934 | /************** Continuing where we left off in pragma.c *********************/ |
| 112935 | |
| 112936 | /* |
| @@ -112937,10 +113195,26 @@ | |
| 113195 | lwr = mid + 1; |
| 113196 | } |
| 113197 | } |
| 113198 | return lwr>upr ? 0 : &aPragmaName[mid]; |
| 113199 | } |
| 113200 | |
| 113201 | /* |
| 113202 | ** Helper subroutine for PRAGMA integrity_check: |
| 113203 | ** |
| 113204 | ** Generate code to output a single-column result row with the result |
| 113205 | ** held in register regResult. Decrement the result count and halt if |
| 113206 | ** the maximum number of result rows have been issued. |
| 113207 | */ |
| 113208 | static int integrityCheckResultRow(Vdbe *v, int regResult){ |
| 113209 | int addr; |
| 113210 | sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1); |
| 113211 | addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); |
| 113212 | VdbeCoverage(v); |
| 113213 | sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
| 113214 | return addr; |
| 113215 | } |
| 113216 | |
| 113217 | /* |
| 113218 | ** Process a pragma statement. |
| 113219 | ** |
| 113220 | ** Pragmas are of this form: |
| @@ -113741,33 +114015,37 @@ | |
| 114015 | } |
| 114016 | } |
| 114017 | } |
| 114018 | break; |
| 114019 | |
| 114020 | #ifdef SQLITE_DEBUG |
| 114021 | case PragTyp_STATS: { |
| 114022 | Index *pIdx; |
| 114023 | HashElem *i; |
| 114024 | pParse->nMem = 5; |
| 114025 | sqlite3CodeVerifySchema(pParse, iDb); |
| 114026 | for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ |
| 114027 | Table *pTab = sqliteHashData(i); |
| 114028 | sqlite3VdbeMultiLoad(v, 1, "ssiii", |
| 114029 | pTab->zName, |
| 114030 | 0, |
| 114031 | pTab->szTabRow, |
| 114032 | pTab->nRowLogEst, |
| 114033 | pTab->tabFlags); |
| 114034 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); |
| 114035 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 114036 | sqlite3VdbeMultiLoad(v, 2, "siii", |
| 114037 | pIdx->zName, |
| 114038 | pIdx->szIdxRow, |
| 114039 | pIdx->aiRowLogEst[0], |
| 114040 | pIdx->hasStat1); |
| 114041 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); |
| 114042 | } |
| 114043 | } |
| 114044 | } |
| 114045 | break; |
| 114046 | #endif |
| 114047 | |
| 114048 | case PragTyp_INDEX_INFO: if( zRight ){ |
| 114049 | Index *pIdx; |
| 114050 | Table *pTab; |
| 114051 | pIdx = sqlite3FindIndex(db, zRight, zDb); |
| @@ -114020,13 +114298,21 @@ | |
| 114298 | #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
| 114299 | # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 |
| 114300 | #endif |
| 114301 | |
| 114302 | #ifndef SQLITE_OMIT_INTEGRITY_CHECK |
| 114303 | /* PRAGMA integrity_check |
| 114304 | ** PRAGMA integrity_check(N) |
| 114305 | ** PRAGMA quick_check |
| 114306 | ** PRAGMA quick_check(N) |
| 114307 | ** |
| 114308 | ** Verify the integrity of the database. |
| 114309 | ** |
| 114310 | ** The "quick_check" is reduced version of |
| 114311 | ** integrity_check designed to detect most database corruption |
| 114312 | ** without the overhead of cross-checking indexes. Quick_check |
| 114313 | ** is linear time wherease integrity_check is O(NlogN). |
| 114314 | */ |
| 114315 | case PragTyp_INTEGRITY_CHECK: { |
| 114316 | int i, j, addr, mxErr; |
| 114317 | |
| 114318 | int isQuick = (sqlite3Tolower(zLeft[0])=='q'); |
| @@ -114053,11 +114339,11 @@ | |
| 114339 | sqlite3GetInt32(zRight, &mxErr); |
| 114340 | if( mxErr<=0 ){ |
| 114341 | mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
| 114342 | } |
| 114343 | } |
| 114344 | sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */ |
| 114345 | |
| 114346 | /* Do an integrity check on each database file */ |
| 114347 | for(i=0; i<db->nDb; i++){ |
| 114348 | HashElem *x; |
| 114349 | Hash *pTbls; |
| @@ -114068,14 +114354,10 @@ | |
| 114354 | |
| 114355 | if( OMIT_TEMPDB && i==1 ) continue; |
| 114356 | if( iDb>=0 && i!=iDb ) continue; |
| 114357 | |
| 114358 | sqlite3CodeVerifySchema(pParse, i); |
| 114359 | |
| 114360 | /* Do an integrity check of the B-Tree |
| 114361 | ** |
| 114362 | ** Begin by finding the root pages numbers |
| 114363 | ** for all tables and indices in the database. |
| @@ -114111,29 +114393,30 @@ | |
| 114393 | sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, |
| 114394 | sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), |
| 114395 | P4_DYNAMIC); |
| 114396 | sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); |
| 114397 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); |
| 114398 | integrityCheckResultRow(v, 2); |
| 114399 | sqlite3VdbeJumpHere(v, addr); |
| 114400 | |
| 114401 | /* Make sure all the indices are constructed correctly. |
| 114402 | */ |
| 114403 | for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 114404 | Table *pTab = sqliteHashData(x); |
| 114405 | Index *pIdx, *pPk; |
| 114406 | Index *pPrior = 0; |
| 114407 | int loopTop; |
| 114408 | int iDataCur, iIdxCur; |
| 114409 | int r1 = -1; |
| 114410 | |
| 114411 | if( pTab->pCheck==0 |
| 114412 | && (pTab->tabFlags & TF_HasNotNull)==0 |
| 114413 | && (pTab->pIndex==0 || isQuick) |
| 114414 | ){ |
| 114415 | continue; /* No additional checks needed for this table */ |
| 114416 | } |
| 114417 | pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
| 114418 | sqlite3ExprCacheClear(pParse); |
| 114419 | sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, |
| 114420 | 1, 0, &iDataCur, &iIdxCur); |
| 114421 | sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); |
| 114422 | for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
| @@ -114144,28 +114427,46 @@ | |
| 114427 | sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); |
| 114428 | loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); |
| 114429 | /* Verify that all NOT NULL columns really are NOT NULL */ |
| 114430 | for(j=0; j<pTab->nCol; j++){ |
| 114431 | char *zErr; |
| 114432 | int jmp2; |
| 114433 | if( j==pTab->iPKey ) continue; |
| 114434 | if( pTab->aCol[j].notNull==0 ) continue; |
| 114435 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); |
| 114436 | sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); |
| 114437 | jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); |
| 114438 | zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, |
| 114439 | pTab->aCol[j].zName); |
| 114440 | sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); |
| 114441 | integrityCheckResultRow(v, 3); |
| 114442 | sqlite3VdbeJumpHere(v, jmp2); |
| 114443 | } |
| 114444 | /* Verify CHECK constraints */ |
| 114445 | if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ |
| 114446 | int addrCkFault = sqlite3VdbeMakeLabel(v); |
| 114447 | int addrCkOk = sqlite3VdbeMakeLabel(v); |
| 114448 | ExprList *pCheck = pTab->pCheck; |
| 114449 | char *zErr; |
| 114450 | int k; |
| 114451 | pParse->iSelfTab = iDataCur; |
| 114452 | sqlite3ExprCachePush(pParse); |
| 114453 | for(k=pCheck->nExpr-1; k>0; k--){ |
| 114454 | sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); |
| 114455 | } |
| 114456 | sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, |
| 114457 | SQLITE_JUMPIFNULL); |
| 114458 | sqlite3VdbeResolveLabel(v, addrCkFault); |
| 114459 | zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s", |
| 114460 | pTab->zName); |
| 114461 | sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); |
| 114462 | integrityCheckResultRow(v, 3); |
| 114463 | sqlite3VdbeResolveLabel(v, addrCkOk); |
| 114464 | sqlite3ExprCachePop(pParse); |
| 114465 | } |
| 114466 | /* Validate index entries for the current row */ |
| 114467 | for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){ |
| 114468 | int jmp2, jmp3, jmp4, jmp5; |
| 114469 | int ckUniq = sqlite3VdbeMakeLabel(v); |
| 114470 | if( pPk==pIdx ) continue; |
| 114471 | r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, |
| 114472 | pPrior, r1); |
| @@ -114172,20 +114473,17 @@ | |
| 114473 | pPrior = pIdx; |
| 114474 | sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ |
| 114475 | /* Verify that an index entry exists for the current table row */ |
| 114476 | jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, |
| 114477 | pIdx->nColumn); VdbeCoverage(v); |
| 114478 | sqlite3VdbeLoadString(v, 3, "row "); |
| 114479 | sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); |
| 114480 | sqlite3VdbeLoadString(v, 4, " missing from index "); |
| 114481 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
| 114482 | jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); |
| 114483 | sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
| 114484 | jmp4 = integrityCheckResultRow(v, 3); |
| 114485 | sqlite3VdbeJumpHere(v, jmp2); |
| 114486 | /* For UNIQUE indexes, verify that only one entry exists with the |
| 114487 | ** current key. The entry is unique if (1) any column is NULL |
| 114488 | ** or (2) the next entry has a different key */ |
| 114489 | if( IsUniqueIndex(pIdx) ){ |
| @@ -114202,11 +114500,10 @@ | |
| 114500 | jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
| 114501 | sqlite3VdbeGoto(v, uniqOk); |
| 114502 | sqlite3VdbeJumpHere(v, jmp6); |
| 114503 | sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, |
| 114504 | pIdx->nKeyCol); VdbeCoverage(v); |
| 114505 | sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); |
| 114506 | sqlite3VdbeGoto(v, jmp5); |
| 114507 | sqlite3VdbeResolveLabel(v, uniqOk); |
| 114508 | } |
| 114509 | sqlite3VdbeJumpHere(v, jmp4); |
| @@ -114213,40 +114510,39 @@ | |
| 114510 | sqlite3ResolvePartIdxLabel(pParse, jmp3); |
| 114511 | } |
| 114512 | sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); |
| 114513 | sqlite3VdbeJumpHere(v, loopTop-1); |
| 114514 | #ifndef SQLITE_OMIT_BTREECOUNT |
| 114515 | if( !isQuick ){ |
| 114516 | sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); |
| 114517 | for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
| 114518 | if( pPk==pIdx ) continue; |
| 114519 | sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); |
| 114520 | addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v); |
| 114521 | sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
| 114522 | sqlite3VdbeLoadString(v, 3, pIdx->zName); |
| 114523 | sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); |
| 114524 | integrityCheckResultRow(v, 7); |
| 114525 | sqlite3VdbeJumpHere(v, addr); |
| 114526 | } |
| 114527 | } |
| 114528 | #endif /* SQLITE_OMIT_BTREECOUNT */ |
| 114529 | } |
| 114530 | } |
| 114531 | { |
| 114532 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 114533 | static const VdbeOpList endCode[] = { |
| 114534 | { OP_AddImm, 1, 0, 0}, /* 0 */ |
| 114535 | { OP_IfNotZero, 1, 4, 0}, /* 1 */ |
| 114536 | { OP_String8, 0, 3, 0}, /* 2 */ |
| 114537 | { OP_ResultRow, 3, 1, 0}, /* 3 */ |
| 114538 | }; |
| 114539 | VdbeOp *aOp; |
| 114540 | |
| 114541 | aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
| 114542 | if( aOp ){ |
| 114543 | aOp[0].p2 = 1-mxErr; |
| 114544 | aOp[2].p4type = P4_STATIC; |
| 114545 | aOp[2].p4.z = "ok"; |
| 114546 | } |
| 114547 | } |
| 114548 | } |
| @@ -114466,10 +114762,122 @@ | |
| 114762 | */ |
| 114763 | case PragTyp_SHRINK_MEMORY: { |
| 114764 | sqlite3_db_release_memory(db); |
| 114765 | break; |
| 114766 | } |
| 114767 | |
| 114768 | /* |
| 114769 | ** PRAGMA optimize |
| 114770 | ** PRAGMA optimize(MASK) |
| 114771 | ** PRAGMA schema.optimize |
| 114772 | ** PRAGMA schema.optimize(MASK) |
| 114773 | ** |
| 114774 | ** Attempt to optimize the database. All schemas are optimized in the first |
| 114775 | ** two forms, and only the specified schema is optimized in the latter two. |
| 114776 | ** |
| 114777 | ** The details of optimizations performed by this pragma are expected |
| 114778 | ** to change and improve over time. Applications should anticipate that |
| 114779 | ** this pragma will perform new optimizations in future releases. |
| 114780 | ** |
| 114781 | ** The optional argument is a bitmask of optimizations to perform: |
| 114782 | ** |
| 114783 | ** 0x0001 Debugging mode. Do not actually perform any optimizations |
| 114784 | ** but instead return one line of text for each optimization |
| 114785 | ** that would have been done. Off by default. |
| 114786 | ** |
| 114787 | ** 0x0002 Run ANALYZE on tables that might benefit. On by default. |
| 114788 | ** See below for additional information. |
| 114789 | ** |
| 114790 | ** 0x0004 (Not yet implemented) Record usage and performance |
| 114791 | ** information from the current session in the |
| 114792 | ** database file so that it will be available to "optimize" |
| 114793 | ** pragmas run by future database connections. |
| 114794 | ** |
| 114795 | ** 0x0008 (Not yet implemented) Create indexes that might have |
| 114796 | ** been helpful to recent queries |
| 114797 | ** |
| 114798 | ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all ** of the optimizations listed above except Debug Mode, including new |
| 114799 | ** optimizations that have not yet been invented. If new optimizations are |
| 114800 | ** ever added that should be off by default, those off-by-default |
| 114801 | ** optimizations will have bitmasks of 0x10000 or larger. |
| 114802 | ** |
| 114803 | ** DETERMINATION OF WHEN TO RUN ANALYZE |
| 114804 | ** |
| 114805 | ** In the current implementation, a table is analyzed if only if all of |
| 114806 | ** the following are true: |
| 114807 | ** |
| 114808 | ** (1) MASK bit 0x02 is set. |
| 114809 | ** |
| 114810 | ** (2) The query planner used sqlite_stat1-style statistics for one or |
| 114811 | ** more indexes of the table at some point during the lifetime of |
| 114812 | ** the current connection. |
| 114813 | ** |
| 114814 | ** (3) One or more indexes of the table are currently unanalyzed OR |
| 114815 | ** the number of rows in the table has increased by 25 times or more |
| 114816 | ** since the last time ANALYZE was run. |
| 114817 | ** |
| 114818 | ** The rules for when tables are analyzed are likely to change in |
| 114819 | ** future releases. |
| 114820 | */ |
| 114821 | case PragTyp_OPTIMIZE: { |
| 114822 | int iDbLast; /* Loop termination point for the schema loop */ |
| 114823 | int iTabCur; /* Cursor for a table whose size needs checking */ |
| 114824 | HashElem *k; /* Loop over tables of a schema */ |
| 114825 | Schema *pSchema; /* The current schema */ |
| 114826 | Table *pTab; /* A table in the schema */ |
| 114827 | Index *pIdx; /* An index of the table */ |
| 114828 | LogEst szThreshold; /* Size threshold above which reanalysis is needd */ |
| 114829 | char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ |
| 114830 | u32 opMask; /* Mask of operations to perform */ |
| 114831 | |
| 114832 | if( zRight ){ |
| 114833 | opMask = (u32)sqlite3Atoi(zRight); |
| 114834 | if( (opMask & 0x02)==0 ) break; |
| 114835 | }else{ |
| 114836 | opMask = 0xfffe; |
| 114837 | } |
| 114838 | iTabCur = pParse->nTab++; |
| 114839 | for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){ |
| 114840 | if( iDb==1 ) continue; |
| 114841 | sqlite3CodeVerifySchema(pParse, iDb); |
| 114842 | pSchema = db->aDb[iDb].pSchema; |
| 114843 | for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ |
| 114844 | pTab = (Table*)sqliteHashData(k); |
| 114845 | |
| 114846 | /* If table pTab has not been used in a way that would benefit from |
| 114847 | ** having analysis statistics during the current session, then skip it. |
| 114848 | ** This also has the effect of skipping virtual tables and views */ |
| 114849 | if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue; |
| 114850 | |
| 114851 | /* Reanalyze if the table is 25 times larger than the last analysis */ |
| 114852 | szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 ); |
| 114853 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 114854 | if( !pIdx->hasStat1 ){ |
| 114855 | szThreshold = 0; /* Always analyze if any index lacks statistics */ |
| 114856 | break; |
| 114857 | } |
| 114858 | } |
| 114859 | if( szThreshold ){ |
| 114860 | sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); |
| 114861 | sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur, |
| 114862 | sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold); |
| 114863 | VdbeCoverage(v); |
| 114864 | } |
| 114865 | zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"", |
| 114866 | db->aDb[iDb].zDbSName, pTab->zName); |
| 114867 | if( opMask & 0x01 ){ |
| 114868 | int r1 = sqlite3GetTempReg(pParse); |
| 114869 | sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC); |
| 114870 | sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1); |
| 114871 | }else{ |
| 114872 | sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC); |
| 114873 | } |
| 114874 | } |
| 114875 | } |
| 114876 | sqlite3VdbeAddOp0(v, OP_Expire); |
| 114877 | break; |
| 114878 | } |
| 114879 | |
| 114880 | /* |
| 114881 | ** PRAGMA busy_timeout |
| 114882 | ** PRAGMA busy_timeout = N |
| 114883 | ** |
| @@ -123782,12 +124190,29 @@ | |
| 124190 | ** transient would cause the database file to appear to be deleted |
| 124191 | ** following reboot. |
| 124192 | */ |
| 124193 | SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ |
| 124194 | Vdbe *v = sqlite3GetVdbe(pParse); |
| 124195 | int iDb = 0; |
| 124196 | if( v==0 ) return; |
| 124197 | if( pNm ){ |
| 124198 | #ifndef SQLITE_BUG_COMPATIBLE_20160819 |
| 124199 | /* Default behavior: Report an error if the argument to VACUUM is |
| 124200 | ** not recognized */ |
| 124201 | iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm); |
| 124202 | if( iDb<0 ) return; |
| 124203 | #else |
| 124204 | /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments |
| 124205 | ** to VACUUM are silently ignored. This is a back-out of a bug fix that |
| 124206 | ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270). |
| 124207 | ** The buggy behavior is required for binary compatibility with some |
| 124208 | ** legacy applications. */ |
| 124209 | iDb = sqlite3FindDb(pParse->db, pNm); |
| 124210 | if( iDb<0 ) iDb = 0; |
| 124211 | #endif |
| 124212 | } |
| 124213 | if( iDb!=1 ){ |
| 124214 | sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); |
| 124215 | sqlite3VdbeUsesBtree(v, iDb); |
| 124216 | } |
| 124217 | return; |
| 124218 | } |
| @@ -124377,12 +124802,11 @@ | |
| 124802 | |
| 124803 | db = pParse->db; |
| 124804 | iDb = sqlite3SchemaToIndex(db, pTable->pSchema); |
| 124805 | assert( iDb>=0 ); |
| 124806 | |
| 124807 | assert( pTable->nModuleArg==0 ); |
| 124808 | addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); |
| 124809 | addModuleArgument(db, pTable, 0); |
| 124810 | addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); |
| 124811 | assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) |
| 124812 | || (pParse->sNameToken.z==pName1->z && pName2->z==0) |
| @@ -124666,11 +125090,11 @@ | |
| 125090 | const char *zMod; |
| 125091 | Module *pMod; |
| 125092 | int rc; |
| 125093 | |
| 125094 | assert( pTab ); |
| 125095 | if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){ |
| 125096 | return SQLITE_OK; |
| 125097 | } |
| 125098 | |
| 125099 | /* Locate the required virtual table module */ |
| 125100 | zMod = pTab->azModuleArg[0]; |
| @@ -124736,11 +125160,11 @@ | |
| 125160 | Table *pTab; |
| 125161 | Module *pMod; |
| 125162 | const char *zMod; |
| 125163 | |
| 125164 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); |
| 125165 | assert( pTab && IsVirtual(pTab) && !pTab->pVTable ); |
| 125166 | |
| 125167 | /* Locate the required virtual table module */ |
| 125168 | zMod = pTab->azModuleArg[0]; |
| 125169 | pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); |
| 125170 | |
| @@ -124790,11 +125214,11 @@ | |
| 125214 | sqlite3Error(db, SQLITE_MISUSE); |
| 125215 | sqlite3_mutex_leave(db->mutex); |
| 125216 | return SQLITE_MISUSE_BKPT; |
| 125217 | } |
| 125218 | pTab = pCtx->pTab; |
| 125219 | assert( IsVirtual(pTab) ); |
| 125220 | |
| 125221 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 125222 | if( pParse==0 ){ |
| 125223 | rc = SQLITE_NOMEM_BKPT; |
| 125224 | }else{ |
| @@ -124804,11 +125228,11 @@ | |
| 125228 | |
| 125229 | if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) |
| 125230 | && pParse->pNewTable |
| 125231 | && !db->mallocFailed |
| 125232 | && !pParse->pNewTable->pSelect |
| 125233 | && !IsVirtual(pParse->pNewTable) |
| 125234 | ){ |
| 125235 | if( !pTab->aCol ){ |
| 125236 | Table *pNew = pParse->pNewTable; |
| 125237 | Index *pIdx; |
| 125238 | pTab->aCol = pNew->aCol; |
| @@ -125093,11 +125517,11 @@ | |
| 125517 | /* Check to see the left operand is a column in a virtual table */ |
| 125518 | if( NEVER(pExpr==0) ) return pDef; |
| 125519 | if( pExpr->op!=TK_COLUMN ) return pDef; |
| 125520 | pTab = pExpr->pTab; |
| 125521 | if( NEVER(pTab==0) ) return pDef; |
| 125522 | if( !IsVirtual(pTab) ) return pDef; |
| 125523 | pVtab = sqlite3GetVTable(db, pTab)->pVtab; |
| 125524 | assert( pVtab!=0 ); |
| 125525 | assert( pVtab->pModule!=0 ); |
| 125526 | pMod = (sqlite3_module *)pVtab->pModule; |
| 125527 | if( pMod->xFindFunction==0 ) return pDef; |
| @@ -125188,12 +125612,11 @@ | |
| 125612 | return 0; |
| 125613 | } |
| 125614 | pMod->pEpoTab = pTab; |
| 125615 | pTab->nTabRef = 1; |
| 125616 | pTab->pSchema = db->aDb[0].pSchema; |
| 125617 | assert( pTab->nModuleArg==0 ); |
| 125618 | pTab->iPKey = -1; |
| 125619 | addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
| 125620 | addModuleArgument(db, pTab, 0); |
| 125621 | addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
| 125622 | rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); |
| @@ -125260,11 +125683,11 @@ | |
| 125683 | case SQLITE_VTAB_CONSTRAINT_SUPPORT: { |
| 125684 | VtabCtx *p = db->pVtabCtx; |
| 125685 | if( !p ){ |
| 125686 | rc = SQLITE_MISUSE_BKPT; |
| 125687 | }else{ |
| 125688 | assert( p->pTab==0 || IsVirtual(p->pTab) ); |
| 125689 | p->pVTable->bConstraint = (u8)va_arg(ap, int); |
| 125690 | } |
| 125691 | break; |
| 125692 | } |
| 125693 | default: |
| @@ -125699,12 +126122,17 @@ | |
| 126122 | WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ |
| 126123 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 126124 | UnpackedRecord *pRec; /* Probe for stat4 (if required) */ |
| 126125 | int nRecValid; /* Number of valid fields currently in pRec */ |
| 126126 | #endif |
| 126127 | unsigned int bldFlags; /* SQLITE_BLDF_* flags */ |
| 126128 | }; |
| 126129 | |
| 126130 | /* Allowed values for WhereLoopBuider.bldFlags */ |
| 126131 | #define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ |
| 126132 | #define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ |
| 126133 | |
| 126134 | /* |
| 126135 | ** The WHERE clause processing routine has two halves. The |
| 126136 | ** first part does the start of the WHERE loop and the second |
| 126137 | ** half does the tail of the WHERE loop. An instance of |
| 126138 | ** this structure is returned by the first half and passed |
| @@ -125715,11 +126143,11 @@ | |
| 126143 | */ |
| 126144 | struct WhereInfo { |
| 126145 | Parse *pParse; /* Parsing and code generating context */ |
| 126146 | SrcList *pTabList; /* List of tables in the join */ |
| 126147 | ExprList *pOrderBy; /* The ORDER BY clause or NULL */ |
| 126148 | ExprList *pResultSet; /* Result set of the query */ |
| 126149 | LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ |
| 126150 | int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ |
| 126151 | int iContinue; /* Jump here to continue with next record */ |
| 126152 | int iBreak; /* Jump here to break out of the loop */ |
| 126153 | int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ |
| @@ -126899,10 +127327,11 @@ | |
| 127327 | Parse *pParse; /* Parsing context */ |
| 127328 | sqlite3 *db; /* Database connection */ |
| 127329 | Vdbe *v; /* The prepared stmt under constructions */ |
| 127330 | struct SrcList_item *pTabItem; /* FROM clause term being coded */ |
| 127331 | int addrBrk; /* Jump here to break out of the loop */ |
| 127332 | int addrHalt; /* addrBrk for the outermost loop */ |
| 127333 | int addrCont; /* Jump here to continue with next cycle */ |
| 127334 | int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ |
| 127335 | int iReleaseReg = 0; /* Temp register to free before returning */ |
| 127336 | |
| 127337 | pParse = pWInfo->pParse; |
| @@ -126939,10 +127368,15 @@ | |
| 127368 | if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ |
| 127369 | pLevel->iLeftJoin = ++pParse->nMem; |
| 127370 | sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); |
| 127371 | VdbeComment((v, "init LEFT JOIN no-match flag")); |
| 127372 | } |
| 127373 | |
| 127374 | /* Compute a safe address to jump to if we discover that the table for |
| 127375 | ** this loop is empty and can never contribute content. */ |
| 127376 | for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){} |
| 127377 | addrHalt = pWInfo->a[j].addrBrk; |
| 127378 | |
| 127379 | /* Special case of a FROM clause subquery implemented as a co-routine */ |
| 127380 | if( pTabItem->fg.viaCoroutine ){ |
| 127381 | int regYield = pTabItem->regReturn; |
| 127382 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); |
| @@ -127124,11 +127558,11 @@ | |
| 127558 | VdbeCoverageIf(v, pX->op==TK_LT); |
| 127559 | VdbeCoverageIf(v, pX->op==TK_GE); |
| 127560 | sqlite3ExprCacheAffinityChange(pParse, r1, 1); |
| 127561 | sqlite3ReleaseTempReg(pParse, rTemp); |
| 127562 | }else{ |
| 127563 | sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); |
| 127564 | VdbeCoverageIf(v, bRev==0); |
| 127565 | VdbeCoverageIf(v, bRev!=0); |
| 127566 | } |
| 127567 | if( pEnd ){ |
| 127568 | Expr *pX; |
| @@ -127770,11 +128204,11 @@ | |
| 128204 | pLevel->op = OP_Noop; |
| 128205 | }else{ |
| 128206 | codeCursorHint(pTabItem, pWInfo, pLevel, 0); |
| 128207 | pLevel->op = aStep[bRev]; |
| 128208 | pLevel->p1 = iCur; |
| 128209 | pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt); |
| 128210 | VdbeCoverageIf(v, bRev==0); |
| 128211 | VdbeCoverageIf(v, bRev!=0); |
| 128212 | pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; |
| 128213 | } |
| 128214 | } |
| @@ -128095,19 +128529,10 @@ | |
| 128529 | #ifdef SQLITE_EBCDIC |
| 128530 | if( *pnoCase ) return 0; |
| 128531 | #endif |
| 128532 | pList = pExpr->x.pList; |
| 128533 | pLeft = pList->a[1].pExpr; |
| 128534 | |
| 128535 | pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); |
| 128536 | op = pRight->op; |
| 128537 | if( op==TK_VARIABLE ){ |
| 128538 | Vdbe *pReprepare = pParse->pReprepare; |
| @@ -128120,10 +128545,27 @@ | |
| 128545 | assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); |
| 128546 | }else if( op==TK_STRING ){ |
| 128547 | z = pRight->u.zToken; |
| 128548 | } |
| 128549 | if( z ){ |
| 128550 | |
| 128551 | /* If the RHS begins with a digit or a minus sign, then the LHS must |
| 128552 | ** be an ordinary column (not a virtual table column) with TEXT affinity. |
| 128553 | ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false |
| 128554 | ** even though "lhs LIKE rhs" is true. But if the RHS does not start |
| 128555 | ** with a digit or '-', then "lhs LIKE rhs" will always be false if |
| 128556 | ** the LHS is numeric and so the optimization still works. |
| 128557 | */ |
| 128558 | if( sqlite3Isdigit(z[0]) || z[0]=='-' ){ |
| 128559 | if( pLeft->op!=TK_COLUMN |
| 128560 | || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT |
| 128561 | || IsVirtual(pLeft->pTab) /* Value might be numeric */ |
| 128562 | ){ |
| 128563 | sqlite3ValueFree(pVal); |
| 128564 | return 0; |
| 128565 | } |
| 128566 | } |
| 128567 | cnt = 0; |
| 128568 | while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ |
| 128569 | cnt++; |
| 128570 | } |
| 128571 | if( cnt!=0 && 255!=(u8)z[cnt-1] ){ |
| @@ -128748,11 +129190,11 @@ | |
| 129190 | iCur = pFrom->a[i].iCursor; |
| 129191 | for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 129192 | if( pIdx->aColExpr==0 ) continue; |
| 129193 | for(i=0; i<pIdx->nKeyCol; i++){ |
| 129194 | if( pIdx->aiColumn[i]!=XN_EXPR ) continue; |
| 129195 | if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ |
| 129196 | *piCur = iCur; |
| 129197 | *piColumn = XN_EXPR; |
| 129198 | return 1; |
| 129199 | } |
| 129200 | } |
| @@ -129539,11 +129981,12 @@ | |
| 129981 | do{ |
| 129982 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 129983 | if( pTerm->leftCursor==iCur |
| 129984 | && pTerm->u.leftColumn==iColumn |
| 129985 | && (iColumn!=XN_EXPR |
| 129986 | || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, |
| 129987 | pScan->pIdxExpr,iCur)==0) |
| 129988 | && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) |
| 129989 | ){ |
| 129990 | if( (pTerm->eOperator & WO_EQUIV)!=0 |
| 129991 | && pScan->nEquiv<ArraySize(pScan->aiCur) |
| 129992 | && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN |
| @@ -131716,10 +132159,15 @@ | |
| 132159 | testcase( eOp & WO_IS ); |
| 132160 | testcase( eOp & WO_ISNULL ); |
| 132161 | continue; |
| 132162 | } |
| 132163 | |
| 132164 | if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ |
| 132165 | pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; |
| 132166 | }else{ |
| 132167 | pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; |
| 132168 | } |
| 132169 | pNew->wsFlags = saved_wsFlags; |
| 132170 | pNew->u.btree.nEq = saved_nEq; |
| 132171 | pNew->u.btree.nBtm = saved_nBtm; |
| 132172 | pNew->u.btree.nTop = saved_nTop; |
| 132173 | pNew->nLTerm = saved_nLTerm; |
| @@ -132263,11 +132711,19 @@ | |
| 132711 | pNew->nOut = rSize; |
| 132712 | if( rc ) break; |
| 132713 | } |
| 132714 | } |
| 132715 | |
| 132716 | pBuilder->bldFlags = 0; |
| 132717 | rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); |
| 132718 | if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){ |
| 132719 | /* If a non-unique index is used, or if a prefix of the key for |
| 132720 | ** unique index is used (making the index functionally non-unique) |
| 132721 | ** then the sqlite_stat1 data becomes important for scoring the |
| 132722 | ** plan */ |
| 132723 | pTab->tabFlags |= TF_StatsUsed; |
| 132724 | } |
| 132725 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 132726 | sqlite3Stat4ProbeFree(pBuilder->pRec); |
| 132727 | pBuilder->nRecValid = 0; |
| 132728 | pBuilder->pRec = 0; |
| 132729 | #endif |
| @@ -133443,13 +133899,13 @@ | |
| 133899 | && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 |
| 133900 | && pWInfo->eDistinct==WHERE_DISTINCT_NOOP |
| 133901 | && nRowEst |
| 133902 | ){ |
| 133903 | Bitmask notUsed; |
| 133904 | int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, |
| 133905 | WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); |
| 133906 | if( rc==pWInfo->pResultSet->nExpr ){ |
| 133907 | pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; |
| 133908 | } |
| 133909 | } |
| 133910 | if( pWInfo->pOrderBy ){ |
| 133911 | if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ |
| @@ -133682,11 +134138,11 @@ | |
| 134138 | SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( |
| 134139 | Parse *pParse, /* The parser context */ |
| 134140 | SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ |
| 134141 | Expr *pWhere, /* The WHERE clause */ |
| 134142 | ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ |
| 134143 | ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ |
| 134144 | u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ |
| 134145 | int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number |
| 134146 | ** If WHERE_USE_LIMIT, then the limit amount */ |
| 134147 | ){ |
| 134148 | int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ |
| @@ -133758,11 +134214,11 @@ | |
| 134214 | goto whereBeginError; |
| 134215 | } |
| 134216 | pWInfo->pParse = pParse; |
| 134217 | pWInfo->pTabList = pTabList; |
| 134218 | pWInfo->pOrderBy = pOrderBy; |
| 134219 | pWInfo->pResultSet = pResultSet; |
| 134220 | pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; |
| 134221 | pWInfo->nLevel = nTabList; |
| 134222 | pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); |
| 134223 | pWInfo->wctrlFlags = wctrlFlags; |
| 134224 | pWInfo->iLimit = iAuxArg; |
| @@ -133836,17 +134292,17 @@ | |
| 134292 | /* Analyze all of the subexpressions. */ |
| 134293 | sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); |
| 134294 | if( db->mallocFailed ) goto whereBeginError; |
| 134295 | |
| 134296 | if( wctrlFlags & WHERE_WANT_DISTINCT ){ |
| 134297 | if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ |
| 134298 | /* The DISTINCT marking is pointless. Ignore it. */ |
| 134299 | pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; |
| 134300 | }else if( pOrderBy==0 ){ |
| 134301 | /* Try to ORDER BY the result set to make distinct processing easier */ |
| 134302 | pWInfo->wctrlFlags |= WHERE_DISTINCTBY; |
| 134303 | pWInfo->pOrderBy = pResultSet; |
| 134304 | } |
| 134305 | } |
| 134306 | |
| 134307 | /* Construct the WhereLoop objects */ |
| 134308 | #if defined(WHERETRACE_ENABLED) |
| @@ -133918,14 +134374,14 @@ | |
| 134374 | } |
| 134375 | } |
| 134376 | #endif |
| 134377 | /* Attempt to omit tables from the join that do not effect the result */ |
| 134378 | if( pWInfo->nLevel>=2 |
| 134379 | && pResultSet!=0 |
| 134380 | && OptimizationEnabled(db, SQLITE_OmitNoopJoin) |
| 134381 | ){ |
| 134382 | Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); |
| 134383 | if( sWLB.pOrderBy ){ |
| 134384 | tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); |
| 134385 | } |
| 134386 | while( pWInfo->nLevel>=2 ){ |
| 134387 | WhereTerm *pTerm, *pEnd; |
| @@ -134704,166 +135160,166 @@ | |
| 135160 | ** |
| 135161 | *********** Begin parsing tables **********************************************/ |
| 135162 | #define YY_ACTTAB_COUNT (1567) |
| 135163 | static const YYACTIONTYPE yy_action[] = { |
| 135164 | /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100, |
| 135165 | /* 10 */ 90, 978, 978, 853, 856, 845, 845, 97, 97, 98, |
| 135166 | /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, |
| 135167 | /* 30 */ 94, 94, 94, 93, 351, 325, 976, 976, 824, 824, |
| 135168 | /* 40 */ 826, 946, 354, 99, 100, 90, 978, 978, 853, 856, |
| 135169 | /* 50 */ 845, 845, 97, 97, 98, 98, 98, 98, 338, 96, |
| 135170 | /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 135171 | /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 976, 976, |
| 135172 | /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100, |
| 135173 | /* 90 */ 90, 978, 978, 853, 856, 845, 845, 97, 97, 98, |
| 135174 | /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, |
| 135175 | /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325, |
| 135176 | /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, |
| 135177 | /* 130 */ 978, 978, 853, 856, 845, 845, 97, 97, 98, 98, |
| 135178 | /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, |
| 135179 | /* 150 */ 94, 94, 93, 351, 957, 957, 325, 268, 428, 413, |
| 135180 | /* 160 */ 411, 61, 752, 752, 99, 100, 90, 978, 978, 853, |
| 135181 | /* 170 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 60, |
| 135182 | /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 135183 | /* 190 */ 351, 325, 270, 329, 273, 277, 958, 959, 250, 99, |
| 135184 | /* 200 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, |
| 135185 | /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, |
| 135186 | /* 220 */ 95, 94, 94, 94, 93, 351, 325, 937, 1326, 698, |
| 135187 | /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 978, 978, 853, |
| 135188 | /* 240 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 347, |
| 135189 | /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 135190 | /* 260 */ 351, 325, 937, 1327, 384, 699, 1327, 381, 379, 99, |
| 135191 | /* 270 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, |
| 135192 | /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95, |
| 135193 | /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, |
| 135194 | /* 300 */ 833, 935, 373, 700, 99, 100, 90, 978, 978, 853, |
| 135195 | /* 310 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 375, |
| 135196 | /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 135197 | /* 330 */ 351, 325, 1275, 946, 354, 818, 935, 739, 739, 99, |
| 135198 | /* 340 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, |
| 135199 | /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, |
| 135200 | /* 360 */ 95, 94, 94, 94, 93, 351, 325, 968, 227, 92, |
| 135201 | /* 370 */ 89, 178, 373, 300, 99, 100, 90, 978, 978, 853, |
| 135202 | /* 380 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 920, |
| 135203 | /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 135204 | /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99, |
| 135205 | /* 410 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, |
| 135206 | /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, |
| 135207 | /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 957, |
| 135208 | /* 440 */ 957, 158, 25, 422, 99, 100, 90, 978, 978, 853, |
| 135209 | /* 450 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 450, |
| 135210 | /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 135211 | /* 470 */ 351, 443, 224, 224, 420, 957, 957, 961, 325, 52, |
| 135212 | /* 480 */ 52, 958, 959, 176, 415, 78, 99, 100, 90, 978, |
| 135213 | /* 490 */ 978, 853, 856, 845, 845, 97, 97, 98, 98, 98, |
| 135214 | /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, |
| 135215 | /* 510 */ 94, 93, 351, 325, 428, 418, 298, 958, 959, 961, |
| 135216 | /* 520 */ 81, 99, 88, 90, 978, 978, 853, 856, 845, 845, |
| 135217 | /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96, |
| 135218 | /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 842, |
| 135219 | /* 550 */ 842, 854, 857, 996, 318, 343, 379, 100, 90, 978, |
| 135220 | /* 560 */ 978, 853, 856, 845, 845, 97, 97, 98, 98, 98, |
| 135221 | /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, |
| 135222 | /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, |
| 135223 | /* 590 */ 928, 52, 52, 90, 978, 978, 853, 856, 845, 845, |
| 135224 | /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, |
| 135225 | /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, |
| 135226 | /* 620 */ 846, 3, 1202, 361, 360, 378, 344, 813, 957, 957, |
| 135227 | /* 630 */ 1299, 86, 445, 729, 3, 212, 169, 287, 405, 282, |
| 135228 | /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245, |
| 135229 | /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, |
| 135230 | /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, |
| 135231 | /* 670 */ 958, 959, 194, 455, 670, 402, 399, 398, 448, 243, |
| 135232 | /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224, |
| 135233 | /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427, |
| 135234 | /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452, |
| 135235 | /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1270, |
| 135236 | /* 720 */ 1270, 23, 957, 957, 86, 445, 397, 3, 228, 429, |
| 135237 | /* 730 */ 894, 824, 824, 826, 827, 19, 203, 720, 52, 52, |
| 135238 | /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229, |
| 135239 | /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85, |
| 135240 | /* 760 */ 352, 352, 120, 157, 958, 959, 58, 976, 409, 355, |
| 135241 | /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86, |
| 135242 | /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96, |
| 135243 | /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 135244 | /* 800 */ 832, 120, 452, 451, 813, 886, 819, 83, 84, 976, |
| 135245 | /* 810 */ 813, 132, 410, 919, 85, 352, 352, 132, 407, 789, |
| 135246 | /* 820 */ 957, 957, 92, 89, 178, 916, 448, 262, 370, 261, |
| 135247 | /* 830 */ 82, 913, 80, 262, 370, 261, 776, 824, 824, 826, |
| 135248 | /* 840 */ 827, 19, 933, 434, 96, 96, 96, 96, 95, 95, |
| 135249 | /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 957, |
| 135250 | /* 860 */ 957, 819, 958, 959, 120, 92, 89, 178, 944, 2, |
| 135251 | /* 870 */ 917, 964, 268, 1, 975, 76, 445, 762, 3, 708, |
| 135252 | /* 880 */ 900, 900, 387, 957, 957, 757, 918, 371, 740, 778, |
| 135253 | /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450, |
| 135254 | /* 900 */ 24, 958, 959, 83, 84, 369, 957, 957, 177, 226, |
| 135255 | /* 910 */ 85, 352, 352, 884, 315, 314, 313, 215, 311, 10, |
| 135256 | /* 920 */ 10, 683, 448, 349, 348, 958, 959, 908, 777, 157, |
| 135257 | /* 930 */ 120, 957, 957, 337, 776, 416, 711, 310, 450, 434, |
| 135258 | /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 958, 959, |
| 135259 | /* 950 */ 907, 832, 792, 452, 451, 9, 9, 819, 10, 10, |
| 135260 | /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171, |
| 135261 | /* 970 */ 170, 167, 339, 958, 959, 247, 984, 702, 702, 450, |
| 135262 | /* 980 */ 715, 233, 686, 982, 888, 983, 182, 913, 824, 824, |
| 135263 | /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10, |
| 135264 | /* 1000 */ 10, 888, 890, 749, 957, 957, 916, 268, 985, 198, |
| 135265 | /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825, |
| 135266 | /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91, |
| 135267 | /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 135268 | /* 1040 */ 351, 157, 810, 371, 382, 359, 958, 959, 358, 268, |
| 135269 | /* 1050 */ 450, 917, 368, 324, 824, 824, 826, 450, 709, 450, |
| 135270 | /* 1060 */ 264, 380, 888, 450, 876, 746, 253, 918, 255, 433, |
| 135271 | /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12, |
| 135272 | /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162, |
| 135273 | /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450, |
| 135274 | /* 1100 */ 709, 1209, 450, 132, 450, 39, 39, 450, 40, 40, |
| 135275 | /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28, |
| 135276 | /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450, |
| 135277 | /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767, |
| 135278 | /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47, |
| 135279 | /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172, |
| 135280 | /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122, |
| 135281 | /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 897, 56, 56, |
| 135282 | /* 1180 */ 450, 896, 35, 35, 450, 267, 450, 817, 450, 817, |
| 135283 | /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817, |
| 135284 | /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119, |
| 135285 | /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111, |
| 135286 | /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 911, |
| 135287 | /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331, |
| 135288 | /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 936, 197, |
| 135289 | /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436, |
| 135290 | /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 932, |
| 135291 | /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202, |
| 135292 | /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 883, |
| 135293 | /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74, |
| 135294 | /* 1300 */ 726, 727, 785, 783, 879, 202, 999, 208, 893, 892, |
| 135295 | /* 1310 */ 893, 892, 694, 816, 763, 116, 774, 1289, 431, 432, |
| 135296 | /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289, |
| 135297 | /* 1330 */ 679, 883, 681, 951, 291, 218, 293, 7, 316, 828, |
| 135298 | /* 1340 */ 173, 805, 259, 364, 252, 910, 376, 713, 295, 435, |
| 135299 | /* 1350 */ 308, 168, 954, 993, 135, 400, 990, 284, 881, 880, |
| 135300 | /* 1360 */ 205, 927, 925, 59, 333, 62, 144, 156, 130, 72, |
| 135301 | /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383, |
| 135302 | /* 1380 */ 67, 895, 140, 141, 142, 148, 389, 812, 775, 266, |
| 135303 | /* 1390 */ 219, 190, 154, 391, 912, 875, 271, 406, 191, 322, |
| 135304 | /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421, |
| 135305 | /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346, |
| 135306 | /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 966, 239, |
| 135307 | /* 1430 */ 769, 102, 861, 438, 426, 240, 424, 442, 73, 213, |
| 135308 | /* 1440 */ 688, 238, 22, 453, 952, 214, 217, 216, 454, 677, |
| 135309 | /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166, |
| 135310 | /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 891, |
| 135311 | /* 1470 */ 327, 889, 811, 328, 134, 128, 136, 138, 743, 258, |
| 135312 | /* 1480 */ 906, 184, 143, 129, 909, 186, 63, 64, 145, 187, |
| 135313 | /* 1490 */ 905, 65, 8, 66, 13, 188, 202, 898, 265, 149, |
| 135314 | /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396, |
| 135315 | /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131, |
| 135316 | /* 1520 */ 830, 859, 70, 751, 16, 414, 755, 4, 174, 220, |
| 135317 | /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 874, |
| 135318 | /* 1540 */ 860, 858, 915, 863, 914, 207, 206, 941, 163, 437, |
| 135319 | /* 1550 */ 947, 942, 164, 209, 1002, 441, 862, 165, 210, 829, |
| 135320 | /* 1560 */ 695, 87, 312, 211, 1291, 1290, 309, |
| 135321 | }; |
| 135322 | static const YYCODETYPE yy_lookahead[] = { |
| 135323 | /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, |
| 135324 | /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
| 135325 | /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, |
| @@ -135112,55 +135568,55 @@ | |
| 135568 | /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278, |
| 135569 | /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228, |
| 135570 | /* 320 */ 1288, 1291, 1276, 1277, 1295, |
| 135571 | }; |
| 135572 | static const YYACTIONTYPE yy_default[] = { |
| 135573 | /* 0 */ 1280, 1270, 1270, 1270, 1202, 1202, 1202, 1202, 1270, 1096, |
| 135574 | /* 10 */ 1125, 1125, 1254, 1332, 1332, 1332, 1332, 1332, 1332, 1201, |
| 135575 | /* 20 */ 1332, 1332, 1332, 1332, 1270, 1100, 1131, 1332, 1332, 1332, |
| 135576 | /* 30 */ 1332, 1203, 1204, 1332, 1332, 1332, 1253, 1255, 1141, 1140, |
| 135577 | /* 40 */ 1139, 1138, 1236, 1112, 1136, 1129, 1133, 1203, 1197, 1198, |
| 135578 | /* 50 */ 1196, 1200, 1204, 1332, 1132, 1167, 1181, 1166, 1332, 1332, |
| 135579 | /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135580 | /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135581 | /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135582 | /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135583 | /* 100 */ 1332, 1332, 1332, 1332, 1175, 1180, 1187, 1179, 1176, 1169, |
| 135584 | /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, |
| 135585 | /* 120 */ 1332, 1173, 1184, 1183, 1182, 1261, 1288, 1287, 1332, 1332, |
| 135586 | /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135587 | /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135588 | /* 150 */ 1332, 1332, 1332, 1332, 1332, 1280, 1270, 1025, 1025, 1332, |
| 135589 | /* 160 */ 1270, 1270, 1270, 1270, 1270, 1270, 1266, 1100, 1091, 1332, |
| 135590 | /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135591 | /* 180 */ 1258, 1256, 1332, 1217, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135592 | /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135593 | /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, |
| 135594 | /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1282, 1332, 1231, |
| 135595 | /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, |
| 135596 | /* 230 */ 1321, 1135, 1321, 1042, 1302, 1039, 1125, 1114, 1199, 1125, |
| 135597 | /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, |
| 135598 | /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, |
| 135599 | /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1235, 1318, 1105, 1105, |
| 135600 | /* 270 */ 1016, 1210, 1105, 1016, 1105, 1016, 1210, 1068, 1068, 1068, |
| 135601 | /* 280 */ 1057, 1210, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, |
| 135602 | /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1205, 1105, 1332, |
| 135603 | /* 300 */ 1210, 1214, 1214, 1210, 1130, 1119, 1128, 1126, 1135, 1022, |
| 135604 | /* 310 */ 1060, 1285, 1285, 1281, 1281, 1281, 1281, 1329, 1329, 1266, |
| 135605 | /* 320 */ 1297, 1297, 1044, 1044, 1297, 1332, 1332, 1332, 1332, 1332, |
| 135606 | /* 330 */ 1332, 1292, 1332, 1219, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135607 | /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135608 | /* 350 */ 1332, 1332, 1152, 1332, 1000, 1263, 1332, 1332, 1262, 1332, |
| 135609 | /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135610 | /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, |
| 135611 | /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1234, 1233, 1332, 1332, |
| 135612 | /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135613 | /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 135614 | /* 410 */ 1332, 1082, 1332, 1332, 1332, 1306, 1332, 1332, 1332, 1332, |
| 135615 | /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, |
| 135616 | /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1272, |
| 135617 | /* 440 */ 1332, 1332, 1332, 1271, 1332, 1332, 1332, 1332, 1332, 1154, |
| 135618 | /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, |
| 135619 | }; |
| 135620 | /********** End of lemon-generated parsing tables *****************************/ |
| 135621 | |
| 135622 | /* The next table maps tokens (terminal symbols) into fallback tokens. |
| @@ -135602,147 +136058,147 @@ | |
| 136058 | /* 169 */ "expr ::= expr EQ|NE expr", |
| 136059 | /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", |
| 136060 | /* 171 */ "expr ::= expr PLUS|MINUS expr", |
| 136061 | /* 172 */ "expr ::= expr STAR|SLASH|REM expr", |
| 136062 | /* 173 */ "expr ::= expr CONCAT expr", |
| 136063 | /* 174 */ "likeop ::= NOT LIKE_KW|MATCH", |
| 136064 | /* 175 */ "expr ::= expr likeop expr", |
| 136065 | /* 176 */ "expr ::= expr likeop expr ESCAPE expr", |
| 136066 | /* 177 */ "expr ::= expr ISNULL|NOTNULL", |
| 136067 | /* 178 */ "expr ::= expr NOT NULL", |
| 136068 | /* 179 */ "expr ::= expr IS expr", |
| 136069 | /* 180 */ "expr ::= expr IS NOT expr", |
| 136070 | /* 181 */ "expr ::= NOT expr", |
| 136071 | /* 182 */ "expr ::= BITNOT expr", |
| 136072 | /* 183 */ "expr ::= MINUS expr", |
| 136073 | /* 184 */ "expr ::= PLUS expr", |
| 136074 | /* 185 */ "between_op ::= BETWEEN", |
| 136075 | /* 186 */ "between_op ::= NOT BETWEEN", |
| 136076 | /* 187 */ "expr ::= expr between_op expr AND expr", |
| 136077 | /* 188 */ "in_op ::= IN", |
| 136078 | /* 189 */ "in_op ::= NOT IN", |
| 136079 | /* 190 */ "expr ::= expr in_op LP exprlist RP", |
| 136080 | /* 191 */ "expr ::= LP select RP", |
| 136081 | /* 192 */ "expr ::= expr in_op LP select RP", |
| 136082 | /* 193 */ "expr ::= expr in_op nm dbnm paren_exprlist", |
| 136083 | /* 194 */ "expr ::= EXISTS LP select RP", |
| 136084 | /* 195 */ "expr ::= CASE case_operand case_exprlist case_else END", |
| 136085 | /* 196 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", |
| 136086 | /* 197 */ "case_exprlist ::= WHEN expr THEN expr", |
| 136087 | /* 198 */ "case_else ::= ELSE expr", |
| 136088 | /* 199 */ "case_else ::=", |
| 136089 | /* 200 */ "case_operand ::= expr", |
| 136090 | /* 201 */ "case_operand ::=", |
| 136091 | /* 202 */ "exprlist ::=", |
| 136092 | /* 203 */ "nexprlist ::= nexprlist COMMA expr", |
| 136093 | /* 204 */ "nexprlist ::= expr", |
| 136094 | /* 205 */ "paren_exprlist ::=", |
| 136095 | /* 206 */ "paren_exprlist ::= LP exprlist RP", |
| 136096 | /* 207 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", |
| 136097 | /* 208 */ "uniqueflag ::= UNIQUE", |
| 136098 | /* 209 */ "uniqueflag ::=", |
| 136099 | /* 210 */ "eidlist_opt ::=", |
| 136100 | /* 211 */ "eidlist_opt ::= LP eidlist RP", |
| 136101 | /* 212 */ "eidlist ::= eidlist COMMA nm collate sortorder", |
| 136102 | /* 213 */ "eidlist ::= nm collate sortorder", |
| 136103 | /* 214 */ "collate ::=", |
| 136104 | /* 215 */ "collate ::= COLLATE ID|STRING", |
| 136105 | /* 216 */ "cmd ::= DROP INDEX ifexists fullname", |
| 136106 | /* 217 */ "cmd ::= VACUUM", |
| 136107 | /* 218 */ "cmd ::= VACUUM nm", |
| 136108 | /* 219 */ "cmd ::= PRAGMA nm dbnm", |
| 136109 | /* 220 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", |
| 136110 | /* 221 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", |
| 136111 | /* 222 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", |
| 136112 | /* 223 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", |
| 136113 | /* 224 */ "plus_num ::= PLUS INTEGER|FLOAT", |
| 136114 | /* 225 */ "minus_num ::= MINUS INTEGER|FLOAT", |
| 136115 | /* 226 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", |
| 136116 | /* 227 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", |
| 136117 | /* 228 */ "trigger_time ::= BEFORE", |
| 136118 | /* 229 */ "trigger_time ::= AFTER", |
| 136119 | /* 230 */ "trigger_time ::= INSTEAD OF", |
| 136120 | /* 231 */ "trigger_time ::=", |
| 136121 | /* 232 */ "trigger_event ::= DELETE|INSERT", |
| 136122 | /* 233 */ "trigger_event ::= UPDATE", |
| 136123 | /* 234 */ "trigger_event ::= UPDATE OF idlist", |
| 136124 | /* 235 */ "when_clause ::=", |
| 136125 | /* 236 */ "when_clause ::= WHEN expr", |
| 136126 | /* 237 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", |
| 136127 | /* 238 */ "trigger_cmd_list ::= trigger_cmd SEMI", |
| 136128 | /* 239 */ "trnm ::= nm DOT nm", |
| 136129 | /* 240 */ "tridxby ::= INDEXED BY nm", |
| 136130 | /* 241 */ "tridxby ::= NOT INDEXED", |
| 136131 | /* 242 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", |
| 136132 | /* 243 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", |
| 136133 | /* 244 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", |
| 136134 | /* 245 */ "trigger_cmd ::= select", |
| 136135 | /* 246 */ "expr ::= RAISE LP IGNORE RP", |
| 136136 | /* 247 */ "expr ::= RAISE LP raisetype COMMA nm RP", |
| 136137 | /* 248 */ "raisetype ::= ROLLBACK", |
| 136138 | /* 249 */ "raisetype ::= ABORT", |
| 136139 | /* 250 */ "raisetype ::= FAIL", |
| 136140 | /* 251 */ "cmd ::= DROP TRIGGER ifexists fullname", |
| 136141 | /* 252 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", |
| 136142 | /* 253 */ "cmd ::= DETACH database_kw_opt expr", |
| 136143 | /* 254 */ "key_opt ::=", |
| 136144 | /* 255 */ "key_opt ::= KEY expr", |
| 136145 | /* 256 */ "cmd ::= REINDEX", |
| 136146 | /* 257 */ "cmd ::= REINDEX nm dbnm", |
| 136147 | /* 258 */ "cmd ::= ANALYZE", |
| 136148 | /* 259 */ "cmd ::= ANALYZE nm dbnm", |
| 136149 | /* 260 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", |
| 136150 | /* 261 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", |
| 136151 | /* 262 */ "add_column_fullname ::= fullname", |
| 136152 | /* 263 */ "cmd ::= create_vtab", |
| 136153 | /* 264 */ "cmd ::= create_vtab LP vtabarglist RP", |
| 136154 | /* 265 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", |
| 136155 | /* 266 */ "vtabarg ::=", |
| 136156 | /* 267 */ "vtabargtoken ::= ANY", |
| 136157 | /* 268 */ "vtabargtoken ::= lp anylist RP", |
| 136158 | /* 269 */ "lp ::= LP", |
| 136159 | /* 270 */ "with ::=", |
| 136160 | /* 271 */ "with ::= WITH wqlist", |
| 136161 | /* 272 */ "with ::= WITH RECURSIVE wqlist", |
| 136162 | /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", |
| 136163 | /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", |
| 136164 | /* 275 */ "input ::= cmdlist", |
| 136165 | /* 276 */ "cmdlist ::= cmdlist ecmd", |
| 136166 | /* 277 */ "cmdlist ::= ecmd", |
| 136167 | /* 278 */ "ecmd ::= SEMI", |
| 136168 | /* 279 */ "ecmd ::= explain cmdx SEMI", |
| 136169 | /* 280 */ "explain ::=", |
| 136170 | /* 281 */ "trans_opt ::=", |
| 136171 | /* 282 */ "trans_opt ::= TRANSACTION", |
| 136172 | /* 283 */ "trans_opt ::= TRANSACTION nm", |
| 136173 | /* 284 */ "savepoint_opt ::= SAVEPOINT", |
| 136174 | /* 285 */ "savepoint_opt ::=", |
| 136175 | /* 286 */ "cmd ::= create_table create_table_args", |
| 136176 | /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", |
| 136177 | /* 288 */ "columnlist ::= columnname carglist", |
| 136178 | /* 289 */ "nm ::= ID|INDEXED", |
| 136179 | /* 290 */ "nm ::= STRING", |
| 136180 | /* 291 */ "nm ::= JOIN_KW", |
| 136181 | /* 292 */ "typetoken ::= typename", |
| 136182 | /* 293 */ "typename ::= ID|STRING", |
| 136183 | /* 294 */ "signed ::= plus_num", |
| 136184 | /* 295 */ "signed ::= minus_num", |
| 136185 | /* 296 */ "carglist ::= carglist ccons", |
| 136186 | /* 297 */ "carglist ::=", |
| 136187 | /* 298 */ "ccons ::= NULL onconf", |
| 136188 | /* 299 */ "conslist_opt ::= COMMA conslist", |
| 136189 | /* 300 */ "conslist ::= conslist tconscomma tcons", |
| 136190 | /* 301 */ "conslist ::= tcons", |
| 136191 | /* 302 */ "tconscomma ::=", |
| 136192 | /* 303 */ "defer_subclause_opt ::= defer_subclause", |
| 136193 | /* 304 */ "resolvetype ::= raisetype", |
| 136194 | /* 305 */ "selectnowith ::= oneselect", |
| 136195 | /* 306 */ "oneselect ::= values", |
| 136196 | /* 307 */ "sclp ::= selcollist COMMA", |
| 136197 | /* 308 */ "as ::= ID|STRING", |
| 136198 | /* 309 */ "expr ::= term", |
| 136199 | /* 310 */ "likeop ::= LIKE_KW|MATCH", |
| 136200 | /* 311 */ "exprlist ::= nexprlist", |
| 136201 | /* 312 */ "nmnum ::= plus_num", |
| 136202 | /* 313 */ "nmnum ::= nm", |
| 136203 | /* 314 */ "nmnum ::= ON", |
| 136204 | /* 315 */ "nmnum ::= DELETE", |
| @@ -136375,11 +136831,10 @@ | |
| 136831 | { 173, 3 }, |
| 136832 | { 173, 3 }, |
| 136833 | { 173, 3 }, |
| 136834 | { 173, 3 }, |
| 136835 | { 173, 3 }, |
| 136836 | { 221, 2 }, |
| 136837 | { 173, 3 }, |
| 136838 | { 173, 5 }, |
| 136839 | { 173, 2 }, |
| 136840 | { 173, 3 }, |
| @@ -136512,10 +136967,11 @@ | |
| 136967 | { 194, 1 }, |
| 136968 | { 195, 1 }, |
| 136969 | { 209, 2 }, |
| 136970 | { 210, 1 }, |
| 136971 | { 173, 1 }, |
| 136972 | { 221, 1 }, |
| 136973 | { 208, 1 }, |
| 136974 | { 230, 1 }, |
| 136975 | { 230, 1 }, |
| 136976 | { 230, 1 }, |
| 136977 | { 230, 1 }, |
| @@ -136654,11 +137110,11 @@ | |
| 137110 | case 42: /* autoinc ::= */ yytestcase(yyruleno==42); |
| 137111 | case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); |
| 137112 | case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); |
| 137113 | case 76: /* ifexists ::= */ yytestcase(yyruleno==76); |
| 137114 | case 90: /* distinct ::= */ yytestcase(yyruleno==90); |
| 137115 | case 214: /* collate ::= */ yytestcase(yyruleno==214); |
| 137116 | {yymsp[1].minor.yy194 = 0;} |
| 137117 | break; |
| 137118 | case 17: /* ifnotexists ::= IF NOT EXISTS */ |
| 137119 | {yymsp[-2].minor.yy194 = 1;} |
| 137120 | break; |
| @@ -136798,13 +137254,13 @@ | |
| 137254 | case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); |
| 137255 | {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} |
| 137256 | break; |
| 137257 | case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ |
| 137258 | case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); |
| 137259 | case 186: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==186); |
| 137260 | case 189: /* in_op ::= NOT IN */ yytestcase(yyruleno==189); |
| 137261 | case 215: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==215); |
| 137262 | {yymsp[-1].minor.yy194 = 1;} |
| 137263 | break; |
| 137264 | case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ |
| 137265 | {yymsp[-1].minor.yy194 = 0;} |
| 137266 | break; |
| @@ -136964,13 +137420,13 @@ | |
| 137420 | {yymsp[0].minor.yy194 = SF_All;} |
| 137421 | break; |
| 137422 | case 91: /* sclp ::= */ |
| 137423 | case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); |
| 137424 | case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); |
| 137425 | case 202: /* exprlist ::= */ yytestcase(yyruleno==202); |
| 137426 | case 205: /* paren_exprlist ::= */ yytestcase(yyruleno==205); |
| 137427 | case 210: /* eidlist_opt ::= */ yytestcase(yyruleno==210); |
| 137428 | {yymsp[1].minor.yy148 = 0;} |
| 137429 | break; |
| 137430 | case 92: /* selcollist ::= sclp expr as */ |
| 137431 | { |
| 137432 | yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| @@ -136992,12 +137448,12 @@ | |
| 137448 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); |
| 137449 | } |
| 137450 | break; |
| 137451 | case 95: /* as ::= AS nm */ |
| 137452 | case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); |
| 137453 | case 224: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==224); |
| 137454 | case 225: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==225); |
| 137455 | {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} |
| 137456 | break; |
| 137457 | case 97: /* from ::= */ |
| 137458 | {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} |
| 137459 | break; |
| @@ -137076,18 +137532,18 @@ | |
| 137532 | {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} |
| 137533 | break; |
| 137534 | case 112: /* on_opt ::= ON expr */ |
| 137535 | case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); |
| 137536 | case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); |
| 137537 | case 198: /* case_else ::= ELSE expr */ yytestcase(yyruleno==198); |
| 137538 | {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} |
| 137539 | break; |
| 137540 | case 113: /* on_opt ::= */ |
| 137541 | case 128: /* having_opt ::= */ yytestcase(yyruleno==128); |
| 137542 | case 135: /* where_opt ::= */ yytestcase(yyruleno==135); |
| 137543 | case 199: /* case_else ::= */ yytestcase(yyruleno==199); |
| 137544 | case 201: /* case_operand ::= */ yytestcase(yyruleno==201); |
| 137545 | {yymsp[1].minor.yy72 = 0;} |
| 137546 | break; |
| 137547 | case 115: /* indexed_opt ::= INDEXED BY nm */ |
| 137548 | {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} |
| 137549 | break; |
| @@ -137230,11 +137686,11 @@ | |
| 137686 | case 158: /* term ::= INTEGER */ |
| 137687 | { |
| 137688 | yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); |
| 137689 | yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; |
| 137690 | yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; |
| 137691 | if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf|EP_Resolved; |
| 137692 | } |
| 137693 | yymsp[0].minor.yy190 = yylhsminor.yy190; |
| 137694 | break; |
| 137695 | case 159: /* expr ::= VARIABLE */ |
| 137696 | { |
| @@ -137320,17 +137776,14 @@ | |
| 137776 | case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); |
| 137777 | case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); |
| 137778 | case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); |
| 137779 | {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} |
| 137780 | break; |
| 137781 | case 174: /* likeop ::= NOT LIKE_KW|MATCH */ |
| 137782 | {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} |
| 137783 | break; |
| 137784 | case 175: /* expr ::= expr likeop expr */ |
| 137785 | { |
| 137786 | ExprList *pList; |
| 137787 | int bNot = yymsp[-1].minor.yy0.n & 0x80000000; |
| 137788 | yymsp[-1].minor.yy0.n &= 0x7fffffff; |
| 137789 | pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); |
| @@ -137339,11 +137792,11 @@ | |
| 137792 | exprNot(pParse, bNot, &yymsp[-2].minor.yy190); |
| 137793 | yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137794 | if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 137795 | } |
| 137796 | break; |
| 137797 | case 176: /* expr ::= expr likeop expr ESCAPE expr */ |
| 137798 | { |
| 137799 | ExprList *pList; |
| 137800 | int bNot = yymsp[-3].minor.yy0.n & 0x80000000; |
| 137801 | yymsp[-3].minor.yy0.n &= 0x7fffffff; |
| 137802 | pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| @@ -137353,43 +137806,43 @@ | |
| 137806 | exprNot(pParse, bNot, &yymsp[-4].minor.yy190); |
| 137807 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137808 | if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 137809 | } |
| 137810 | break; |
| 137811 | case 177: /* expr ::= expr ISNULL|NOTNULL */ |
| 137812 | {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} |
| 137813 | break; |
| 137814 | case 178: /* expr ::= expr NOT NULL */ |
| 137815 | {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} |
| 137816 | break; |
| 137817 | case 179: /* expr ::= expr IS expr */ |
| 137818 | { |
| 137819 | spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); |
| 137820 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); |
| 137821 | } |
| 137822 | break; |
| 137823 | case 180: /* expr ::= expr IS NOT expr */ |
| 137824 | { |
| 137825 | spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); |
| 137826 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); |
| 137827 | } |
| 137828 | break; |
| 137829 | case 181: /* expr ::= NOT expr */ |
| 137830 | case 182: /* expr ::= BITNOT expr */ yytestcase(yyruleno==182); |
| 137831 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137832 | break; |
| 137833 | case 183: /* expr ::= MINUS expr */ |
| 137834 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137835 | break; |
| 137836 | case 184: /* expr ::= PLUS expr */ |
| 137837 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 137838 | break; |
| 137839 | case 185: /* between_op ::= BETWEEN */ |
| 137840 | case 188: /* in_op ::= IN */ yytestcase(yyruleno==188); |
| 137841 | {yymsp[0].minor.yy194 = 0;} |
| 137842 | break; |
| 137843 | case 187: /* expr ::= expr between_op expr AND expr */ |
| 137844 | { |
| 137845 | ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 137846 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 137847 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); |
| 137848 | if( yymsp[-4].minor.yy190.pExpr ){ |
| @@ -137399,11 +137852,11 @@ | |
| 137852 | } |
| 137853 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137854 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 137855 | } |
| 137856 | break; |
| 137857 | case 190: /* expr ::= expr in_op LP exprlist RP */ |
| 137858 | { |
| 137859 | if( yymsp[-1].minor.yy148==0 ){ |
| 137860 | /* Expressions of the form |
| 137861 | ** |
| 137862 | ** expr1 IN () |
| @@ -137452,26 +137905,26 @@ | |
| 137905 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137906 | } |
| 137907 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 137908 | } |
| 137909 | break; |
| 137910 | case 191: /* expr ::= LP select RP */ |
| 137911 | { |
| 137912 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 137913 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); |
| 137914 | sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 137915 | } |
| 137916 | break; |
| 137917 | case 192: /* expr ::= expr in_op LP select RP */ |
| 137918 | { |
| 137919 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); |
| 137920 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 137921 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137922 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 137923 | } |
| 137924 | break; |
| 137925 | case 193: /* expr ::= expr in_op nm dbnm paren_exprlist */ |
| 137926 | { |
| 137927 | SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); |
| 137928 | Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); |
| 137929 | if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); |
| 137930 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); |
| @@ -137478,19 +137931,19 @@ | |
| 137931 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); |
| 137932 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 137933 | yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; |
| 137934 | } |
| 137935 | break; |
| 137936 | case 194: /* expr ::= EXISTS LP select RP */ |
| 137937 | { |
| 137938 | Expr *p; |
| 137939 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 137940 | p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); |
| 137941 | sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); |
| 137942 | } |
| 137943 | break; |
| 137944 | case 195: /* expr ::= CASE case_operand case_exprlist case_else END */ |
| 137945 | { |
| 137946 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ |
| 137947 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); |
| 137948 | if( yymsp[-4].minor.yy190.pExpr ){ |
| 137949 | yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; |
| @@ -137499,313 +137952,314 @@ | |
| 137952 | sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); |
| 137953 | sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); |
| 137954 | } |
| 137955 | } |
| 137956 | break; |
| 137957 | case 196: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ |
| 137958 | { |
| 137959 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); |
| 137960 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 137961 | } |
| 137962 | break; |
| 137963 | case 197: /* case_exprlist ::= WHEN expr THEN expr */ |
| 137964 | { |
| 137965 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 137966 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 137967 | } |
| 137968 | break; |
| 137969 | case 200: /* case_operand ::= expr */ |
| 137970 | {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} |
| 137971 | break; |
| 137972 | case 203: /* nexprlist ::= nexprlist COMMA expr */ |
| 137973 | {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} |
| 137974 | break; |
| 137975 | case 204: /* nexprlist ::= expr */ |
| 137976 | {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} |
| 137977 | break; |
| 137978 | case 206: /* paren_exprlist ::= LP exprlist RP */ |
| 137979 | case 211: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==211); |
| 137980 | {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} |
| 137981 | break; |
| 137982 | case 207: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ |
| 137983 | { |
| 137984 | sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, |
| 137985 | sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, |
| 137986 | &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); |
| 137987 | } |
| 137988 | break; |
| 137989 | case 208: /* uniqueflag ::= UNIQUE */ |
| 137990 | case 249: /* raisetype ::= ABORT */ yytestcase(yyruleno==249); |
| 137991 | {yymsp[0].minor.yy194 = OE_Abort;} |
| 137992 | break; |
| 137993 | case 209: /* uniqueflag ::= */ |
| 137994 | {yymsp[1].minor.yy194 = OE_None;} |
| 137995 | break; |
| 137996 | case 212: /* eidlist ::= eidlist COMMA nm collate sortorder */ |
| 137997 | { |
| 137998 | yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); |
| 137999 | } |
| 138000 | break; |
| 138001 | case 213: /* eidlist ::= nm collate sortorder */ |
| 138002 | { |
| 138003 | yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ |
| 138004 | } |
| 138005 | break; |
| 138006 | case 216: /* cmd ::= DROP INDEX ifexists fullname */ |
| 138007 | {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} |
| 138008 | break; |
| 138009 | case 217: /* cmd ::= VACUUM */ |
| 138010 | {sqlite3Vacuum(pParse,0);} |
| 138011 | break; |
| 138012 | case 218: /* cmd ::= VACUUM nm */ |
| 138013 | {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} |
| 138014 | break; |
| 138015 | case 219: /* cmd ::= PRAGMA nm dbnm */ |
| 138016 | {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} |
| 138017 | break; |
| 138018 | case 220: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ |
| 138019 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} |
| 138020 | break; |
| 138021 | case 221: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ |
| 138022 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} |
| 138023 | break; |
| 138024 | case 222: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ |
| 138025 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} |
| 138026 | break; |
| 138027 | case 223: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ |
| 138028 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} |
| 138029 | break; |
| 138030 | case 226: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ |
| 138031 | { |
| 138032 | Token all; |
| 138033 | all.z = yymsp[-3].minor.yy0.z; |
| 138034 | all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; |
| 138035 | sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); |
| 138036 | } |
| 138037 | break; |
| 138038 | case 227: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ |
| 138039 | { |
| 138040 | sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); |
| 138041 | yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ |
| 138042 | } |
| 138043 | break; |
| 138044 | case 228: /* trigger_time ::= BEFORE */ |
| 138045 | { yymsp[0].minor.yy194 = TK_BEFORE; } |
| 138046 | break; |
| 138047 | case 229: /* trigger_time ::= AFTER */ |
| 138048 | { yymsp[0].minor.yy194 = TK_AFTER; } |
| 138049 | break; |
| 138050 | case 230: /* trigger_time ::= INSTEAD OF */ |
| 138051 | { yymsp[-1].minor.yy194 = TK_INSTEAD;} |
| 138052 | break; |
| 138053 | case 231: /* trigger_time ::= */ |
| 138054 | { yymsp[1].minor.yy194 = TK_BEFORE; } |
| 138055 | break; |
| 138056 | case 232: /* trigger_event ::= DELETE|INSERT */ |
| 138057 | case 233: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==233); |
| 138058 | {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} |
| 138059 | break; |
| 138060 | case 234: /* trigger_event ::= UPDATE OF idlist */ |
| 138061 | {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} |
| 138062 | break; |
| 138063 | case 235: /* when_clause ::= */ |
| 138064 | case 254: /* key_opt ::= */ yytestcase(yyruleno==254); |
| 138065 | { yymsp[1].minor.yy72 = 0; } |
| 138066 | break; |
| 138067 | case 236: /* when_clause ::= WHEN expr */ |
| 138068 | case 255: /* key_opt ::= KEY expr */ yytestcase(yyruleno==255); |
| 138069 | { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } |
| 138070 | break; |
| 138071 | case 237: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ |
| 138072 | { |
| 138073 | assert( yymsp[-2].minor.yy145!=0 ); |
| 138074 | yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; |
| 138075 | yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 138076 | } |
| 138077 | break; |
| 138078 | case 238: /* trigger_cmd_list ::= trigger_cmd SEMI */ |
| 138079 | { |
| 138080 | assert( yymsp[-1].minor.yy145!=0 ); |
| 138081 | yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 138082 | } |
| 138083 | break; |
| 138084 | case 239: /* trnm ::= nm DOT nm */ |
| 138085 | { |
| 138086 | yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; |
| 138087 | sqlite3ErrorMsg(pParse, |
| 138088 | "qualified table names are not allowed on INSERT, UPDATE, and DELETE " |
| 138089 | "statements within triggers"); |
| 138090 | } |
| 138091 | break; |
| 138092 | case 240: /* tridxby ::= INDEXED BY nm */ |
| 138093 | { |
| 138094 | sqlite3ErrorMsg(pParse, |
| 138095 | "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " |
| 138096 | "within triggers"); |
| 138097 | } |
| 138098 | break; |
| 138099 | case 241: /* tridxby ::= NOT INDEXED */ |
| 138100 | { |
| 138101 | sqlite3ErrorMsg(pParse, |
| 138102 | "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " |
| 138103 | "within triggers"); |
| 138104 | } |
| 138105 | break; |
| 138106 | case 242: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ |
| 138107 | {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} |
| 138108 | break; |
| 138109 | case 243: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ |
| 138110 | {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} |
| 138111 | break; |
| 138112 | case 244: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ |
| 138113 | {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} |
| 138114 | break; |
| 138115 | case 245: /* trigger_cmd ::= select */ |
| 138116 | {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} |
| 138117 | break; |
| 138118 | case 246: /* expr ::= RAISE LP IGNORE RP */ |
| 138119 | { |
| 138120 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 138121 | yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); |
| 138122 | if( yymsp[-3].minor.yy190.pExpr ){ |
| 138123 | yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; |
| 138124 | } |
| 138125 | } |
| 138126 | break; |
| 138127 | case 247: /* expr ::= RAISE LP raisetype COMMA nm RP */ |
| 138128 | { |
| 138129 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 138130 | yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); |
| 138131 | if( yymsp[-5].minor.yy190.pExpr ) { |
| 138132 | yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; |
| 138133 | } |
| 138134 | } |
| 138135 | break; |
| 138136 | case 248: /* raisetype ::= ROLLBACK */ |
| 138137 | {yymsp[0].minor.yy194 = OE_Rollback;} |
| 138138 | break; |
| 138139 | case 250: /* raisetype ::= FAIL */ |
| 138140 | {yymsp[0].minor.yy194 = OE_Fail;} |
| 138141 | break; |
| 138142 | case 251: /* cmd ::= DROP TRIGGER ifexists fullname */ |
| 138143 | { |
| 138144 | sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); |
| 138145 | } |
| 138146 | break; |
| 138147 | case 252: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ |
| 138148 | { |
| 138149 | sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); |
| 138150 | } |
| 138151 | break; |
| 138152 | case 253: /* cmd ::= DETACH database_kw_opt expr */ |
| 138153 | { |
| 138154 | sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); |
| 138155 | } |
| 138156 | break; |
| 138157 | case 256: /* cmd ::= REINDEX */ |
| 138158 | {sqlite3Reindex(pParse, 0, 0);} |
| 138159 | break; |
| 138160 | case 257: /* cmd ::= REINDEX nm dbnm */ |
| 138161 | {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 138162 | break; |
| 138163 | case 258: /* cmd ::= ANALYZE */ |
| 138164 | {sqlite3Analyze(pParse, 0, 0);} |
| 138165 | break; |
| 138166 | case 259: /* cmd ::= ANALYZE nm dbnm */ |
| 138167 | {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 138168 | break; |
| 138169 | case 260: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ |
| 138170 | { |
| 138171 | sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); |
| 138172 | } |
| 138173 | break; |
| 138174 | case 261: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ |
| 138175 | { |
| 138176 | yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; |
| 138177 | sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); |
| 138178 | } |
| 138179 | break; |
| 138180 | case 262: /* add_column_fullname ::= fullname */ |
| 138181 | { |
| 138182 | disableLookaside(pParse); |
| 138183 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); |
| 138184 | } |
| 138185 | break; |
| 138186 | case 263: /* cmd ::= create_vtab */ |
| 138187 | {sqlite3VtabFinishParse(pParse,0);} |
| 138188 | break; |
| 138189 | case 264: /* cmd ::= create_vtab LP vtabarglist RP */ |
| 138190 | {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} |
| 138191 | break; |
| 138192 | case 265: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ |
| 138193 | { |
| 138194 | sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); |
| 138195 | } |
| 138196 | break; |
| 138197 | case 266: /* vtabarg ::= */ |
| 138198 | {sqlite3VtabArgInit(pParse);} |
| 138199 | break; |
| 138200 | case 267: /* vtabargtoken ::= ANY */ |
| 138201 | case 268: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==268); |
| 138202 | case 269: /* lp ::= LP */ yytestcase(yyruleno==269); |
| 138203 | {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} |
| 138204 | break; |
| 138205 | case 270: /* with ::= */ |
| 138206 | {yymsp[1].minor.yy285 = 0;} |
| 138207 | break; |
| 138208 | case 271: /* with ::= WITH wqlist */ |
| 138209 | { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } |
| 138210 | break; |
| 138211 | case 272: /* with ::= WITH RECURSIVE wqlist */ |
| 138212 | { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } |
| 138213 | break; |
| 138214 | case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ |
| 138215 | { |
| 138216 | yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ |
| 138217 | } |
| 138218 | break; |
| 138219 | case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ |
| 138220 | { |
| 138221 | yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); |
| 138222 | } |
| 138223 | break; |
| 138224 | default: |
| 138225 | /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); |
| 138226 | /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); |
| 138227 | /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); |
| 138228 | /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); |
| 138229 | /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); |
| 138230 | /* (280) explain ::= */ yytestcase(yyruleno==280); |
| 138231 | /* (281) trans_opt ::= */ yytestcase(yyruleno==281); |
| 138232 | /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); |
| 138233 | /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); |
| 138234 | /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); |
| 138235 | /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); |
| 138236 | /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); |
| 138237 | /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); |
| 138238 | /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); |
| 138239 | /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); |
| 138240 | /* (290) nm ::= STRING */ yytestcase(yyruleno==290); |
| 138241 | /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); |
| 138242 | /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); |
| 138243 | /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); |
| 138244 | /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); |
| 138245 | /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); |
| 138246 | /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); |
| 138247 | /* (297) carglist ::= */ yytestcase(yyruleno==297); |
| 138248 | /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); |
| 138249 | /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); |
| 138250 | /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); |
| 138251 | /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); |
| 138252 | /* (302) tconscomma ::= */ yytestcase(yyruleno==302); |
| 138253 | /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); |
| 138254 | /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); |
| 138255 | /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); |
| 138256 | /* (306) oneselect ::= values */ yytestcase(yyruleno==306); |
| 138257 | /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); |
| 138258 | /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); |
| 138259 | /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); |
| 138260 | /* (310) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==310); |
| 138261 | /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); |
| 138262 | /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); |
| 138263 | /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); |
| 138264 | /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); |
| 138265 | /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); |
| @@ -138854,12 +139308,12 @@ | |
| 139308 | ** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that |
| 139309 | ** error message. |
| 139310 | */ |
| 139311 | SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ |
| 139312 | int nErr = 0; /* Number of errors encountered */ |
| 139313 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 139314 | int n = 0; /* Length of the next token token */ |
| 139315 | int tokenType; /* type of the next token */ |
| 139316 | int lastTokenParsed = -1; /* type of the previous token */ |
| 139317 | sqlite3 *db = pParse->db; /* The database connection */ |
| 139318 | int mxSqlLen; /* Max length of an SQL string */ |
| 139319 | #ifdef sqlite3Parser_ENGINEALWAYSONSTACK |
| @@ -138871,11 +139325,10 @@ | |
| 139325 | if( db->nVdbeActive==0 ){ |
| 139326 | db->u1.isInterrupted = 0; |
| 139327 | } |
| 139328 | pParse->rc = SQLITE_OK; |
| 139329 | pParse->zTail = zSql; |
| 139330 | assert( pzErrMsg!=0 ); |
| 139331 | /* sqlite3ParserTrace(stdout, "parser: "); */ |
| 139332 | #ifdef sqlite3Parser_ENGINEALWAYSONSTACK |
| 139333 | pEngine = zSpace; |
| 139334 | sqlite3ParserInit(pEngine); |
| @@ -138889,16 +139342,14 @@ | |
| 139342 | assert( pParse->pNewTable==0 ); |
| 139343 | assert( pParse->pNewTrigger==0 ); |
| 139344 | assert( pParse->nVar==0 ); |
| 139345 | assert( pParse->pVList==0 ); |
| 139346 | while( 1 ){ |
| 139347 | if( zSql[0]!=0 ){ |
| 139348 | n = sqlite3GetToken((u8*)zSql, &tokenType); |
| 139349 | mxSqlLen -= n; |
| 139350 | if( mxSqlLen<0 ){ |
| 139351 | pParse->rc = SQLITE_TOOBIG; |
| 139352 | break; |
| 139353 | } |
| 139354 | }else{ |
| 139355 | /* Upon reaching the end of input, call the parser two more times |
| @@ -138908,30 +139359,34 @@ | |
| 139359 | }else if( lastTokenParsed==0 ){ |
| 139360 | break; |
| 139361 | }else{ |
| 139362 | tokenType = TK_SEMI; |
| 139363 | } |
| 139364 | zSql -= n; |
| 139365 | } |
| 139366 | if( tokenType>=TK_SPACE ){ |
| 139367 | assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); |
| 139368 | if( db->u1.isInterrupted ){ |
| 139369 | pParse->rc = SQLITE_INTERRUPT; |
| 139370 | break; |
| 139371 | } |
| 139372 | if( tokenType==TK_ILLEGAL ){ |
| 139373 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); |
| 139374 | break; |
| 139375 | } |
| 139376 | zSql += n; |
| 139377 | }else{ |
| 139378 | pParse->sLastToken.z = zSql; |
| 139379 | pParse->sLastToken.n = n; |
| 139380 | sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); |
| 139381 | lastTokenParsed = tokenType; |
| 139382 | zSql += n; |
| 139383 | if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; |
| 139384 | } |
| 139385 | } |
| 139386 | assert( nErr==0 ); |
| 139387 | pParse->zTail = zSql; |
| 139388 | #ifdef YYTRACKMAXSTACKDEPTH |
| 139389 | sqlite3_mutex_enter(sqlite3MallocMutex()); |
| 139390 | sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, |
| 139391 | sqlite3ParserStackPeak(pEngine) |
| 139392 | ); |
| @@ -140301,10 +140756,25 @@ | |
| 140756 | return 0; |
| 140757 | } |
| 140758 | #endif |
| 140759 | return db->lastRowid; |
| 140760 | } |
| 140761 | |
| 140762 | /* |
| 140763 | ** Set the value returned by the sqlite3_last_insert_rowid() API function. |
| 140764 | */ |
| 140765 | SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){ |
| 140766 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 140767 | if( !sqlite3SafetyCheckOk(db) ){ |
| 140768 | (void)SQLITE_MISUSE_BKPT; |
| 140769 | return; |
| 140770 | } |
| 140771 | #endif |
| 140772 | sqlite3_mutex_enter(db->mutex); |
| 140773 | db->lastRowid = iRowid; |
| 140774 | sqlite3_mutex_leave(db->mutex); |
| 140775 | } |
| 140776 | |
| 140777 | /* |
| 140778 | ** Return the number of changes in the most recent call to sqlite3_exec(). |
| 140779 | */ |
| 140780 | SQLITE_API int sqlite3_changes(sqlite3 *db){ |
| @@ -148111,12 +148581,14 @@ | |
| 148581 | ** segments. |
| 148582 | */ |
| 148583 | const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ |
| 148584 | |
| 148585 | Fts3Table *p = (Fts3Table*)pVtab; |
| 148586 | int rc; |
| 148587 | i64 iLastRowid = sqlite3_last_insert_rowid(p->db); |
| 148588 | |
| 148589 | rc = sqlite3Fts3PendingTermsFlush(p); |
| 148590 | if( rc==SQLITE_OK |
| 148591 | && p->nLeafAdd>(nMinMerge/16) |
| 148592 | && p->nAutoincrmerge && p->nAutoincrmerge!=0xff |
| 148593 | ){ |
| 148594 | int mxLevel = 0; /* Maximum relative level value in db */ |
| @@ -148127,10 +148599,11 @@ | |
| 148599 | A = p->nLeafAdd * mxLevel; |
| 148600 | A += (A/2); |
| 148601 | if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); |
| 148602 | } |
| 148603 | sqlite3Fts3SegmentsClose(p); |
| 148604 | sqlite3_set_last_insert_rowid(p->db, iLastRowid); |
| 148605 | return rc; |
| 148606 | } |
| 148607 | |
| 148608 | /* |
| 148609 | ** If it is currently unknown whether or not the FTS table has an %_stat |
| @@ -168462,10 +168935,11 @@ | |
| 168935 | int nStep; /* Rows processed for current object */ |
| 168936 | int nProgress; /* Rows processed for all objects */ |
| 168937 | RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ |
| 168938 | const char *zVfsName; /* Name of automatically created rbu vfs */ |
| 168939 | rbu_file *pTargetFd; /* File handle open on target db */ |
| 168940 | int nPagePerSector; /* Pages per sector for pTargetFd */ |
| 168941 | i64 iOalSz; |
| 168942 | i64 nPhaseOneStep; |
| 168943 | |
| 168944 | /* The following state variables are used as part of the incremental |
| 168945 | ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding |
| @@ -170726,10 +171200,27 @@ | |
| 171200 | |
| 171201 | if( p->rc==SQLITE_OK ){ |
| 171202 | if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){ |
| 171203 | p->rc = SQLITE_DONE; |
| 171204 | p->eStage = RBU_STAGE_DONE; |
| 171205 | }else{ |
| 171206 | int nSectorSize; |
| 171207 | sqlite3_file *pDb = p->pTargetFd->pReal; |
| 171208 | sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal; |
| 171209 | assert( p->nPagePerSector==0 ); |
| 171210 | nSectorSize = pDb->pMethods->xSectorSize(pDb); |
| 171211 | if( nSectorSize>p->pgsz ){ |
| 171212 | p->nPagePerSector = nSectorSize / p->pgsz; |
| 171213 | }else{ |
| 171214 | p->nPagePerSector = 1; |
| 171215 | } |
| 171216 | |
| 171217 | /* Call xSync() on the wal file. This causes SQLite to sync the |
| 171218 | ** directory in which the target database and the wal file reside, in |
| 171219 | ** case it has not been synced since the rename() call in |
| 171220 | ** rbuMoveOalFile(). */ |
| 171221 | p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL); |
| 171222 | } |
| 171223 | } |
| 171224 | } |
| 171225 | |
| 171226 | /* |
| @@ -171381,13 +171872,30 @@ | |
| 171872 | if( p->rc==SQLITE_OK ){ |
| 171873 | p->eStage = RBU_STAGE_DONE; |
| 171874 | p->rc = SQLITE_DONE; |
| 171875 | } |
| 171876 | }else{ |
| 171877 | /* At one point the following block copied a single frame from the |
| 171878 | ** wal file to the database file. So that one call to sqlite3rbu_step() |
| 171879 | ** checkpointed a single frame. |
| 171880 | ** |
| 171881 | ** However, if the sector-size is larger than the page-size, and the |
| 171882 | ** application calls sqlite3rbu_savestate() or close() immediately |
| 171883 | ** after this step, then rbu_step() again, then a power failure occurs, |
| 171884 | ** then the database page written here may be damaged. Work around |
| 171885 | ** this by checkpointing frames until the next page in the aFrame[] |
| 171886 | ** lies on a different disk sector to the current one. */ |
| 171887 | u32 iSector; |
| 171888 | do{ |
| 171889 | RbuFrame *pFrame = &p->aFrame[p->nStep]; |
| 171890 | iSector = (pFrame->iDbPage-1) / p->nPagePerSector; |
| 171891 | rbuCheckpointFrame(p, pFrame); |
| 171892 | p->nStep++; |
| 171893 | }while( p->nStep<p->nFrame |
| 171894 | && iSector==((p->aFrame[p->nStep].iDbPage-1) / p->nPagePerSector) |
| 171895 | && p->rc==SQLITE_OK |
| 171896 | ); |
| 171897 | } |
| 171898 | p->nProgress++; |
| 171899 | } |
| 171900 | break; |
| 171901 | } |
| @@ -171823,10 +172331,16 @@ | |
| 172331 | |
| 172332 | /* Commit the transaction to the *-oal file. */ |
| 172333 | if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ |
| 172334 | p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); |
| 172335 | } |
| 172336 | |
| 172337 | /* Sync the db file if currently doing an incremental checkpoint */ |
| 172338 | if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){ |
| 172339 | sqlite3_file *pDb = p->pTargetFd->pReal; |
| 172340 | p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); |
| 172341 | } |
| 172342 | |
| 172343 | rbuSaveState(p, p->eStage); |
| 172344 | |
| 172345 | if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ |
| 172346 | p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); |
| @@ -171947,10 +172461,16 @@ | |
| 172461 | assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE ); |
| 172462 | if( p->eStage==RBU_STAGE_OAL ){ |
| 172463 | assert( rc!=SQLITE_DONE ); |
| 172464 | if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0); |
| 172465 | } |
| 172466 | |
| 172467 | /* Sync the db file */ |
| 172468 | if( rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){ |
| 172469 | sqlite3_file *pDb = p->pTargetFd->pReal; |
| 172470 | rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); |
| 172471 | } |
| 172472 | |
| 172473 | p->rc = rc; |
| 172474 | rbuSaveState(p, p->eStage); |
| 172475 | rc = p->rc; |
| 172476 | |
| @@ -181079,11 +181599,13 @@ | |
| 181599 | typedef unsigned short u16; |
| 181600 | typedef short i16; |
| 181601 | typedef sqlite3_int64 i64; |
| 181602 | typedef sqlite3_uint64 u64; |
| 181603 | |
| 181604 | #ifndef ArraySize |
| 181605 | # define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) |
| 181606 | #endif |
| 181607 | |
| 181608 | #define testcase(x) |
| 181609 | #define ALWAYS(x) 1 |
| 181610 | #define NEVER(x) 0 |
| 181611 | |
| @@ -186302,11 +186824,14 @@ | |
| 186824 | if( p1->bEof==0 ){ |
| 186825 | if( (p1->iRowid==iLast) |
| 186826 | || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) |
| 186827 | ){ |
| 186828 | int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); |
| 186829 | if( rc!=SQLITE_OK ){ |
| 186830 | pNode->bNomatch = 0; |
| 186831 | return rc; |
| 186832 | } |
| 186833 | } |
| 186834 | } |
| 186835 | } |
| 186836 | |
| 186837 | fts5ExprNodeTest_OR(pExpr, pNode); |
| @@ -186333,11 +186858,14 @@ | |
| 186858 | Fts5ExprNode *pChild = pAnd->apChild[iChild]; |
| 186859 | int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); |
| 186860 | if( cmp>0 ){ |
| 186861 | /* Advance pChild until it points to iLast or laster */ |
| 186862 | rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); |
| 186863 | if( rc!=SQLITE_OK ){ |
| 186864 | pAnd->bNomatch = 0; |
| 186865 | return rc; |
| 186866 | } |
| 186867 | } |
| 186868 | |
| 186869 | /* If the child node is now at EOF, so is the parent AND node. Otherwise, |
| 186870 | ** the child node is guaranteed to have advanced at least as far as |
| 186871 | ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the |
| @@ -186372,10 +186900,12 @@ | |
| 186900 | i64 iFrom |
| 186901 | ){ |
| 186902 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 186903 | if( rc==SQLITE_OK ){ |
| 186904 | rc = fts5ExprNodeTest_AND(pExpr, pNode); |
| 186905 | }else{ |
| 186906 | pNode->bNomatch = 0; |
| 186907 | } |
| 186908 | return rc; |
| 186909 | } |
| 186910 | |
| 186911 | static int fts5ExprNodeTest_NOT( |
| @@ -186414,10 +186944,13 @@ | |
| 186944 | ){ |
| 186945 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 186946 | if( rc==SQLITE_OK ){ |
| 186947 | rc = fts5ExprNodeTest_NOT(pExpr, pNode); |
| 186948 | } |
| 186949 | if( rc!=SQLITE_OK ){ |
| 186950 | pNode->bNomatch = 0; |
| 186951 | } |
| 186952 | return rc; |
| 186953 | } |
| 186954 | |
| 186955 | /* |
| 186956 | ** If pNode currently points to a match, this function returns SQLITE_OK |
| @@ -197534,11 +198067,11 @@ | |
| 198067 | int nArg, /* Number of args */ |
| 198068 | sqlite3_value **apUnused /* Function arguments */ |
| 198069 | ){ |
| 198070 | assert( nArg==0 ); |
| 198071 | UNUSED_PARAM2(nArg, apUnused); |
| 198072 | sqlite3_result_text(pCtx, "fts5: 2017-03-10 17:03:11 f8560c60d10c0365b33342ab05b5a953987b0471", -1, SQLITE_TRANSIENT); |
| 198073 | } |
| 198074 | |
| 198075 | static int fts5Init(sqlite3 *db){ |
| 198076 | static const sqlite3_module fts5Mod = { |
| 198077 | /* iVersion */ 2, |
| @@ -198197,15 +198730,10 @@ | |
| 198730 | sqlite3_step(pDel); |
| 198731 | rc = sqlite3_reset(pDel); |
| 198732 | } |
| 198733 | } |
| 198734 | |
| 198735 | return rc; |
| 198736 | } |
| 198737 | |
| 198738 | /* |
| 198739 | ** Delete all entries in the FTS5 index. |
| @@ -198405,15 +198933,10 @@ | |
| 198933 | if( rc==SQLITE_OK ){ |
| 198934 | rc = fts5StorageInsertDocsize(p, iRowid, &buf); |
| 198935 | } |
| 198936 | sqlite3_free(buf.p); |
| 198937 | |
| 198938 | return rc; |
| 198939 | } |
| 198940 | |
| 198941 | static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){ |
| 198942 | Fts5Config *pConfig = p->pConfig; |
| @@ -198744,16 +199267,21 @@ | |
| 199267 | |
| 199268 | /* |
| 199269 | ** Flush any data currently held in-memory to disk. |
| 199270 | */ |
| 199271 | static int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){ |
| 199272 | int rc = SQLITE_OK; |
| 199273 | i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db); |
| 199274 | if( p->bTotalsValid ){ |
| 199275 | rc = fts5StorageSaveTotals(p); |
| 199276 | if( bCommit ) p->bTotalsValid = 0; |
| 199277 | } |
| 199278 | if( rc==SQLITE_OK ){ |
| 199279 | rc = sqlite3Fts5IndexSync(p->pIndex, bCommit); |
| 199280 | } |
| 199281 | sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid); |
| 199282 | return rc; |
| 199283 | } |
| 199284 | |
| 199285 | static int sqlite3Fts5StorageRollback(Fts5Storage *p){ |
| 199286 | p->bTotalsValid = 0; |
| 199287 | return sqlite3Fts5IndexRollback(p->pIndex); |
| 199288 |
+36
-16
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -119,13 +119,13 @@ | ||
| 119 | 119 | ** |
| 120 | 120 | ** See also: [sqlite3_libversion()], |
| 121 | 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | 123 | */ |
| 124 | -#define SQLITE_VERSION "3.17.0" | |
| 125 | -#define SQLITE_VERSION_NUMBER 3017000 | |
| 126 | -#define SQLITE_SOURCE_ID "2017-02-13 16:02:40 ada05cfa86ad7f5645450ac7a2a21c9aa6e57d2c" | |
| 124 | +#define SQLITE_VERSION "3.18.0" | |
| 125 | +#define SQLITE_VERSION_NUMBER 3018000 | |
| 126 | +#define SQLITE_SOURCE_ID "2017-03-10 17:03:11 f8560c60d10c0365b33342ab05b5a953987b0471" | |
| 127 | 127 | |
| 128 | 128 | /* |
| 129 | 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | 130 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 131 | 131 | ** |
| @@ -2038,24 +2038,34 @@ | ||
| 2038 | 2038 | ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those |
| 2039 | 2039 | ** names are not also used by explicitly declared columns. ^If |
| 2040 | 2040 | ** the table has a column of type [INTEGER PRIMARY KEY] then that column |
| 2041 | 2041 | ** is another alias for the rowid. |
| 2042 | 2042 | ** |
| 2043 | -** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the | |
| 2044 | -** most recent successful [INSERT] into a rowid table or [virtual table] | |
| 2045 | -** on database connection D. | |
| 2046 | -** ^Inserts into [WITHOUT ROWID] tables are not recorded. | |
| 2047 | -** ^If no successful [INSERT]s into rowid tables | |
| 2048 | -** have ever occurred on the database connection D, | |
| 2049 | -** then sqlite3_last_insert_rowid(D) returns zero. | |
| 2043 | +** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of | |
| 2044 | +** the most recent successful [INSERT] into a rowid table or [virtual table] | |
| 2045 | +** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not | |
| 2046 | +** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred | |
| 2047 | +** on the database connection D, then sqlite3_last_insert_rowid(D) returns | |
| 2048 | +** zero. | |
| 2050 | 2049 | ** |
| 2051 | -** ^(If an [INSERT] occurs within a trigger or within a [virtual table] | |
| 2052 | -** method, then this routine will return the [rowid] of the inserted | |
| 2053 | -** row as long as the trigger or virtual table method is running. | |
| 2054 | -** But once the trigger or virtual table method ends, the value returned | |
| 2055 | -** by this routine reverts to what it was before the trigger or virtual | |
| 2056 | -** table method began.)^ | |
| 2050 | +** As well as being set automatically as rows are inserted into database | |
| 2051 | +** tables, the value returned by this function may be set explicitly by | |
| 2052 | +** [sqlite3_set_last_insert_rowid()] | |
| 2053 | +** | |
| 2054 | +** Some virtual table implementations may INSERT rows into rowid tables as | |
| 2055 | +** part of committing a transaction (e.g. to flush data accumulated in memory | |
| 2056 | +** to disk). In this case subsequent calls to this function return the rowid | |
| 2057 | +** associated with these internal INSERT operations, which leads to | |
| 2058 | +** unintuitive results. Virtual table implementations that do write to rowid | |
| 2059 | +** tables in this way can avoid this problem by restoring the original | |
| 2060 | +** rowid value using [sqlite3_set_last_insert_rowid()] before returning | |
| 2061 | +** control to the user. | |
| 2062 | +** | |
| 2063 | +** ^(If an [INSERT] occurs within a trigger then this routine will | |
| 2064 | +** return the [rowid] of the inserted row as long as the trigger is | |
| 2065 | +** running. Once the trigger program ends, the value returned | |
| 2066 | +** by this routine reverts to what it was before the trigger was fired.)^ | |
| 2057 | 2067 | ** |
| 2058 | 2068 | ** ^An [INSERT] that fails due to a constraint violation is not a |
| 2059 | 2069 | ** successful [INSERT] and does not change the value returned by this |
| 2060 | 2070 | ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, |
| 2061 | 2071 | ** and INSERT OR ABORT make no changes to the return value of this |
| @@ -2078,10 +2088,20 @@ | ||
| 2078 | 2088 | ** unpredictable and might not equal either the old or the new |
| 2079 | 2089 | ** last insert [rowid]. |
| 2080 | 2090 | */ |
| 2081 | 2091 | SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); |
| 2082 | 2092 | |
| 2093 | +/* | |
| 2094 | +** CAPI3REF: Set the Last Insert Rowid value. | |
| 2095 | +** METHOD: sqlite3 | |
| 2096 | +** | |
| 2097 | +** The sqlite3_set_last_insert_rowid(D, R) method allows the application to | |
| 2098 | +** set the value returned by calling sqlite3_last_insert_rowid(D) to R | |
| 2099 | +** without inserting a row into the database. | |
| 2100 | +*/ | |
| 2101 | +SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); | |
| 2102 | + | |
| 2083 | 2103 | /* |
| 2084 | 2104 | ** CAPI3REF: Count The Number Of Rows Modified |
| 2085 | 2105 | ** METHOD: sqlite3 |
| 2086 | 2106 | ** |
| 2087 | 2107 | ** ^This function returns the number of rows modified, inserted or |
| 2088 | 2108 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,13 +119,13 @@ | |
| 119 | ** |
| 120 | ** See also: [sqlite3_libversion()], |
| 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | */ |
| 124 | #define SQLITE_VERSION "3.17.0" |
| 125 | #define SQLITE_VERSION_NUMBER 3017000 |
| 126 | #define SQLITE_SOURCE_ID "2017-02-13 16:02:40 ada05cfa86ad7f5645450ac7a2a21c9aa6e57d2c" |
| 127 | |
| 128 | /* |
| 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 131 | ** |
| @@ -2038,24 +2038,34 @@ | |
| 2038 | ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those |
| 2039 | ** names are not also used by explicitly declared columns. ^If |
| 2040 | ** the table has a column of type [INTEGER PRIMARY KEY] then that column |
| 2041 | ** is another alias for the rowid. |
| 2042 | ** |
| 2043 | ** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the |
| 2044 | ** most recent successful [INSERT] into a rowid table or [virtual table] |
| 2045 | ** on database connection D. |
| 2046 | ** ^Inserts into [WITHOUT ROWID] tables are not recorded. |
| 2047 | ** ^If no successful [INSERT]s into rowid tables |
| 2048 | ** have ever occurred on the database connection D, |
| 2049 | ** then sqlite3_last_insert_rowid(D) returns zero. |
| 2050 | ** |
| 2051 | ** ^(If an [INSERT] occurs within a trigger or within a [virtual table] |
| 2052 | ** method, then this routine will return the [rowid] of the inserted |
| 2053 | ** row as long as the trigger or virtual table method is running. |
| 2054 | ** But once the trigger or virtual table method ends, the value returned |
| 2055 | ** by this routine reverts to what it was before the trigger or virtual |
| 2056 | ** table method began.)^ |
| 2057 | ** |
| 2058 | ** ^An [INSERT] that fails due to a constraint violation is not a |
| 2059 | ** successful [INSERT] and does not change the value returned by this |
| 2060 | ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, |
| 2061 | ** and INSERT OR ABORT make no changes to the return value of this |
| @@ -2078,10 +2088,20 @@ | |
| 2078 | ** unpredictable and might not equal either the old or the new |
| 2079 | ** last insert [rowid]. |
| 2080 | */ |
| 2081 | SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); |
| 2082 | |
| 2083 | /* |
| 2084 | ** CAPI3REF: Count The Number Of Rows Modified |
| 2085 | ** METHOD: sqlite3 |
| 2086 | ** |
| 2087 | ** ^This function returns the number of rows modified, inserted or |
| 2088 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,13 +119,13 @@ | |
| 119 | ** |
| 120 | ** See also: [sqlite3_libversion()], |
| 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | */ |
| 124 | #define SQLITE_VERSION "3.18.0" |
| 125 | #define SQLITE_VERSION_NUMBER 3018000 |
| 126 | #define SQLITE_SOURCE_ID "2017-03-10 17:03:11 f8560c60d10c0365b33342ab05b5a953987b0471" |
| 127 | |
| 128 | /* |
| 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 131 | ** |
| @@ -2038,24 +2038,34 @@ | |
| 2038 | ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those |
| 2039 | ** names are not also used by explicitly declared columns. ^If |
| 2040 | ** the table has a column of type [INTEGER PRIMARY KEY] then that column |
| 2041 | ** is another alias for the rowid. |
| 2042 | ** |
| 2043 | ** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of |
| 2044 | ** the most recent successful [INSERT] into a rowid table or [virtual table] |
| 2045 | ** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not |
| 2046 | ** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred |
| 2047 | ** on the database connection D, then sqlite3_last_insert_rowid(D) returns |
| 2048 | ** zero. |
| 2049 | ** |
| 2050 | ** As well as being set automatically as rows are inserted into database |
| 2051 | ** tables, the value returned by this function may be set explicitly by |
| 2052 | ** [sqlite3_set_last_insert_rowid()] |
| 2053 | ** |
| 2054 | ** Some virtual table implementations may INSERT rows into rowid tables as |
| 2055 | ** part of committing a transaction (e.g. to flush data accumulated in memory |
| 2056 | ** to disk). In this case subsequent calls to this function return the rowid |
| 2057 | ** associated with these internal INSERT operations, which leads to |
| 2058 | ** unintuitive results. Virtual table implementations that do write to rowid |
| 2059 | ** tables in this way can avoid this problem by restoring the original |
| 2060 | ** rowid value using [sqlite3_set_last_insert_rowid()] before returning |
| 2061 | ** control to the user. |
| 2062 | ** |
| 2063 | ** ^(If an [INSERT] occurs within a trigger then this routine will |
| 2064 | ** return the [rowid] of the inserted row as long as the trigger is |
| 2065 | ** running. Once the trigger program ends, the value returned |
| 2066 | ** by this routine reverts to what it was before the trigger was fired.)^ |
| 2067 | ** |
| 2068 | ** ^An [INSERT] that fails due to a constraint violation is not a |
| 2069 | ** successful [INSERT] and does not change the value returned by this |
| 2070 | ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, |
| 2071 | ** and INSERT OR ABORT make no changes to the return value of this |
| @@ -2078,10 +2088,20 @@ | |
| 2088 | ** unpredictable and might not equal either the old or the new |
| 2089 | ** last insert [rowid]. |
| 2090 | */ |
| 2091 | SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); |
| 2092 | |
| 2093 | /* |
| 2094 | ** CAPI3REF: Set the Last Insert Rowid value. |
| 2095 | ** METHOD: sqlite3 |
| 2096 | ** |
| 2097 | ** The sqlite3_set_last_insert_rowid(D, R) method allows the application to |
| 2098 | ** set the value returned by calling sqlite3_last_insert_rowid(D) to R |
| 2099 | ** without inserting a row into the database. |
| 2100 | */ |
| 2101 | SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); |
| 2102 | |
| 2103 | /* |
| 2104 | ** CAPI3REF: Count The Number Of Rows Modified |
| 2105 | ** METHOD: sqlite3 |
| 2106 | ** |
| 2107 | ** ^This function returns the number of rows modified, inserted or |
| 2108 |
+35
-32
| --- src/stash.c | ||
| +++ src/stash.c | ||
| @@ -332,52 +332,45 @@ | ||
| 332 | 332 | isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a); |
| 333 | 333 | diff_file_mem(&empty, &a, isBin1, isBin2, zNew, zDiffCmd, |
| 334 | 334 | zBinGlob, fIncludeBinary, diffFlags); |
| 335 | 335 | }else if( isRemoved ){ |
| 336 | 336 | fossil_print("DELETE %s\n", zOrig); |
| 337 | - if( fBaseline==0 ){ | |
| 338 | - if( file_wd_islink(zOPath) ){ | |
| 339 | - blob_read_link(&a, zOPath); | |
| 340 | - }else{ | |
| 341 | - blob_read_from_file(&a, zOPath); | |
| 342 | - } | |
| 343 | - }else{ | |
| 344 | - content_get(rid, &a); | |
| 345 | - } | |
| 346 | - diff_print_index(zNew, diffFlags); | |
| 347 | - isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); | |
| 348 | - isBin2 = 0; | |
| 349 | - diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd, | |
| 350 | - zBinGlob, fIncludeBinary, diffFlags); | |
| 351 | - }else{ | |
| 352 | - Blob delta, disk; | |
| 337 | + diff_print_index(zNew, diffFlags); | |
| 338 | + isBin2 = 0; | |
| 339 | + if( fBaseline ){ | |
| 340 | + content_get(rid, &a); | |
| 341 | + isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); | |
| 342 | + diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd, | |
| 343 | + zBinGlob, fIncludeBinary, diffFlags); | |
| 344 | + }else{ | |
| 345 | + } | |
| 346 | + }else{ | |
| 347 | + Blob delta; | |
| 353 | 348 | int isOrigLink = file_wd_islink(zOPath); |
| 354 | 349 | db_ephemeral_blob(&q, 6, &delta); |
| 355 | - if( fBaseline==0 ){ | |
| 356 | - if( isOrigLink ){ | |
| 357 | - blob_read_link(&disk, zOPath); | |
| 358 | - }else{ | |
| 359 | - blob_read_from_file(&disk, zOPath); | |
| 360 | - } | |
| 361 | - } | |
| 362 | 350 | fossil_print("CHANGED %s\n", zNew); |
| 363 | 351 | if( !isOrigLink != !isLink ){ |
| 364 | 352 | diff_print_index(zNew, diffFlags); |
| 365 | 353 | diff_print_filenames(zOrig, zNew, diffFlags); |
| 366 | 354 | printf(DIFF_CANNOT_COMPUTE_SYMLINK); |
| 367 | 355 | }else{ |
| 368 | - Blob *pBase = fBaseline ? &a : &disk; | |
| 369 | 356 | content_get(rid, &a); |
| 370 | 357 | blob_delta_apply(&a, &delta, &b); |
| 371 | - isBin1 = fIncludeBinary ? 0 : looks_like_binary(pBase); | |
| 358 | + isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); | |
| 372 | 359 | isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b); |
| 373 | - diff_file_mem(fBaseline? &a : &disk, &b, isBin1, isBin2, zNew, | |
| 374 | - zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); | |
| 360 | + if( fBaseline ){ | |
| 361 | + diff_file_mem(&a, &b, isBin1, isBin2, zNew, | |
| 362 | + zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); | |
| 363 | + }else{ | |
| 364 | + /*Diff with file on disk using fSwapDiff=1 to show the diff in the | |
| 365 | + same direction as if fBaseline=1.*/ | |
| 366 | + diff_file(&b, isBin2, zOPath, zNew, zDiffCmd, | |
| 367 | + zBinGlob, fIncludeBinary, diffFlags, 1); | |
| 368 | + } | |
| 375 | 369 | blob_reset(&a); |
| 376 | 370 | blob_reset(&b); |
| 377 | 371 | } |
| 378 | - if( !fBaseline ) blob_reset(&disk); | |
| 379 | 372 | blob_reset(&delta); |
| 380 | 373 | } |
| 381 | 374 | } |
| 382 | 375 | db_finalize(&q); |
| 383 | 376 | } |
| @@ -433,12 +426,15 @@ | ||
| 433 | 426 | ** |
| 434 | 427 | ** List all changes sets currently stashed. Show information about |
| 435 | 428 | ** individual files in each changeset if -v or --verbose is used. |
| 436 | 429 | ** |
| 437 | 430 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 431 | +** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS? | |
| 438 | 432 | ** |
| 439 | -** Show the contents of a stash. | |
| 433 | +** Show the contents of a stash as a diff against it's baseline. | |
| 434 | +** With gshow and gcat, gdiff-command is used instead of internal | |
| 435 | +** diff logic. | |
| 440 | 436 | ** |
| 441 | 437 | ** fossil stash pop |
| 442 | 438 | ** fossil stash apply ?STASHID? |
| 443 | 439 | ** |
| 444 | 440 | ** Apply STASHID or the most recently create stash to the current |
| @@ -460,18 +456,20 @@ | ||
| 460 | 456 | ** |
| 461 | 457 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 462 | 458 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| 463 | 459 | ** |
| 464 | 460 | ** Show diffs of the current working directory and what that |
| 465 | -** directory would be if STASHID were applied. | |
| 461 | +** directory would be if STASHID were applied. With gdiff, | |
| 462 | +** gdiff-command is used instead of internal diff logic. | |
| 466 | 463 | ** |
| 467 | 464 | ** SUMMARY: |
| 468 | 465 | ** fossil stash |
| 469 | 466 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 470 | 467 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 471 | 468 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 472 | 469 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 470 | +** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS? | |
| 473 | 471 | ** fossil stash pop |
| 474 | 472 | ** fossil stash apply|goto ?STASHID? |
| 475 | 473 | ** fossil stash drop|rm ?STASHID? ?-a|--all? |
| 476 | 474 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 477 | 475 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| @@ -654,25 +652,30 @@ | ||
| 654 | 652 | undo_finish(); |
| 655 | 653 | }else |
| 656 | 654 | if( memcmp(zCmd, "diff", nCmd)==0 |
| 657 | 655 | || memcmp(zCmd, "gdiff", nCmd)==0 |
| 658 | 656 | || memcmp(zCmd, "show", nCmd)==0 |
| 657 | + || memcmp(zCmd, "gshow", nCmd)==0 | |
| 659 | 658 | || memcmp(zCmd, "cat", nCmd)==0 |
| 659 | + || memcmp(zCmd, "gcat", nCmd)==0 | |
| 660 | 660 | ){ |
| 661 | 661 | const char *zDiffCmd = 0; |
| 662 | 662 | const char *zBinGlob = 0; |
| 663 | 663 | int fIncludeBinary = 0; |
| 664 | - int fBaseline = zCmd[0]=='s' || zCmd[0]=='c'; | |
| 664 | + int fBaseline = 0; | |
| 665 | 665 | u64 diffFlags; |
| 666 | 666 | |
| 667 | + if( strstr(zCmd,"show")!=0 || strstr(zCmd,"cat")!=0 ){ | |
| 668 | + fBaseline = 1; | |
| 669 | + } | |
| 667 | 670 | if( find_option("tk",0,0)!=0 ){ |
| 668 | 671 | db_close(0); |
| 669 | 672 | diff_tk(fBaseline ? "stash show" : "stash diff", 3); |
| 670 | 673 | return; |
| 671 | 674 | } |
| 672 | 675 | if( find_option("internal","i",0)==0 ){ |
| 673 | - zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); | |
| 676 | + zDiffCmd = diff_command_external(zCmd[0]=='g'); | |
| 674 | 677 | } |
| 675 | 678 | diffFlags = diff_options(); |
| 676 | 679 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 677 | 680 | if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd)); |
| 678 | 681 | if( zDiffCmd ){ |
| 679 | 682 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -332,52 +332,45 @@ | |
| 332 | isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a); |
| 333 | diff_file_mem(&empty, &a, isBin1, isBin2, zNew, zDiffCmd, |
| 334 | zBinGlob, fIncludeBinary, diffFlags); |
| 335 | }else if( isRemoved ){ |
| 336 | fossil_print("DELETE %s\n", zOrig); |
| 337 | if( fBaseline==0 ){ |
| 338 | if( file_wd_islink(zOPath) ){ |
| 339 | blob_read_link(&a, zOPath); |
| 340 | }else{ |
| 341 | blob_read_from_file(&a, zOPath); |
| 342 | } |
| 343 | }else{ |
| 344 | content_get(rid, &a); |
| 345 | } |
| 346 | diff_print_index(zNew, diffFlags); |
| 347 | isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); |
| 348 | isBin2 = 0; |
| 349 | diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd, |
| 350 | zBinGlob, fIncludeBinary, diffFlags); |
| 351 | }else{ |
| 352 | Blob delta, disk; |
| 353 | int isOrigLink = file_wd_islink(zOPath); |
| 354 | db_ephemeral_blob(&q, 6, &delta); |
| 355 | if( fBaseline==0 ){ |
| 356 | if( isOrigLink ){ |
| 357 | blob_read_link(&disk, zOPath); |
| 358 | }else{ |
| 359 | blob_read_from_file(&disk, zOPath); |
| 360 | } |
| 361 | } |
| 362 | fossil_print("CHANGED %s\n", zNew); |
| 363 | if( !isOrigLink != !isLink ){ |
| 364 | diff_print_index(zNew, diffFlags); |
| 365 | diff_print_filenames(zOrig, zNew, diffFlags); |
| 366 | printf(DIFF_CANNOT_COMPUTE_SYMLINK); |
| 367 | }else{ |
| 368 | Blob *pBase = fBaseline ? &a : &disk; |
| 369 | content_get(rid, &a); |
| 370 | blob_delta_apply(&a, &delta, &b); |
| 371 | isBin1 = fIncludeBinary ? 0 : looks_like_binary(pBase); |
| 372 | isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b); |
| 373 | diff_file_mem(fBaseline? &a : &disk, &b, isBin1, isBin2, zNew, |
| 374 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); |
| 375 | blob_reset(&a); |
| 376 | blob_reset(&b); |
| 377 | } |
| 378 | if( !fBaseline ) blob_reset(&disk); |
| 379 | blob_reset(&delta); |
| 380 | } |
| 381 | } |
| 382 | db_finalize(&q); |
| 383 | } |
| @@ -433,12 +426,15 @@ | |
| 433 | ** |
| 434 | ** List all changes sets currently stashed. Show information about |
| 435 | ** individual files in each changeset if -v or --verbose is used. |
| 436 | ** |
| 437 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 438 | ** |
| 439 | ** Show the contents of a stash. |
| 440 | ** |
| 441 | ** fossil stash pop |
| 442 | ** fossil stash apply ?STASHID? |
| 443 | ** |
| 444 | ** Apply STASHID or the most recently create stash to the current |
| @@ -460,18 +456,20 @@ | |
| 460 | ** |
| 461 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 462 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| 463 | ** |
| 464 | ** Show diffs of the current working directory and what that |
| 465 | ** directory would be if STASHID were applied. |
| 466 | ** |
| 467 | ** SUMMARY: |
| 468 | ** fossil stash |
| 469 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 470 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 471 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 472 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 473 | ** fossil stash pop |
| 474 | ** fossil stash apply|goto ?STASHID? |
| 475 | ** fossil stash drop|rm ?STASHID? ?-a|--all? |
| 476 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 477 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| @@ -654,25 +652,30 @@ | |
| 654 | undo_finish(); |
| 655 | }else |
| 656 | if( memcmp(zCmd, "diff", nCmd)==0 |
| 657 | || memcmp(zCmd, "gdiff", nCmd)==0 |
| 658 | || memcmp(zCmd, "show", nCmd)==0 |
| 659 | || memcmp(zCmd, "cat", nCmd)==0 |
| 660 | ){ |
| 661 | const char *zDiffCmd = 0; |
| 662 | const char *zBinGlob = 0; |
| 663 | int fIncludeBinary = 0; |
| 664 | int fBaseline = zCmd[0]=='s' || zCmd[0]=='c'; |
| 665 | u64 diffFlags; |
| 666 | |
| 667 | if( find_option("tk",0,0)!=0 ){ |
| 668 | db_close(0); |
| 669 | diff_tk(fBaseline ? "stash show" : "stash diff", 3); |
| 670 | return; |
| 671 | } |
| 672 | if( find_option("internal","i",0)==0 ){ |
| 673 | zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); |
| 674 | } |
| 675 | diffFlags = diff_options(); |
| 676 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 677 | if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd)); |
| 678 | if( zDiffCmd ){ |
| 679 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -332,52 +332,45 @@ | |
| 332 | isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a); |
| 333 | diff_file_mem(&empty, &a, isBin1, isBin2, zNew, zDiffCmd, |
| 334 | zBinGlob, fIncludeBinary, diffFlags); |
| 335 | }else if( isRemoved ){ |
| 336 | fossil_print("DELETE %s\n", zOrig); |
| 337 | diff_print_index(zNew, diffFlags); |
| 338 | isBin2 = 0; |
| 339 | if( fBaseline ){ |
| 340 | content_get(rid, &a); |
| 341 | isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); |
| 342 | diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd, |
| 343 | zBinGlob, fIncludeBinary, diffFlags); |
| 344 | }else{ |
| 345 | } |
| 346 | }else{ |
| 347 | Blob delta; |
| 348 | int isOrigLink = file_wd_islink(zOPath); |
| 349 | db_ephemeral_blob(&q, 6, &delta); |
| 350 | fossil_print("CHANGED %s\n", zNew); |
| 351 | if( !isOrigLink != !isLink ){ |
| 352 | diff_print_index(zNew, diffFlags); |
| 353 | diff_print_filenames(zOrig, zNew, diffFlags); |
| 354 | printf(DIFF_CANNOT_COMPUTE_SYMLINK); |
| 355 | }else{ |
| 356 | content_get(rid, &a); |
| 357 | blob_delta_apply(&a, &delta, &b); |
| 358 | isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); |
| 359 | isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b); |
| 360 | if( fBaseline ){ |
| 361 | diff_file_mem(&a, &b, isBin1, isBin2, zNew, |
| 362 | zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); |
| 363 | }else{ |
| 364 | /*Diff with file on disk using fSwapDiff=1 to show the diff in the |
| 365 | same direction as if fBaseline=1.*/ |
| 366 | diff_file(&b, isBin2, zOPath, zNew, zDiffCmd, |
| 367 | zBinGlob, fIncludeBinary, diffFlags, 1); |
| 368 | } |
| 369 | blob_reset(&a); |
| 370 | blob_reset(&b); |
| 371 | } |
| 372 | blob_reset(&delta); |
| 373 | } |
| 374 | } |
| 375 | db_finalize(&q); |
| 376 | } |
| @@ -433,12 +426,15 @@ | |
| 426 | ** |
| 427 | ** List all changes sets currently stashed. Show information about |
| 428 | ** individual files in each changeset if -v or --verbose is used. |
| 429 | ** |
| 430 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 431 | ** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS? |
| 432 | ** |
| 433 | ** Show the contents of a stash as a diff against it's baseline. |
| 434 | ** With gshow and gcat, gdiff-command is used instead of internal |
| 435 | ** diff logic. |
| 436 | ** |
| 437 | ** fossil stash pop |
| 438 | ** fossil stash apply ?STASHID? |
| 439 | ** |
| 440 | ** Apply STASHID or the most recently create stash to the current |
| @@ -460,18 +456,20 @@ | |
| 456 | ** |
| 457 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 458 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| 459 | ** |
| 460 | ** Show diffs of the current working directory and what that |
| 461 | ** directory would be if STASHID were applied. With gdiff, |
| 462 | ** gdiff-command is used instead of internal diff logic. |
| 463 | ** |
| 464 | ** SUMMARY: |
| 465 | ** fossil stash |
| 466 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 467 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 468 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 469 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 470 | ** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS? |
| 471 | ** fossil stash pop |
| 472 | ** fossil stash apply|goto ?STASHID? |
| 473 | ** fossil stash drop|rm ?STASHID? ?-a|--all? |
| 474 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 475 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| @@ -654,25 +652,30 @@ | |
| 652 | undo_finish(); |
| 653 | }else |
| 654 | if( memcmp(zCmd, "diff", nCmd)==0 |
| 655 | || memcmp(zCmd, "gdiff", nCmd)==0 |
| 656 | || memcmp(zCmd, "show", nCmd)==0 |
| 657 | || memcmp(zCmd, "gshow", nCmd)==0 |
| 658 | || memcmp(zCmd, "cat", nCmd)==0 |
| 659 | || memcmp(zCmd, "gcat", nCmd)==0 |
| 660 | ){ |
| 661 | const char *zDiffCmd = 0; |
| 662 | const char *zBinGlob = 0; |
| 663 | int fIncludeBinary = 0; |
| 664 | int fBaseline = 0; |
| 665 | u64 diffFlags; |
| 666 | |
| 667 | if( strstr(zCmd,"show")!=0 || strstr(zCmd,"cat")!=0 ){ |
| 668 | fBaseline = 1; |
| 669 | } |
| 670 | if( find_option("tk",0,0)!=0 ){ |
| 671 | db_close(0); |
| 672 | diff_tk(fBaseline ? "stash show" : "stash diff", 3); |
| 673 | return; |
| 674 | } |
| 675 | if( find_option("internal","i",0)==0 ){ |
| 676 | zDiffCmd = diff_command_external(zCmd[0]=='g'); |
| 677 | } |
| 678 | diffFlags = diff_options(); |
| 679 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 680 | if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd)); |
| 681 | if( zDiffCmd ){ |
| 682 |
+71
-4
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -76,11 +76,11 @@ | ||
| 76 | 76 | style_submenu_element("URLs", "urllist"); |
| 77 | 77 | style_submenu_element("Schema", "repo_schema"); |
| 78 | 78 | style_submenu_element("Web-Cache", "cachestat"); |
| 79 | 79 | } |
| 80 | 80 | style_submenu_element("Activity Reports", "reports"); |
| 81 | - style_submenu_element("SHA1 Collisions", "hash-collisions"); | |
| 81 | + style_submenu_element("Hash Collisions", "hash-collisions"); | |
| 82 | 82 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 83 | 83 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 84 | 84 | } |
| 85 | 85 | if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ |
| 86 | 86 | style_submenu_element("Environment", "test_env"); |
| @@ -183,11 +183,16 @@ | ||
| 183 | 183 | @ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a> |
| 184 | 184 | @ </td></tr> |
| 185 | 185 | @ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid()) |
| 186 | 186 | @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion())) |
| 187 | 187 | @ <a href='version?verbose=2'>(details)</a></td></tr> |
| 188 | - @ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema)</td></tr> | |
| 188 | + if( g.eHashPolicy!=HPOLICY_AUTO ){ | |
| 189 | + @ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema), | |
| 190 | + @ %s(hpolicy_name())</td></tr> | |
| 191 | + }else{ | |
| 192 | + @ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema)</td></tr> | |
| 193 | + } | |
| 189 | 194 | @ <tr><th>Repository Rebuilt:</th><td> |
| 190 | 195 | @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never")) |
| 191 | 196 | @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr> |
| 192 | 197 | @ <tr><th>Database Stats:</th><td> |
| 193 | 198 | @ %d(db_int(0, "PRAGMA repository.page_count")) pages, |
| @@ -383,10 +388,12 @@ | ||
| 383 | 388 | ** |
| 384 | 389 | ** Show the repository schema |
| 385 | 390 | */ |
| 386 | 391 | void repo_schema_page(void){ |
| 387 | 392 | Stmt q; |
| 393 | + Blob sql; | |
| 394 | + const char *zArg = P("n"); | |
| 388 | 395 | login_check_credentials(); |
| 389 | 396 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 390 | 397 | |
| 391 | 398 | style_header("Repository Schema"); |
| 392 | 399 | style_adunit_config(ADUNIT_RIGHT_OK); |
| @@ -393,18 +400,78 @@ | ||
| 393 | 400 | style_submenu_element("Stat", "stat"); |
| 394 | 401 | style_submenu_element("URLs", "urllist"); |
| 395 | 402 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 396 | 403 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 397 | 404 | } |
| 398 | - db_prepare(&q, | |
| 399 | - "SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL"); | |
| 405 | + blob_init(&sql, | |
| 406 | + "SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL", -1); | |
| 407 | + if( zArg ){ | |
| 408 | + style_submenu_element("All", "repo_schema"); | |
| 409 | + blob_appendf(&sql, " AND (tbl_name=%Q OR name=%Q)", zArg, zArg); | |
| 410 | + } | |
| 411 | + blob_appendf(&sql, " ORDER BY tbl_name, type<>'table', name"); | |
| 412 | + db_prepare(&q, "%s", blob_str(&sql)/*safe-for-%s*/); | |
| 413 | + blob_reset(&sql); | |
| 400 | 414 | @ <pre> |
| 401 | 415 | while( db_step(&q)==SQLITE_ROW ){ |
| 402 | 416 | @ %h(db_column_text(&q, 0)); |
| 403 | 417 | } |
| 404 | 418 | @ </pre> |
| 405 | 419 | db_finalize(&q); |
| 420 | + if( db_table_exists("repository","sqlite_stat1") ){ | |
| 421 | + if( zArg ){ | |
| 422 | + db_prepare(&q, | |
| 423 | + "SELECT tbl, idx, stat FROM repository.sqlite_stat1" | |
| 424 | + " WHERE tbl LIKE %Q OR idx LIKE %Q" | |
| 425 | + " ORDER BY tbl, idx", zArg, zArg); | |
| 426 | + | |
| 427 | + @ <hr> | |
| 428 | + @ <pre> | |
| 429 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 430 | + const char *zTab = db_column_text(&q,0); | |
| 431 | + const char *zIdx = db_column_text(&q,1); | |
| 432 | + const char *zStat = db_column_text(&q,2); | |
| 433 | + @ INSERT INTO sqlite_stat1 VALUES('%h(zTab)','%h(zIdx)','%h(zStat)'); | |
| 434 | + } | |
| 435 | + @ </pre> | |
| 436 | + db_finalize(&q); | |
| 437 | + }else{ | |
| 438 | + style_submenu_element("Stat1","repo_stat1"); | |
| 439 | + } | |
| 440 | + } | |
| 441 | + style_footer(); | |
| 442 | +} | |
| 443 | + | |
| 444 | +/* | |
| 445 | +** WEBPAGE: repo_stat1 | |
| 446 | +** | |
| 447 | +** Show the sqlite_stat1 table for the repository schema | |
| 448 | +*/ | |
| 449 | +void repo_stat1_page(void){ | |
| 450 | + login_check_credentials(); | |
| 451 | + if( !g.perm.Admin ){ login_needed(0); return; } | |
| 452 | + | |
| 453 | + style_header("Repository STAT1 Table"); | |
| 454 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 455 | + style_submenu_element("Stat", "stat"); | |
| 456 | + style_submenu_element("Schema", "repo_schema"); | |
| 457 | + if( db_table_exists("repository","sqlite_stat1") ){ | |
| 458 | + Stmt q; | |
| 459 | + db_prepare(&q, | |
| 460 | + "SELECT tbl, idx, stat FROM repository.sqlite_stat1" | |
| 461 | + " ORDER BY tbl, idx"); | |
| 462 | + @ <pre> | |
| 463 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 464 | + const char *zTab = db_column_text(&q,0); | |
| 465 | + const char *zIdx = db_column_text(&q,1); | |
| 466 | + const char *zStat = db_column_text(&q,2); | |
| 467 | + char *zUrl = href("%R/repo_schema?n=%t",zTab); | |
| 468 | + @ INSERT INTO sqlite_stat1 VALUES('%z(zUrl)%h(zTab)</a>','%h(zIdx)','%h(zStat)'); | |
| 469 | + } | |
| 470 | + @ </pre> | |
| 471 | + db_finalize(&q); | |
| 472 | + } | |
| 406 | 473 | style_footer(); |
| 407 | 474 | } |
| 408 | 475 | |
| 409 | 476 | /* |
| 410 | 477 | ** WEBPAGE: repo-tabsize |
| 411 | 478 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -76,11 +76,11 @@ | |
| 76 | style_submenu_element("URLs", "urllist"); |
| 77 | style_submenu_element("Schema", "repo_schema"); |
| 78 | style_submenu_element("Web-Cache", "cachestat"); |
| 79 | } |
| 80 | style_submenu_element("Activity Reports", "reports"); |
| 81 | style_submenu_element("SHA1 Collisions", "hash-collisions"); |
| 82 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 83 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 84 | } |
| 85 | if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ |
| 86 | style_submenu_element("Environment", "test_env"); |
| @@ -183,11 +183,16 @@ | |
| 183 | @ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a> |
| 184 | @ </td></tr> |
| 185 | @ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid()) |
| 186 | @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion())) |
| 187 | @ <a href='version?verbose=2'>(details)</a></td></tr> |
| 188 | @ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema)</td></tr> |
| 189 | @ <tr><th>Repository Rebuilt:</th><td> |
| 190 | @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never")) |
| 191 | @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr> |
| 192 | @ <tr><th>Database Stats:</th><td> |
| 193 | @ %d(db_int(0, "PRAGMA repository.page_count")) pages, |
| @@ -383,10 +388,12 @@ | |
| 383 | ** |
| 384 | ** Show the repository schema |
| 385 | */ |
| 386 | void repo_schema_page(void){ |
| 387 | Stmt q; |
| 388 | login_check_credentials(); |
| 389 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 390 | |
| 391 | style_header("Repository Schema"); |
| 392 | style_adunit_config(ADUNIT_RIGHT_OK); |
| @@ -393,18 +400,78 @@ | |
| 393 | style_submenu_element("Stat", "stat"); |
| 394 | style_submenu_element("URLs", "urllist"); |
| 395 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 396 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 397 | } |
| 398 | db_prepare(&q, |
| 399 | "SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL"); |
| 400 | @ <pre> |
| 401 | while( db_step(&q)==SQLITE_ROW ){ |
| 402 | @ %h(db_column_text(&q, 0)); |
| 403 | } |
| 404 | @ </pre> |
| 405 | db_finalize(&q); |
| 406 | style_footer(); |
| 407 | } |
| 408 | |
| 409 | /* |
| 410 | ** WEBPAGE: repo-tabsize |
| 411 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -76,11 +76,11 @@ | |
| 76 | style_submenu_element("URLs", "urllist"); |
| 77 | style_submenu_element("Schema", "repo_schema"); |
| 78 | style_submenu_element("Web-Cache", "cachestat"); |
| 79 | } |
| 80 | style_submenu_element("Activity Reports", "reports"); |
| 81 | style_submenu_element("Hash Collisions", "hash-collisions"); |
| 82 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 83 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 84 | } |
| 85 | if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ |
| 86 | style_submenu_element("Environment", "test_env"); |
| @@ -183,11 +183,16 @@ | |
| 183 | @ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a> |
| 184 | @ </td></tr> |
| 185 | @ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid()) |
| 186 | @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion())) |
| 187 | @ <a href='version?verbose=2'>(details)</a></td></tr> |
| 188 | if( g.eHashPolicy!=HPOLICY_AUTO ){ |
| 189 | @ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema), |
| 190 | @ %s(hpolicy_name())</td></tr> |
| 191 | }else{ |
| 192 | @ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema)</td></tr> |
| 193 | } |
| 194 | @ <tr><th>Repository Rebuilt:</th><td> |
| 195 | @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never")) |
| 196 | @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr> |
| 197 | @ <tr><th>Database Stats:</th><td> |
| 198 | @ %d(db_int(0, "PRAGMA repository.page_count")) pages, |
| @@ -383,10 +388,12 @@ | |
| 388 | ** |
| 389 | ** Show the repository schema |
| 390 | */ |
| 391 | void repo_schema_page(void){ |
| 392 | Stmt q; |
| 393 | Blob sql; |
| 394 | const char *zArg = P("n"); |
| 395 | login_check_credentials(); |
| 396 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 397 | |
| 398 | style_header("Repository Schema"); |
| 399 | style_adunit_config(ADUNIT_RIGHT_OK); |
| @@ -393,18 +400,78 @@ | |
| 400 | style_submenu_element("Stat", "stat"); |
| 401 | style_submenu_element("URLs", "urllist"); |
| 402 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 403 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 404 | } |
| 405 | blob_init(&sql, |
| 406 | "SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL", -1); |
| 407 | if( zArg ){ |
| 408 | style_submenu_element("All", "repo_schema"); |
| 409 | blob_appendf(&sql, " AND (tbl_name=%Q OR name=%Q)", zArg, zArg); |
| 410 | } |
| 411 | blob_appendf(&sql, " ORDER BY tbl_name, type<>'table', name"); |
| 412 | db_prepare(&q, "%s", blob_str(&sql)/*safe-for-%s*/); |
| 413 | blob_reset(&sql); |
| 414 | @ <pre> |
| 415 | while( db_step(&q)==SQLITE_ROW ){ |
| 416 | @ %h(db_column_text(&q, 0)); |
| 417 | } |
| 418 | @ </pre> |
| 419 | db_finalize(&q); |
| 420 | if( db_table_exists("repository","sqlite_stat1") ){ |
| 421 | if( zArg ){ |
| 422 | db_prepare(&q, |
| 423 | "SELECT tbl, idx, stat FROM repository.sqlite_stat1" |
| 424 | " WHERE tbl LIKE %Q OR idx LIKE %Q" |
| 425 | " ORDER BY tbl, idx", zArg, zArg); |
| 426 | |
| 427 | @ <hr> |
| 428 | @ <pre> |
| 429 | while( db_step(&q)==SQLITE_ROW ){ |
| 430 | const char *zTab = db_column_text(&q,0); |
| 431 | const char *zIdx = db_column_text(&q,1); |
| 432 | const char *zStat = db_column_text(&q,2); |
| 433 | @ INSERT INTO sqlite_stat1 VALUES('%h(zTab)','%h(zIdx)','%h(zStat)'); |
| 434 | } |
| 435 | @ </pre> |
| 436 | db_finalize(&q); |
| 437 | }else{ |
| 438 | style_submenu_element("Stat1","repo_stat1"); |
| 439 | } |
| 440 | } |
| 441 | style_footer(); |
| 442 | } |
| 443 | |
| 444 | /* |
| 445 | ** WEBPAGE: repo_stat1 |
| 446 | ** |
| 447 | ** Show the sqlite_stat1 table for the repository schema |
| 448 | */ |
| 449 | void repo_stat1_page(void){ |
| 450 | login_check_credentials(); |
| 451 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 452 | |
| 453 | style_header("Repository STAT1 Table"); |
| 454 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 455 | style_submenu_element("Stat", "stat"); |
| 456 | style_submenu_element("Schema", "repo_schema"); |
| 457 | if( db_table_exists("repository","sqlite_stat1") ){ |
| 458 | Stmt q; |
| 459 | db_prepare(&q, |
| 460 | "SELECT tbl, idx, stat FROM repository.sqlite_stat1" |
| 461 | " ORDER BY tbl, idx"); |
| 462 | @ <pre> |
| 463 | while( db_step(&q)==SQLITE_ROW ){ |
| 464 | const char *zTab = db_column_text(&q,0); |
| 465 | const char *zIdx = db_column_text(&q,1); |
| 466 | const char *zStat = db_column_text(&q,2); |
| 467 | char *zUrl = href("%R/repo_schema?n=%t",zTab); |
| 468 | @ INSERT INTO sqlite_stat1 VALUES('%z(zUrl)%h(zTab)</a>','%h(zIdx)','%h(zStat)'); |
| 469 | } |
| 470 | @ </pre> |
| 471 | db_finalize(&q); |
| 472 | } |
| 473 | style_footer(); |
| 474 | } |
| 475 | |
| 476 | /* |
| 477 | ** WEBPAGE: repo-tabsize |
| 478 |
+1
-1
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -627,11 +627,11 @@ | ||
| 627 | 627 | blob_init(&value, 0, 0); |
| 628 | 628 | for(i=3; i<g.argc; i++){ |
| 629 | 629 | int pid = name_to_typed_rid(g.argv[i], "ci"); |
| 630 | 630 | if( i>3 ) blob_append(&value, " ", 1); |
| 631 | 631 | zUuid = rid_to_uuid(pid); |
| 632 | - blob_append(&value, zUuid, UUID_SIZE); | |
| 632 | + blob_append(&value, zUuid, strlen(zUuid)); | |
| 633 | 633 | fossil_free(zUuid); |
| 634 | 634 | } |
| 635 | 635 | if( bTest && !dryRun ){ |
| 636 | 636 | tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid); |
| 637 | 637 | }else{ |
| 638 | 638 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -627,11 +627,11 @@ | |
| 627 | blob_init(&value, 0, 0); |
| 628 | for(i=3; i<g.argc; i++){ |
| 629 | int pid = name_to_typed_rid(g.argv[i], "ci"); |
| 630 | if( i>3 ) blob_append(&value, " ", 1); |
| 631 | zUuid = rid_to_uuid(pid); |
| 632 | blob_append(&value, zUuid, UUID_SIZE); |
| 633 | fossil_free(zUuid); |
| 634 | } |
| 635 | if( bTest && !dryRun ){ |
| 636 | tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid); |
| 637 | }else{ |
| 638 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -627,11 +627,11 @@ | |
| 627 | blob_init(&value, 0, 0); |
| 628 | for(i=3; i<g.argc; i++){ |
| 629 | int pid = name_to_typed_rid(g.argv[i], "ci"); |
| 630 | if( i>3 ) blob_append(&value, " ", 1); |
| 631 | zUuid = rid_to_uuid(pid); |
| 632 | blob_append(&value, zUuid, strlen(zUuid)); |
| 633 | fossil_free(zUuid); |
| 634 | } |
| 635 | if( bTest && !dryRun ){ |
| 636 | tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid); |
| 637 | }else{ |
| 638 |
+2
-6
| --- src/tar.c | ||
| +++ src/tar.c | ||
| @@ -483,11 +483,11 @@ | ||
| 483 | 483 | content_get(rid, &mfile); |
| 484 | 484 | if( blob_size(&mfile)==0 ){ |
| 485 | 485 | blob_zero(pTar); |
| 486 | 486 | return; |
| 487 | 487 | } |
| 488 | - blob_zero(&hash); | |
| 488 | + blob_set_dynamic(&hash, rid_to_uuid(rid)); | |
| 489 | 489 | blob_zero(&filename); |
| 490 | 490 | |
| 491 | 491 | if( zDir && zDir[0] ){ |
| 492 | 492 | blob_appendf(&filename, "%s/", zDir); |
| 493 | 493 | } |
| @@ -520,13 +520,10 @@ | ||
| 520 | 520 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 521 | 521 | if( eflg & MFESTFLG_RAW ){ |
| 522 | 522 | blob_append(&filename, "manifest", -1); |
| 523 | 523 | zName = blob_str(&filename); |
| 524 | 524 | } |
| 525 | - if( eflg & MFESTFLG_UUID ){ | |
| 526 | - sha1sum_blob(&mfile, &hash); | |
| 527 | - } | |
| 528 | 525 | if( eflg & MFESTFLG_RAW ) { |
| 529 | 526 | sterilize_manifest(&mfile); |
| 530 | 527 | tar_add_file(zName, &mfile, 0, mTime); |
| 531 | 528 | } |
| 532 | 529 | } |
| @@ -535,11 +532,10 @@ | ||
| 535 | 532 | blob_append(&hash, "\n", 1); |
| 536 | 533 | blob_resize(&filename, nPrefix); |
| 537 | 534 | blob_append(&filename, "manifest.uuid", -1); |
| 538 | 535 | zName = blob_str(&filename); |
| 539 | 536 | tar_add_file(zName, &hash, 0, mTime); |
| 540 | - blob_reset(&hash); | |
| 541 | 537 | } |
| 542 | 538 | if( eflg & MFESTFLG_TAGS ){ |
| 543 | 539 | Blob tagslist; |
| 544 | 540 | blob_zero(&tagslist); |
| 545 | 541 | get_checkin_taglist(rid, &tagslist); |
| @@ -564,19 +560,19 @@ | ||
| 564 | 560 | tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime); |
| 565 | 561 | blob_reset(&file); |
| 566 | 562 | } |
| 567 | 563 | } |
| 568 | 564 | }else{ |
| 569 | - sha1sum_blob(&mfile, &hash); | |
| 570 | 565 | blob_append(&filename, blob_str(&hash), 16); |
| 571 | 566 | zName = blob_str(&filename); |
| 572 | 567 | mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;"); |
| 573 | 568 | tar_begin(mTime); |
| 574 | 569 | tar_add_file(zName, &mfile, 0, mTime); |
| 575 | 570 | } |
| 576 | 571 | manifest_destroy(pManifest); |
| 577 | 572 | blob_reset(&mfile); |
| 573 | + blob_reset(&hash); | |
| 578 | 574 | blob_reset(&filename); |
| 579 | 575 | tar_finish(pTar); |
| 580 | 576 | } |
| 581 | 577 | |
| 582 | 578 | /* |
| 583 | 579 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -483,11 +483,11 @@ | |
| 483 | content_get(rid, &mfile); |
| 484 | if( blob_size(&mfile)==0 ){ |
| 485 | blob_zero(pTar); |
| 486 | return; |
| 487 | } |
| 488 | blob_zero(&hash); |
| 489 | blob_zero(&filename); |
| 490 | |
| 491 | if( zDir && zDir[0] ){ |
| 492 | blob_appendf(&filename, "%s/", zDir); |
| 493 | } |
| @@ -520,13 +520,10 @@ | |
| 520 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 521 | if( eflg & MFESTFLG_RAW ){ |
| 522 | blob_append(&filename, "manifest", -1); |
| 523 | zName = blob_str(&filename); |
| 524 | } |
| 525 | if( eflg & MFESTFLG_UUID ){ |
| 526 | sha1sum_blob(&mfile, &hash); |
| 527 | } |
| 528 | if( eflg & MFESTFLG_RAW ) { |
| 529 | sterilize_manifest(&mfile); |
| 530 | tar_add_file(zName, &mfile, 0, mTime); |
| 531 | } |
| 532 | } |
| @@ -535,11 +532,10 @@ | |
| 535 | blob_append(&hash, "\n", 1); |
| 536 | blob_resize(&filename, nPrefix); |
| 537 | blob_append(&filename, "manifest.uuid", -1); |
| 538 | zName = blob_str(&filename); |
| 539 | tar_add_file(zName, &hash, 0, mTime); |
| 540 | blob_reset(&hash); |
| 541 | } |
| 542 | if( eflg & MFESTFLG_TAGS ){ |
| 543 | Blob tagslist; |
| 544 | blob_zero(&tagslist); |
| 545 | get_checkin_taglist(rid, &tagslist); |
| @@ -564,19 +560,19 @@ | |
| 564 | tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime); |
| 565 | blob_reset(&file); |
| 566 | } |
| 567 | } |
| 568 | }else{ |
| 569 | sha1sum_blob(&mfile, &hash); |
| 570 | blob_append(&filename, blob_str(&hash), 16); |
| 571 | zName = blob_str(&filename); |
| 572 | mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;"); |
| 573 | tar_begin(mTime); |
| 574 | tar_add_file(zName, &mfile, 0, mTime); |
| 575 | } |
| 576 | manifest_destroy(pManifest); |
| 577 | blob_reset(&mfile); |
| 578 | blob_reset(&filename); |
| 579 | tar_finish(pTar); |
| 580 | } |
| 581 | |
| 582 | /* |
| 583 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -483,11 +483,11 @@ | |
| 483 | content_get(rid, &mfile); |
| 484 | if( blob_size(&mfile)==0 ){ |
| 485 | blob_zero(pTar); |
| 486 | return; |
| 487 | } |
| 488 | blob_set_dynamic(&hash, rid_to_uuid(rid)); |
| 489 | blob_zero(&filename); |
| 490 | |
| 491 | if( zDir && zDir[0] ){ |
| 492 | blob_appendf(&filename, "%s/", zDir); |
| 493 | } |
| @@ -520,13 +520,10 @@ | |
| 520 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 521 | if( eflg & MFESTFLG_RAW ){ |
| 522 | blob_append(&filename, "manifest", -1); |
| 523 | zName = blob_str(&filename); |
| 524 | } |
| 525 | if( eflg & MFESTFLG_RAW ) { |
| 526 | sterilize_manifest(&mfile); |
| 527 | tar_add_file(zName, &mfile, 0, mTime); |
| 528 | } |
| 529 | } |
| @@ -535,11 +532,10 @@ | |
| 532 | blob_append(&hash, "\n", 1); |
| 533 | blob_resize(&filename, nPrefix); |
| 534 | blob_append(&filename, "manifest.uuid", -1); |
| 535 | zName = blob_str(&filename); |
| 536 | tar_add_file(zName, &hash, 0, mTime); |
| 537 | } |
| 538 | if( eflg & MFESTFLG_TAGS ){ |
| 539 | Blob tagslist; |
| 540 | blob_zero(&tagslist); |
| 541 | get_checkin_taglist(rid, &tagslist); |
| @@ -564,19 +560,19 @@ | |
| 560 | tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime); |
| 561 | blob_reset(&file); |
| 562 | } |
| 563 | } |
| 564 | }else{ |
| 565 | blob_append(&filename, blob_str(&hash), 16); |
| 566 | zName = blob_str(&filename); |
| 567 | mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;"); |
| 568 | tar_begin(mTime); |
| 569 | tar_add_file(zName, &mfile, 0, mTime); |
| 570 | } |
| 571 | manifest_destroy(pManifest); |
| 572 | blob_reset(&mfile); |
| 573 | blob_reset(&hash); |
| 574 | blob_reset(&filename); |
| 575 | tar_finish(pTar); |
| 576 | } |
| 577 | |
| 578 | /* |
| 579 |
+2
-2
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -723,11 +723,11 @@ | ||
| 723 | 723 | ** mi: "merge-in". An array of integer rail positions from which |
| 724 | 724 | ** merge arrows should be drawn into this node. If the value is |
| 725 | 725 | ** negative, then the rail position is the absolute value of mi[] |
| 726 | 726 | ** and a thin merge-arrow descender is drawn to the bottom of |
| 727 | 727 | ** the screen. |
| 728 | - ** h: The SHA1 hash of the object being graphed | |
| 728 | + ** h: The artifact hash of the object being graphed | |
| 729 | 729 | */ |
| 730 | 730 | cgi_printf("var rowinfo = [\n"); |
| 731 | 731 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 732 | 732 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:", |
| 733 | 733 | pRow->idx, /* id */ |
| @@ -1461,11 +1461,11 @@ | ||
| 1461 | 1461 | ** v Show details of files changed |
| 1462 | 1462 | ** f=CHECKIN Show family (immediate parents and children) of CHECKIN |
| 1463 | 1463 | ** from=CHECKIN Path from... |
| 1464 | 1464 | ** to=CHECKIN ... to this |
| 1465 | 1465 | ** shortest ... show only the shortest path |
| 1466 | -** uf=FILE_SHA1 Show only check-ins that contain the given file version | |
| 1466 | +** uf=FILE_HASH Show only check-ins that contain the given file version | |
| 1467 | 1467 | ** chng=GLOBLIST Show only check-ins that involve changes to a file whose |
| 1468 | 1468 | ** name matches one of the comma-separate GLOBLIST |
| 1469 | 1469 | ** brbg Background color from branch name |
| 1470 | 1470 | ** ubg Background color from user |
| 1471 | 1471 | ** namechng Show only check-ins that have filename changes |
| 1472 | 1472 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -723,11 +723,11 @@ | |
| 723 | ** mi: "merge-in". An array of integer rail positions from which |
| 724 | ** merge arrows should be drawn into this node. If the value is |
| 725 | ** negative, then the rail position is the absolute value of mi[] |
| 726 | ** and a thin merge-arrow descender is drawn to the bottom of |
| 727 | ** the screen. |
| 728 | ** h: The SHA1 hash of the object being graphed |
| 729 | */ |
| 730 | cgi_printf("var rowinfo = [\n"); |
| 731 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 732 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:", |
| 733 | pRow->idx, /* id */ |
| @@ -1461,11 +1461,11 @@ | |
| 1461 | ** v Show details of files changed |
| 1462 | ** f=CHECKIN Show family (immediate parents and children) of CHECKIN |
| 1463 | ** from=CHECKIN Path from... |
| 1464 | ** to=CHECKIN ... to this |
| 1465 | ** shortest ... show only the shortest path |
| 1466 | ** uf=FILE_SHA1 Show only check-ins that contain the given file version |
| 1467 | ** chng=GLOBLIST Show only check-ins that involve changes to a file whose |
| 1468 | ** name matches one of the comma-separate GLOBLIST |
| 1469 | ** brbg Background color from branch name |
| 1470 | ** ubg Background color from user |
| 1471 | ** namechng Show only check-ins that have filename changes |
| 1472 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -723,11 +723,11 @@ | |
| 723 | ** mi: "merge-in". An array of integer rail positions from which |
| 724 | ** merge arrows should be drawn into this node. If the value is |
| 725 | ** negative, then the rail position is the absolute value of mi[] |
| 726 | ** and a thin merge-arrow descender is drawn to the bottom of |
| 727 | ** the screen. |
| 728 | ** h: The artifact hash of the object being graphed |
| 729 | */ |
| 730 | cgi_printf("var rowinfo = [\n"); |
| 731 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 732 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:", |
| 733 | pRow->idx, /* id */ |
| @@ -1461,11 +1461,11 @@ | |
| 1461 | ** v Show details of files changed |
| 1462 | ** f=CHECKIN Show family (immediate parents and children) of CHECKIN |
| 1463 | ** from=CHECKIN Path from... |
| 1464 | ** to=CHECKIN ... to this |
| 1465 | ** shortest ... show only the shortest path |
| 1466 | ** uf=FILE_HASH Show only check-ins that contain the given file version |
| 1467 | ** chng=GLOBLIST Show only check-ins that involve changes to a file whose |
| 1468 | ** name matches one of the comma-separate GLOBLIST |
| 1469 | ** brbg Background color from branch name |
| 1470 | ** ubg Background color from user |
| 1471 | ** namechng Show only check-ins that have filename changes |
| 1472 |
+58
-1
| --- src/unversioned.c | ||
| +++ src/unversioned.c | ||
| @@ -456,11 +456,11 @@ | ||
| 456 | 456 | ** Query parameters: |
| 457 | 457 | ** |
| 458 | 458 | ** byage=1 Order the initial display be decreasing age |
| 459 | 459 | ** showdel=0 Show deleted files |
| 460 | 460 | */ |
| 461 | -void uvstat_page(void){ | |
| 461 | +void uvlist_page(void){ | |
| 462 | 462 | Stmt q; |
| 463 | 463 | sqlite3_int64 iNow; |
| 464 | 464 | sqlite3_int64 iTotalSz = 0; |
| 465 | 465 | int cnt = 0; |
| 466 | 466 | int n = 0; |
| @@ -554,5 +554,62 @@ | ||
| 554 | 554 | }else{ |
| 555 | 555 | @ No unversioned files on this server. |
| 556 | 556 | } |
| 557 | 557 | style_footer(); |
| 558 | 558 | } |
| 559 | + | |
| 560 | +/* | |
| 561 | +** WEBPAGE: juvlist | |
| 562 | +** | |
| 563 | +** Return a complete list of unversioned files as JSON. The JSON | |
| 564 | +** looks like this: | |
| 565 | +** | |
| 566 | +** [{"name":NAME, | |
| 567 | +** "mtime":MTIME, | |
| 568 | +** "hash":HASH, | |
| 569 | +** "size":SIZE, | |
| 570 | +** "user":USER}] | |
| 571 | +*/ | |
| 572 | +void uvlist_json_page(void){ | |
| 573 | + Stmt q; | |
| 574 | + char *zSep = "["; | |
| 575 | + Blob json; | |
| 576 | + | |
| 577 | + login_check_credentials(); | |
| 578 | + if( !g.perm.Read ){ login_needed(g.anon.Read); return; } | |
| 579 | + cgi_set_content_type("text/json"); | |
| 580 | + if( !db_table_exists("repository","unversioned") ){ | |
| 581 | + blob_init(&json, "[]", -1); | |
| 582 | + cgi_set_content(&json); | |
| 583 | + return; | |
| 584 | + } | |
| 585 | + blob_init(&json, 0, 0); | |
| 586 | + db_prepare(&q, | |
| 587 | + "SELECT" | |
| 588 | + " name," | |
| 589 | + " mtime," | |
| 590 | + " hash," | |
| 591 | + " sz," | |
| 592 | + " (SELECT login FROM rcvfrom, user" | |
| 593 | + " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)" | |
| 594 | + " FROM unversioned WHERE hash IS NOT NULL" | |
| 595 | + ); | |
| 596 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 597 | + const char *zName = db_column_text(&q, 0); | |
| 598 | + sqlite3_int64 mtime = db_column_int(&q, 1); | |
| 599 | + const char *zHash = db_column_text(&q, 2); | |
| 600 | + int fullSize = db_column_int(&q, 3); | |
| 601 | + const char *zLogin = db_column_text(&q, 4); | |
| 602 | + if( zLogin==0 ) zLogin = ""; | |
| 603 | + blob_appendf(&json, "%s{\"name\":\"", zSep); | |
| 604 | + zSep = ",\n "; | |
| 605 | + blob_append_json_string(&json, zName); | |
| 606 | + blob_appendf(&json, "\",\n \"mtime\":%lld,\n \"hash\":\"", mtime); | |
| 607 | + blob_append_json_string(&json, zHash); | |
| 608 | + blob_appendf(&json, "\",\n \"size\":%d,\n \"user\":\"", fullSize); | |
| 609 | + blob_append_json_string(&json, zLogin); | |
| 610 | + blob_appendf(&json, "\"}"); | |
| 611 | + } | |
| 612 | + db_finalize(&q); | |
| 613 | + blob_appendf(&json,"]\n"); | |
| 614 | + cgi_set_content(&json); | |
| 615 | +} | |
| 559 | 616 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -456,11 +456,11 @@ | |
| 456 | ** Query parameters: |
| 457 | ** |
| 458 | ** byage=1 Order the initial display be decreasing age |
| 459 | ** showdel=0 Show deleted files |
| 460 | */ |
| 461 | void uvstat_page(void){ |
| 462 | Stmt q; |
| 463 | sqlite3_int64 iNow; |
| 464 | sqlite3_int64 iTotalSz = 0; |
| 465 | int cnt = 0; |
| 466 | int n = 0; |
| @@ -554,5 +554,62 @@ | |
| 554 | }else{ |
| 555 | @ No unversioned files on this server. |
| 556 | } |
| 557 | style_footer(); |
| 558 | } |
| 559 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -456,11 +456,11 @@ | |
| 456 | ** Query parameters: |
| 457 | ** |
| 458 | ** byage=1 Order the initial display be decreasing age |
| 459 | ** showdel=0 Show deleted files |
| 460 | */ |
| 461 | void uvlist_page(void){ |
| 462 | Stmt q; |
| 463 | sqlite3_int64 iNow; |
| 464 | sqlite3_int64 iTotalSz = 0; |
| 465 | int cnt = 0; |
| 466 | int n = 0; |
| @@ -554,5 +554,62 @@ | |
| 554 | }else{ |
| 555 | @ No unversioned files on this server. |
| 556 | } |
| 557 | style_footer(); |
| 558 | } |
| 559 | |
| 560 | /* |
| 561 | ** WEBPAGE: juvlist |
| 562 | ** |
| 563 | ** Return a complete list of unversioned files as JSON. The JSON |
| 564 | ** looks like this: |
| 565 | ** |
| 566 | ** [{"name":NAME, |
| 567 | ** "mtime":MTIME, |
| 568 | ** "hash":HASH, |
| 569 | ** "size":SIZE, |
| 570 | ** "user":USER}] |
| 571 | */ |
| 572 | void uvlist_json_page(void){ |
| 573 | Stmt q; |
| 574 | char *zSep = "["; |
| 575 | Blob json; |
| 576 | |
| 577 | login_check_credentials(); |
| 578 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 579 | cgi_set_content_type("text/json"); |
| 580 | if( !db_table_exists("repository","unversioned") ){ |
| 581 | blob_init(&json, "[]", -1); |
| 582 | cgi_set_content(&json); |
| 583 | return; |
| 584 | } |
| 585 | blob_init(&json, 0, 0); |
| 586 | db_prepare(&q, |
| 587 | "SELECT" |
| 588 | " name," |
| 589 | " mtime," |
| 590 | " hash," |
| 591 | " sz," |
| 592 | " (SELECT login FROM rcvfrom, user" |
| 593 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)" |
| 594 | " FROM unversioned WHERE hash IS NOT NULL" |
| 595 | ); |
| 596 | while( db_step(&q)==SQLITE_ROW ){ |
| 597 | const char *zName = db_column_text(&q, 0); |
| 598 | sqlite3_int64 mtime = db_column_int(&q, 1); |
| 599 | const char *zHash = db_column_text(&q, 2); |
| 600 | int fullSize = db_column_int(&q, 3); |
| 601 | const char *zLogin = db_column_text(&q, 4); |
| 602 | if( zLogin==0 ) zLogin = ""; |
| 603 | blob_appendf(&json, "%s{\"name\":\"", zSep); |
| 604 | zSep = ",\n "; |
| 605 | blob_append_json_string(&json, zName); |
| 606 | blob_appendf(&json, "\",\n \"mtime\":%lld,\n \"hash\":\"", mtime); |
| 607 | blob_append_json_string(&json, zHash); |
| 608 | blob_appendf(&json, "\",\n \"size\":%d,\n \"user\":\"", fullSize); |
| 609 | blob_append_json_string(&json, zLogin); |
| 610 | blob_appendf(&json, "\"}"); |
| 611 | } |
| 612 | db_finalize(&q); |
| 613 | blob_appendf(&json,"]\n"); |
| 614 | cgi_set_content(&json); |
| 615 | } |
| 616 |
+6
-8
| --- src/verify.c | ||
| +++ src/verify.c | ||
| @@ -34,27 +34,25 @@ | ||
| 34 | 34 | ** |
| 35 | 35 | ** Panic if anything goes wrong. If this procedure returns it means |
| 36 | 36 | ** that everything is OK. |
| 37 | 37 | */ |
| 38 | 38 | static void verify_rid(int rid){ |
| 39 | - Blob uuid, hash, content; | |
| 39 | + Blob uuid, content; | |
| 40 | 40 | if( content_size(rid, 0)<0 ){ |
| 41 | 41 | return; /* No way to verify phantoms */ |
| 42 | 42 | } |
| 43 | 43 | blob_zero(&uuid); |
| 44 | 44 | db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 45 | - if( blob_size(&uuid)!=UUID_SIZE ){ | |
| 45 | + if( !hname_validate(blob_buffer(&uuid), blob_size(&uuid)) ){ | |
| 46 | 46 | fossil_fatal("not a valid rid: %d", rid); |
| 47 | 47 | } |
| 48 | 48 | if( content_get(rid, &content) ){ |
| 49 | - sha1sum_blob(&content, &hash); | |
| 50 | - blob_reset(&content); | |
| 51 | - if( blob_compare(&uuid, &hash) ){ | |
| 52 | - fossil_fatal("hash of rid %d (%b) does not match its uuid (%b)", | |
| 53 | - rid, &hash, &uuid); | |
| 49 | + if( !hname_verify_hash(&content, blob_buffer(&uuid), blob_size(&uuid)) ){ | |
| 50 | + fossil_fatal("hash of rid %d does not match its uuid (%b)", | |
| 51 | + rid, &uuid); | |
| 54 | 52 | } |
| 55 | - blob_reset(&hash); | |
| 53 | + blob_reset(&content); | |
| 56 | 54 | } |
| 57 | 55 | blob_reset(&uuid); |
| 58 | 56 | } |
| 59 | 57 | |
| 60 | 58 | /* |
| 61 | 59 |
| --- src/verify.c | |
| +++ src/verify.c | |
| @@ -34,27 +34,25 @@ | |
| 34 | ** |
| 35 | ** Panic if anything goes wrong. If this procedure returns it means |
| 36 | ** that everything is OK. |
| 37 | */ |
| 38 | static void verify_rid(int rid){ |
| 39 | Blob uuid, hash, content; |
| 40 | if( content_size(rid, 0)<0 ){ |
| 41 | return; /* No way to verify phantoms */ |
| 42 | } |
| 43 | blob_zero(&uuid); |
| 44 | db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 45 | if( blob_size(&uuid)!=UUID_SIZE ){ |
| 46 | fossil_fatal("not a valid rid: %d", rid); |
| 47 | } |
| 48 | if( content_get(rid, &content) ){ |
| 49 | sha1sum_blob(&content, &hash); |
| 50 | blob_reset(&content); |
| 51 | if( blob_compare(&uuid, &hash) ){ |
| 52 | fossil_fatal("hash of rid %d (%b) does not match its uuid (%b)", |
| 53 | rid, &hash, &uuid); |
| 54 | } |
| 55 | blob_reset(&hash); |
| 56 | } |
| 57 | blob_reset(&uuid); |
| 58 | } |
| 59 | |
| 60 | /* |
| 61 |
| --- src/verify.c | |
| +++ src/verify.c | |
| @@ -34,27 +34,25 @@ | |
| 34 | ** |
| 35 | ** Panic if anything goes wrong. If this procedure returns it means |
| 36 | ** that everything is OK. |
| 37 | */ |
| 38 | static void verify_rid(int rid){ |
| 39 | Blob uuid, content; |
| 40 | if( content_size(rid, 0)<0 ){ |
| 41 | return; /* No way to verify phantoms */ |
| 42 | } |
| 43 | blob_zero(&uuid); |
| 44 | db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 45 | if( !hname_validate(blob_buffer(&uuid), blob_size(&uuid)) ){ |
| 46 | fossil_fatal("not a valid rid: %d", rid); |
| 47 | } |
| 48 | if( content_get(rid, &content) ){ |
| 49 | if( !hname_verify_hash(&content, blob_buffer(&uuid), blob_size(&uuid)) ){ |
| 50 | fossil_fatal("hash of rid %d does not match its uuid (%b)", |
| 51 | rid, &uuid); |
| 52 | } |
| 53 | blob_reset(&content); |
| 54 | } |
| 55 | blob_reset(&uuid); |
| 56 | } |
| 57 | |
| 58 | /* |
| 59 |
+19
-30
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -21,12 +21,12 @@ | ||
| 21 | 21 | #include "vfile.h" |
| 22 | 22 | #include <assert.h> |
| 23 | 23 | #include <sys/types.h> |
| 24 | 24 | |
| 25 | 25 | /* |
| 26 | -** The input is guaranteed to be a 40-character well-formed UUID. | |
| 27 | -** Find its rid. | |
| 26 | +** The input is guaranteed to be a 40- or 64-character well-formed | |
| 27 | +** artifact hash. Find its rid. | |
| 28 | 28 | */ |
| 29 | 29 | int fast_uuid_to_rid(const char *zUuid){ |
| 30 | 30 | static Stmt q; |
| 31 | 31 | int rid; |
| 32 | 32 | db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid"); |
| @@ -51,17 +51,17 @@ | ||
| 51 | 51 | ** create a phantom record. A private phantom is created for 2 and |
| 52 | 52 | ** a public phantom is created for 1. |
| 53 | 53 | */ |
| 54 | 54 | int uuid_to_rid(const char *zUuid, int phantomize){ |
| 55 | 55 | int rid, sz; |
| 56 | - char z[UUID_SIZE+1]; | |
| 56 | + char z[HNAME_MAX+1]; | |
| 57 | 57 | |
| 58 | 58 | sz = strlen(zUuid); |
| 59 | - if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){ | |
| 60 | - return 0; | |
| 59 | + if( !hname_validate(zUuid, sz) ){ | |
| 60 | + return 0; /* Not a valid hash */ | |
| 61 | 61 | } |
| 62 | - memcpy(z, zUuid, UUID_SIZE+1); | |
| 62 | + memcpy(z, zUuid, sz+1); | |
| 63 | 63 | canonical16(z, sz); |
| 64 | 64 | rid = fast_uuid_to_rid(z); |
| 65 | 65 | if( rid==0 && phantomize ){ |
| 66 | 66 | rid = content_new(zUuid, phantomize-1); |
| 67 | 67 | } |
| @@ -130,11 +130,11 @@ | ||
| 130 | 130 | /* |
| 131 | 131 | ** The cksigFlags parameter to vfile_check_signature() is an OR-ed |
| 132 | 132 | ** combination of the following bits: |
| 133 | 133 | */ |
| 134 | 134 | #define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */ |
| 135 | -#define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */ | |
| 135 | +#define CKSIG_HASH 0x002 /* Verify file content using hashing */ | |
| 136 | 136 | #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */ |
| 137 | 137 | |
| 138 | 138 | #endif /* INTERFACE */ |
| 139 | 139 | |
| 140 | 140 | /* |
| @@ -159,12 +159,12 @@ | ||
| 159 | 159 | ** |
| 160 | 160 | ** If the size of the file has changed, then we always know that the file |
| 161 | 161 | ** changed without having to look at the mtime or on-disk content. |
| 162 | 162 | ** |
| 163 | 163 | ** The mtime of the file is only a factor if the mtime-changes setting |
| 164 | -** is false and the useSha1sum flag is false. If the mtime-changes | |
| 165 | -** setting is true (or undefined - it defaults to true) or if useSha1sum | |
| 164 | +** is false and the CKSIG_HASH flag is false. If the mtime-changes | |
| 165 | +** setting is true (or undefined - it defaults to true) or if CKSIG_HASH | |
| 166 | 166 | ** is true, then we do not trust the mtime and will examine the on-disk |
| 167 | 167 | ** content to determine if a file really is the same. |
| 168 | 168 | ** |
| 169 | 169 | ** If the mtime is used, it is used only to determine if files are the same. |
| 170 | 170 | ** If the mtime of a file has changed, we still examine the on-disk content |
| @@ -171,12 +171,11 @@ | ||
| 171 | 171 | ** to see whether or not the edit was a null-edit. |
| 172 | 172 | */ |
| 173 | 173 | void vfile_check_signature(int vid, unsigned int cksigFlags){ |
| 174 | 174 | int nErr = 0; |
| 175 | 175 | Stmt q; |
| 176 | - Blob fileCksum, origCksum; | |
| 177 | - int useMtime = (cksigFlags & CKSIG_SHA1)==0 | |
| 176 | + int useMtime = (cksigFlags & CKSIG_HASH)==0 | |
| 178 | 177 | && db_get_boolean("mtime-changes", 1); |
| 179 | 178 | |
| 180 | 179 | db_begin_transaction(); |
| 181 | 180 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 182 | 181 | " vfile.mrid, deleted, chnged, uuid, size, mtime," |
| @@ -222,40 +221,30 @@ | ||
| 222 | 221 | chnged = 1; |
| 223 | 222 | } |
| 224 | 223 | if( origSize!=currentSize ){ |
| 225 | 224 | if( chnged!=1 ){ |
| 226 | 225 | /* A file size change is definitive - the file has changed. No |
| 227 | - ** need to check the mtime or sha1sum */ | |
| 226 | + ** need to check the mtime or hash */ | |
| 228 | 227 | chnged = 1; |
| 229 | 228 | } |
| 230 | 229 | }else if( chnged==1 && rid!=0 && !isDeleted ){ |
| 231 | 230 | /* File is believed to have changed but it is the same size. |
| 232 | 231 | ** Double check that it really has changed by looking at content. */ |
| 232 | + const char *zUuid = db_column_text(&q, 5); | |
| 233 | + int nUuid = db_column_bytes(&q, 5); | |
| 233 | 234 | assert( origSize==currentSize ); |
| 234 | - db_ephemeral_blob(&q, 5, &origCksum); | |
| 235 | - if( sha1sum_file(zName, &fileCksum) ){ | |
| 236 | - blob_zero(&fileCksum); | |
| 237 | - } | |
| 238 | - if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0; | |
| 239 | - blob_reset(&origCksum); | |
| 240 | - blob_reset(&fileCksum); | |
| 235 | + if( hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 0; | |
| 241 | 236 | }else if( (chnged==0 || chnged==2 || chnged==4) |
| 242 | 237 | && (useMtime==0 || currentMtime!=oldMtime) ){ |
| 243 | 238 | /* For files that were formerly believed to be unchanged or that were |
| 244 | 239 | ** changed by merging, if their mtime changes, or unconditionally |
| 245 | - ** if --sha1sum is used, check to see if they have been edited by | |
| 246 | - ** looking at their SHA1 sum */ | |
| 240 | + ** if --hash is used, check to see if they have been edited by | |
| 241 | + ** looking at their artifact hashes */ | |
| 242 | + const char *zUuid = db_column_text(&q, 5); | |
| 243 | + int nUuid = db_column_bytes(&q, 5); | |
| 247 | 244 | assert( origSize==currentSize ); |
| 248 | - db_ephemeral_blob(&q, 5, &origCksum); | |
| 249 | - if( sha1sum_file(zName, &fileCksum) ){ | |
| 250 | - blob_zero(&fileCksum); | |
| 251 | - } | |
| 252 | - if( blob_compare(&fileCksum, &origCksum) ){ | |
| 253 | - chnged = 1; | |
| 254 | - } | |
| 255 | - blob_reset(&origCksum); | |
| 256 | - blob_reset(&fileCksum); | |
| 245 | + if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1; | |
| 257 | 246 | } |
| 258 | 247 | if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){ |
| 259 | 248 | i64 desiredMtime; |
| 260 | 249 | if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){ |
| 261 | 250 | if( currentMtime!=desiredMtime ){ |
| 262 | 251 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -21,12 +21,12 @@ | |
| 21 | #include "vfile.h" |
| 22 | #include <assert.h> |
| 23 | #include <sys/types.h> |
| 24 | |
| 25 | /* |
| 26 | ** The input is guaranteed to be a 40-character well-formed UUID. |
| 27 | ** Find its rid. |
| 28 | */ |
| 29 | int fast_uuid_to_rid(const char *zUuid){ |
| 30 | static Stmt q; |
| 31 | int rid; |
| 32 | db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid"); |
| @@ -51,17 +51,17 @@ | |
| 51 | ** create a phantom record. A private phantom is created for 2 and |
| 52 | ** a public phantom is created for 1. |
| 53 | */ |
| 54 | int uuid_to_rid(const char *zUuid, int phantomize){ |
| 55 | int rid, sz; |
| 56 | char z[UUID_SIZE+1]; |
| 57 | |
| 58 | sz = strlen(zUuid); |
| 59 | if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){ |
| 60 | return 0; |
| 61 | } |
| 62 | memcpy(z, zUuid, UUID_SIZE+1); |
| 63 | canonical16(z, sz); |
| 64 | rid = fast_uuid_to_rid(z); |
| 65 | if( rid==0 && phantomize ){ |
| 66 | rid = content_new(zUuid, phantomize-1); |
| 67 | } |
| @@ -130,11 +130,11 @@ | |
| 130 | /* |
| 131 | ** The cksigFlags parameter to vfile_check_signature() is an OR-ed |
| 132 | ** combination of the following bits: |
| 133 | */ |
| 134 | #define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */ |
| 135 | #define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */ |
| 136 | #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */ |
| 137 | |
| 138 | #endif /* INTERFACE */ |
| 139 | |
| 140 | /* |
| @@ -159,12 +159,12 @@ | |
| 159 | ** |
| 160 | ** If the size of the file has changed, then we always know that the file |
| 161 | ** changed without having to look at the mtime or on-disk content. |
| 162 | ** |
| 163 | ** The mtime of the file is only a factor if the mtime-changes setting |
| 164 | ** is false and the useSha1sum flag is false. If the mtime-changes |
| 165 | ** setting is true (or undefined - it defaults to true) or if useSha1sum |
| 166 | ** is true, then we do not trust the mtime and will examine the on-disk |
| 167 | ** content to determine if a file really is the same. |
| 168 | ** |
| 169 | ** If the mtime is used, it is used only to determine if files are the same. |
| 170 | ** If the mtime of a file has changed, we still examine the on-disk content |
| @@ -171,12 +171,11 @@ | |
| 171 | ** to see whether or not the edit was a null-edit. |
| 172 | */ |
| 173 | void vfile_check_signature(int vid, unsigned int cksigFlags){ |
| 174 | int nErr = 0; |
| 175 | Stmt q; |
| 176 | Blob fileCksum, origCksum; |
| 177 | int useMtime = (cksigFlags & CKSIG_SHA1)==0 |
| 178 | && db_get_boolean("mtime-changes", 1); |
| 179 | |
| 180 | db_begin_transaction(); |
| 181 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 182 | " vfile.mrid, deleted, chnged, uuid, size, mtime," |
| @@ -222,40 +221,30 @@ | |
| 222 | chnged = 1; |
| 223 | } |
| 224 | if( origSize!=currentSize ){ |
| 225 | if( chnged!=1 ){ |
| 226 | /* A file size change is definitive - the file has changed. No |
| 227 | ** need to check the mtime or sha1sum */ |
| 228 | chnged = 1; |
| 229 | } |
| 230 | }else if( chnged==1 && rid!=0 && !isDeleted ){ |
| 231 | /* File is believed to have changed but it is the same size. |
| 232 | ** Double check that it really has changed by looking at content. */ |
| 233 | assert( origSize==currentSize ); |
| 234 | db_ephemeral_blob(&q, 5, &origCksum); |
| 235 | if( sha1sum_file(zName, &fileCksum) ){ |
| 236 | blob_zero(&fileCksum); |
| 237 | } |
| 238 | if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0; |
| 239 | blob_reset(&origCksum); |
| 240 | blob_reset(&fileCksum); |
| 241 | }else if( (chnged==0 || chnged==2 || chnged==4) |
| 242 | && (useMtime==0 || currentMtime!=oldMtime) ){ |
| 243 | /* For files that were formerly believed to be unchanged or that were |
| 244 | ** changed by merging, if their mtime changes, or unconditionally |
| 245 | ** if --sha1sum is used, check to see if they have been edited by |
| 246 | ** looking at their SHA1 sum */ |
| 247 | assert( origSize==currentSize ); |
| 248 | db_ephemeral_blob(&q, 5, &origCksum); |
| 249 | if( sha1sum_file(zName, &fileCksum) ){ |
| 250 | blob_zero(&fileCksum); |
| 251 | } |
| 252 | if( blob_compare(&fileCksum, &origCksum) ){ |
| 253 | chnged = 1; |
| 254 | } |
| 255 | blob_reset(&origCksum); |
| 256 | blob_reset(&fileCksum); |
| 257 | } |
| 258 | if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){ |
| 259 | i64 desiredMtime; |
| 260 | if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){ |
| 261 | if( currentMtime!=desiredMtime ){ |
| 262 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -21,12 +21,12 @@ | |
| 21 | #include "vfile.h" |
| 22 | #include <assert.h> |
| 23 | #include <sys/types.h> |
| 24 | |
| 25 | /* |
| 26 | ** The input is guaranteed to be a 40- or 64-character well-formed |
| 27 | ** artifact hash. Find its rid. |
| 28 | */ |
| 29 | int fast_uuid_to_rid(const char *zUuid){ |
| 30 | static Stmt q; |
| 31 | int rid; |
| 32 | db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid"); |
| @@ -51,17 +51,17 @@ | |
| 51 | ** create a phantom record. A private phantom is created for 2 and |
| 52 | ** a public phantom is created for 1. |
| 53 | */ |
| 54 | int uuid_to_rid(const char *zUuid, int phantomize){ |
| 55 | int rid, sz; |
| 56 | char z[HNAME_MAX+1]; |
| 57 | |
| 58 | sz = strlen(zUuid); |
| 59 | if( !hname_validate(zUuid, sz) ){ |
| 60 | return 0; /* Not a valid hash */ |
| 61 | } |
| 62 | memcpy(z, zUuid, sz+1); |
| 63 | canonical16(z, sz); |
| 64 | rid = fast_uuid_to_rid(z); |
| 65 | if( rid==0 && phantomize ){ |
| 66 | rid = content_new(zUuid, phantomize-1); |
| 67 | } |
| @@ -130,11 +130,11 @@ | |
| 130 | /* |
| 131 | ** The cksigFlags parameter to vfile_check_signature() is an OR-ed |
| 132 | ** combination of the following bits: |
| 133 | */ |
| 134 | #define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */ |
| 135 | #define CKSIG_HASH 0x002 /* Verify file content using hashing */ |
| 136 | #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */ |
| 137 | |
| 138 | #endif /* INTERFACE */ |
| 139 | |
| 140 | /* |
| @@ -159,12 +159,12 @@ | |
| 159 | ** |
| 160 | ** If the size of the file has changed, then we always know that the file |
| 161 | ** changed without having to look at the mtime or on-disk content. |
| 162 | ** |
| 163 | ** The mtime of the file is only a factor if the mtime-changes setting |
| 164 | ** is false and the CKSIG_HASH flag is false. If the mtime-changes |
| 165 | ** setting is true (or undefined - it defaults to true) or if CKSIG_HASH |
| 166 | ** is true, then we do not trust the mtime and will examine the on-disk |
| 167 | ** content to determine if a file really is the same. |
| 168 | ** |
| 169 | ** If the mtime is used, it is used only to determine if files are the same. |
| 170 | ** If the mtime of a file has changed, we still examine the on-disk content |
| @@ -171,12 +171,11 @@ | |
| 171 | ** to see whether or not the edit was a null-edit. |
| 172 | */ |
| 173 | void vfile_check_signature(int vid, unsigned int cksigFlags){ |
| 174 | int nErr = 0; |
| 175 | Stmt q; |
| 176 | int useMtime = (cksigFlags & CKSIG_HASH)==0 |
| 177 | && db_get_boolean("mtime-changes", 1); |
| 178 | |
| 179 | db_begin_transaction(); |
| 180 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 181 | " vfile.mrid, deleted, chnged, uuid, size, mtime," |
| @@ -222,40 +221,30 @@ | |
| 221 | chnged = 1; |
| 222 | } |
| 223 | if( origSize!=currentSize ){ |
| 224 | if( chnged!=1 ){ |
| 225 | /* A file size change is definitive - the file has changed. No |
| 226 | ** need to check the mtime or hash */ |
| 227 | chnged = 1; |
| 228 | } |
| 229 | }else if( chnged==1 && rid!=0 && !isDeleted ){ |
| 230 | /* File is believed to have changed but it is the same size. |
| 231 | ** Double check that it really has changed by looking at content. */ |
| 232 | const char *zUuid = db_column_text(&q, 5); |
| 233 | int nUuid = db_column_bytes(&q, 5); |
| 234 | assert( origSize==currentSize ); |
| 235 | if( hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 0; |
| 236 | }else if( (chnged==0 || chnged==2 || chnged==4) |
| 237 | && (useMtime==0 || currentMtime!=oldMtime) ){ |
| 238 | /* For files that were formerly believed to be unchanged or that were |
| 239 | ** changed by merging, if their mtime changes, or unconditionally |
| 240 | ** if --hash is used, check to see if they have been edited by |
| 241 | ** looking at their artifact hashes */ |
| 242 | const char *zUuid = db_column_text(&q, 5); |
| 243 | int nUuid = db_column_bytes(&q, 5); |
| 244 | assert( origSize==currentSize ); |
| 245 | if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1; |
| 246 | } |
| 247 | if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){ |
| 248 | i64 desiredMtime; |
| 249 | if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){ |
| 250 | if( currentMtime!=desiredMtime ){ |
| 251 |
+2
-2
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -1122,12 +1122,12 @@ | ||
| 1122 | 1122 | */ |
| 1123 | 1123 | int wiki_technote_to_rid(const char *zETime) { |
| 1124 | 1124 | int rid=0; /* Artifact ID of the tech note */ |
| 1125 | 1125 | int nETime = strlen(zETime); |
| 1126 | 1126 | Stmt q; |
| 1127 | - if( nETime>=4 && nETime<=UUID_SIZE && validate16(zETime, nETime) ){ | |
| 1128 | - char zUuid[UUID_SIZE+1]; | |
| 1127 | + if( nETime>=4 && nETime<=HNAME_MAX && validate16(zETime, nETime) ){ | |
| 1128 | + char zUuid[HNAME_MAX+1]; | |
| 1129 | 1129 | memcpy(zUuid, zETime, nETime+1); |
| 1130 | 1130 | canonical16(zUuid, nETime); |
| 1131 | 1131 | db_prepare(&q, |
| 1132 | 1132 | "SELECT e.objid" |
| 1133 | 1133 | " FROM event e, tag t" |
| 1134 | 1134 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1122,12 +1122,12 @@ | |
| 1122 | */ |
| 1123 | int wiki_technote_to_rid(const char *zETime) { |
| 1124 | int rid=0; /* Artifact ID of the tech note */ |
| 1125 | int nETime = strlen(zETime); |
| 1126 | Stmt q; |
| 1127 | if( nETime>=4 && nETime<=UUID_SIZE && validate16(zETime, nETime) ){ |
| 1128 | char zUuid[UUID_SIZE+1]; |
| 1129 | memcpy(zUuid, zETime, nETime+1); |
| 1130 | canonical16(zUuid, nETime); |
| 1131 | db_prepare(&q, |
| 1132 | "SELECT e.objid" |
| 1133 | " FROM event e, tag t" |
| 1134 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1122,12 +1122,12 @@ | |
| 1122 | */ |
| 1123 | int wiki_technote_to_rid(const char *zETime) { |
| 1124 | int rid=0; /* Artifact ID of the tech note */ |
| 1125 | int nETime = strlen(zETime); |
| 1126 | Stmt q; |
| 1127 | if( nETime>=4 && nETime<=HNAME_MAX && validate16(zETime, nETime) ){ |
| 1128 | char zUuid[HNAME_MAX+1]; |
| 1129 | memcpy(zUuid, zETime, nETime+1); |
| 1130 | canonical16(zUuid, nETime); |
| 1131 | db_prepare(&q, |
| 1132 | "SELECT e.objid" |
| 1133 | " FROM event e, tag t" |
| 1134 |
+1
-1
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -1067,11 +1067,11 @@ | ||
| 1067 | 1067 | ** If the input string corresponds to an existing baseline, |
| 1068 | 1068 | ** return true. |
| 1069 | 1069 | */ |
| 1070 | 1070 | static int is_valid_uuid(const char *z){ |
| 1071 | 1071 | int n = strlen(z); |
| 1072 | - if( n<4 || n>UUID_SIZE ) return 0; | |
| 1072 | + if( n<4 || n>HNAME_MAX ) return 0; | |
| 1073 | 1073 | if( !validate16(z, n) ) return 0; |
| 1074 | 1074 | return 1; |
| 1075 | 1075 | } |
| 1076 | 1076 | |
| 1077 | 1077 | /* |
| 1078 | 1078 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1067,11 +1067,11 @@ | |
| 1067 | ** If the input string corresponds to an existing baseline, |
| 1068 | ** return true. |
| 1069 | */ |
| 1070 | static int is_valid_uuid(const char *z){ |
| 1071 | int n = strlen(z); |
| 1072 | if( n<4 || n>UUID_SIZE ) return 0; |
| 1073 | if( !validate16(z, n) ) return 0; |
| 1074 | return 1; |
| 1075 | } |
| 1076 | |
| 1077 | /* |
| 1078 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1067,11 +1067,11 @@ | |
| 1067 | ** If the input string corresponds to an existing baseline, |
| 1068 | ** return true. |
| 1069 | */ |
| 1070 | static int is_valid_uuid(const char *z){ |
| 1071 | int n = strlen(z); |
| 1072 | if( n<4 || n>HNAME_MAX ) return 0; |
| 1073 | if( !validate16(z, n) ) return 0; |
| 1074 | return 1; |
| 1075 | } |
| 1076 | |
| 1077 | /* |
| 1078 |
+96
-66
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -49,16 +49,17 @@ | ||
| 49 | 49 | int nDanglingFile; /* Number of dangling deltas received */ |
| 50 | 50 | int mxSend; /* Stop sending "file" when pOut reaches this size */ |
| 51 | 51 | int resync; /* Send igot cards for all holdings */ |
| 52 | 52 | u8 syncPrivate; /* True to enable syncing private content */ |
| 53 | 53 | u8 nextIsPrivate; /* If true, next "file" received is a private */ |
| 54 | + u32 clientVersion; /* Version of the client software */ | |
| 54 | 55 | time_t maxTime; /* Time when this transfer should be finished */ |
| 55 | 56 | }; |
| 56 | 57 | |
| 57 | 58 | |
| 58 | 59 | /* |
| 59 | -** The input blob contains a UUID. Convert it into a record ID. | |
| 60 | +** The input blob contains an artifact. Convert it into a record ID. | |
| 60 | 61 | ** Create a phantom record if no prior record exists and |
| 61 | 62 | ** phantomize is true. |
| 62 | 63 | ** |
| 63 | 64 | ** Compare to uuid_to_rid(). This routine takes a blob argument |
| 64 | 65 | ** and does less error checking. |
| @@ -100,12 +101,12 @@ | ||
| 100 | 101 | ** message. This routine finishes parsing that message and does |
| 101 | 102 | ** a record insert of the file. |
| 102 | 103 | ** |
| 103 | 104 | ** The file line is in one of the following two forms: |
| 104 | 105 | ** |
| 105 | -** file UUID SIZE \n CONTENT | |
| 106 | -** file UUID DELTASRC SIZE \n CONTENT | |
| 106 | +** file HASH SIZE \n CONTENT | |
| 107 | +** file HASH DELTASRC SIZE \n CONTENT | |
| 107 | 108 | ** |
| 108 | 109 | ** The content is SIZE bytes immediately following the newline. |
| 109 | 110 | ** If DELTASRC exists, then the CONTENT is a delta against the |
| 110 | 111 | ** content of DELTASRC. |
| 111 | 112 | ** |
| @@ -122,29 +123,30 @@ | ||
| 122 | 123 | int *pnUuidList |
| 123 | 124 | ){ |
| 124 | 125 | int n; |
| 125 | 126 | int rid; |
| 126 | 127 | int srcid = 0; |
| 127 | - Blob content, hash; | |
| 128 | + Blob content; | |
| 128 | 129 | int isPriv; |
| 130 | + Blob *pUuid; | |
| 129 | 131 | |
| 130 | 132 | isPriv = pXfer->nextIsPrivate; |
| 131 | 133 | pXfer->nextIsPrivate = 0; |
| 132 | 134 | if( pXfer->nToken<3 |
| 133 | 135 | || pXfer->nToken>4 |
| 134 | - || !blob_is_uuid(&pXfer->aToken[1]) | |
| 136 | + || !blob_is_hname(&pXfer->aToken[1]) | |
| 135 | 137 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n) |
| 136 | 138 | || n<0 |
| 137 | - || (pXfer->nToken==4 && !blob_is_uuid(&pXfer->aToken[2])) | |
| 139 | + || (pXfer->nToken==4 && !blob_is_hname(&pXfer->aToken[2])) | |
| 138 | 140 | ){ |
| 139 | 141 | blob_appendf(&pXfer->err, "malformed file line"); |
| 140 | 142 | return; |
| 141 | 143 | } |
| 142 | 144 | blob_zero(&content); |
| 143 | - blob_zero(&hash); | |
| 144 | 145 | blob_extract(pXfer->pIn, n, &content); |
| 145 | - if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ | |
| 146 | + pUuid = &pXfer->aToken[1]; | |
| 147 | + if( !cloneFlag && uuid_is_shunned(blob_str(pUuid)) ){ | |
| 146 | 148 | /* Ignore files that have been shunned */ |
| 147 | 149 | blob_reset(&content); |
| 148 | 150 | return; |
| 149 | 151 | } |
| 150 | 152 | if( isPriv && !g.perm.Private ){ |
| @@ -158,26 +160,26 @@ | ||
| 158 | 160 | pXfer->nDeltaRcvd++; |
| 159 | 161 | }else{ |
| 160 | 162 | srcid = 0; |
| 161 | 163 | pXfer->nFileRcvd++; |
| 162 | 164 | } |
| 163 | - rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, | |
| 165 | + rid = content_put_ex(&content, blob_str(pUuid), srcid, | |
| 164 | 166 | 0, isPriv); |
| 165 | - Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]), | |
| 166 | - blob_size(&pXfer->aToken[1])); | |
| 167 | + Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), | |
| 168 | + blob_size(pUuid)); | |
| 167 | 169 | remote_has(rid); |
| 168 | 170 | blob_reset(&content); |
| 169 | 171 | return; |
| 170 | 172 | } |
| 171 | 173 | if( pXfer->nToken==4 ){ |
| 172 | 174 | Blob src, next; |
| 173 | 175 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| 174 | 176 | if( content_get(srcid, &src)==0 ){ |
| 175 | - rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, | |
| 177 | + rid = content_put_ex(&content, blob_str(pUuid), srcid, | |
| 176 | 178 | 0, isPriv); |
| 177 | - Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]), | |
| 178 | - blob_size(&pXfer->aToken[1])); | |
| 179 | + Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), | |
| 180 | + blob_size(pUuid)); | |
| 179 | 181 | pXfer->nDanglingFile++; |
| 180 | 182 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 181 | 183 | if( !isPriv ) content_make_public(rid); |
| 182 | 184 | blob_reset(&src); |
| 183 | 185 | blob_reset(&content); |
| @@ -189,19 +191,15 @@ | ||
| 189 | 191 | blob_reset(&content); |
| 190 | 192 | content = next; |
| 191 | 193 | }else{ |
| 192 | 194 | pXfer->nFileRcvd++; |
| 193 | 195 | } |
| 194 | - sha1sum_blob(&content, &hash); | |
| 195 | - if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){ | |
| 196 | - blob_appendf(&pXfer->err, | |
| 197 | - "wrong hash on received artifact: expected %s but got %s", | |
| 198 | - blob_str(&pXfer->aToken[1]), blob_str(&hash)); | |
| 199 | - } | |
| 200 | - rid = content_put_ex(&content, blob_str(&hash), 0, 0, isPriv); | |
| 201 | - Th_AppendToList(pzUuidList, pnUuidList, blob_str(&hash), blob_size(&hash)); | |
| 202 | - blob_reset(&hash); | |
| 196 | + if( hname_verify_hash(&content, blob_buffer(pUuid), blob_size(pUuid))==0 ){ | |
| 197 | + blob_appendf(&pXfer->err, "wrong hash on received artifact: %b", pUuid); | |
| 198 | + } | |
| 199 | + rid = content_put_ex(&content, blob_str(pUuid), 0, 0, isPriv); | |
| 200 | + Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), blob_size(pUuid)); | |
| 203 | 201 | if( rid==0 ){ |
| 204 | 202 | blob_appendf(&pXfer->err, "%s", g.zErrMsg); |
| 205 | 203 | blob_reset(&content); |
| 206 | 204 | }else{ |
| 207 | 205 | if( !isPriv ) content_make_public(rid); |
| @@ -217,18 +215,18 @@ | ||
| 217 | 215 | ** a record insert of the file. The difference between "file" and |
| 218 | 216 | ** "cfile" is that with "cfile" the content is already compressed. |
| 219 | 217 | ** |
| 220 | 218 | ** The file line is in one of the following two forms: |
| 221 | 219 | ** |
| 222 | -** cfile UUID USIZE CSIZE \n CONTENT | |
| 223 | -** cfile UUID DELTASRC USIZE CSIZE \n CONTENT | |
| 220 | +** cfile HASH USIZE CSIZE \n CONTENT | |
| 221 | +** cfile HASH DELTASRC USIZE CSIZE \n CONTENT | |
| 224 | 222 | ** |
| 225 | 223 | ** The content is CSIZE bytes immediately following the newline. |
| 226 | 224 | ** If DELTASRC exists, then the CONTENT is a delta against the |
| 227 | 225 | ** content of DELTASRC. |
| 228 | 226 | ** |
| 229 | -** The original size of the UUID artifact is USIZE. | |
| 227 | +** The original size of the HASH artifact is USIZE. | |
| 230 | 228 | ** |
| 231 | 229 | ** If any error occurs, write a message into pErr which has already |
| 232 | 230 | ** be initialized to an empty string. |
| 233 | 231 | ** |
| 234 | 232 | ** Any artifact successfully received by this routine is considered to |
| @@ -248,15 +246,15 @@ | ||
| 248 | 246 | |
| 249 | 247 | isPriv = pXfer->nextIsPrivate; |
| 250 | 248 | pXfer->nextIsPrivate = 0; |
| 251 | 249 | if( pXfer->nToken<4 |
| 252 | 250 | || pXfer->nToken>5 |
| 253 | - || !blob_is_uuid(&pXfer->aToken[1]) | |
| 251 | + || !blob_is_hname(&pXfer->aToken[1]) | |
| 254 | 252 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU) |
| 255 | 253 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC) |
| 256 | 254 | || szC<0 || szU<0 |
| 257 | - || (pXfer->nToken==5 && !blob_is_uuid(&pXfer->aToken[2])) | |
| 255 | + || (pXfer->nToken==5 && !blob_is_hname(&pXfer->aToken[2])) | |
| 258 | 256 | ){ |
| 259 | 257 | blob_appendf(&pXfer->err, "malformed cfile line"); |
| 260 | 258 | return; |
| 261 | 259 | } |
| 262 | 260 | if( isPriv && !g.perm.Private ){ |
| @@ -297,11 +295,11 @@ | ||
| 297 | 295 | ** |
| 298 | 296 | ** If the 0x0001 bit of FLAGS is set, that means the file has been |
| 299 | 297 | ** deleted, SIZE is zero, the HASH is "-", and the "\n CONTENT" is omitted. |
| 300 | 298 | ** |
| 301 | 299 | ** SIZE is the number of bytes of CONTENT. The CONTENT is uncompressed. |
| 302 | -** HASH is the SHA1 hash of CONTENT. | |
| 300 | +** HASH is the artifact hash of CONTENT. | |
| 303 | 301 | ** |
| 304 | 302 | ** If the 0x0004 bit of FLAGS is set, that means the CONTENT is omitted. |
| 305 | 303 | ** The sender might have omitted the content because it is too big to |
| 306 | 304 | ** transmit, or because it is unchanged and this record exists purely |
| 307 | 305 | ** to update the MTIME. |
| @@ -310,11 +308,10 @@ | ||
| 310 | 308 | sqlite3_int64 mtime; /* The MTIME */ |
| 311 | 309 | Blob *pHash; /* The HASH value */ |
| 312 | 310 | int sz; /* The SIZE */ |
| 313 | 311 | int flags; /* The FLAGS */ |
| 314 | 312 | Blob content; /* The CONTENT */ |
| 315 | - Blob hash; /* Hash computed from CONTENT to compare with HASH */ | |
| 316 | 313 | Blob x; /* Compressed content */ |
| 317 | 314 | Stmt q; /* SQL statements for comparison and insert */ |
| 318 | 315 | int isDelete; /* HASH is "-" indicating this is a delete */ |
| 319 | 316 | int nullContent; /* True of CONTENT is NULL */ |
| 320 | 317 | int iStatus; /* Result from unversioned_status() */ |
| @@ -321,25 +318,23 @@ | ||
| 321 | 318 | |
| 322 | 319 | pHash = &pXfer->aToken[3]; |
| 323 | 320 | if( pXfer->nToken==5 |
| 324 | 321 | || !blob_is_filename(&pXfer->aToken[1]) |
| 325 | 322 | || !blob_is_int64(&pXfer->aToken[2], &mtime) |
| 326 | - || (!blob_eq(pHash,"-") && !blob_is_uuid(pHash)) | |
| 323 | + || (!blob_eq(pHash,"-") && !blob_is_hname(pHash)) | |
| 327 | 324 | || !blob_is_int(&pXfer->aToken[4], &sz) |
| 328 | 325 | || !blob_is_int(&pXfer->aToken[5], &flags) |
| 329 | 326 | ){ |
| 330 | 327 | blob_appendf(&pXfer->err, "malformed uvfile line"); |
| 331 | 328 | return; |
| 332 | 329 | } |
| 333 | 330 | blob_init(&content, 0, 0); |
| 334 | - blob_init(&hash, 0, 0); | |
| 335 | 331 | blob_init(&x, 0, 0); |
| 336 | 332 | if( sz>0 && (flags & 0x0005)==0 ){ |
| 337 | 333 | blob_extract(pXfer->pIn, sz, &content); |
| 338 | 334 | nullContent = 0; |
| 339 | - sha1sum_blob(&content, &hash); | |
| 340 | - if( blob_compare(&hash, pHash)!=0 ){ | |
| 335 | + if( hname_verify_hash(&content, blob_buffer(pHash), blob_size(pHash))==0 ){ | |
| 341 | 336 | blob_appendf(&pXfer->err, "in uvfile line, HASH does not match CONTENT"); |
| 342 | 337 | goto end_accept_unversioned_file; |
| 343 | 338 | } |
| 344 | 339 | }else{ |
| 345 | 340 | nullContent = 1; |
| @@ -399,11 +394,10 @@ | ||
| 399 | 394 | db_unset("uv-hash", 0); |
| 400 | 395 | |
| 401 | 396 | end_accept_unversioned_file: |
| 402 | 397 | blob_reset(&x); |
| 403 | 398 | blob_reset(&content); |
| 404 | - blob_reset(&hash); | |
| 405 | 399 | } |
| 406 | 400 | |
| 407 | 401 | /* |
| 408 | 402 | ** Try to send a file as a delta against its parent. |
| 409 | 403 | ** If successful, return the number of bytes in the delta. |
| @@ -415,11 +409,11 @@ | ||
| 415 | 409 | static int send_delta_parent( |
| 416 | 410 | Xfer *pXfer, /* The transfer context */ |
| 417 | 411 | int rid, /* record id of the file to send */ |
| 418 | 412 | int isPrivate, /* True if rid is a private artifact */ |
| 419 | 413 | Blob *pContent, /* The content of the file to send */ |
| 420 | - Blob *pUuid /* The UUID of the file to send */ | |
| 414 | + Blob *pUuid /* The HASH of the file to send */ | |
| 421 | 415 | ){ |
| 422 | 416 | static const char *const azQuery[] = { |
| 423 | 417 | "SELECT pid FROM plink x" |
| 424 | 418 | " WHERE cid=%d" |
| 425 | 419 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)", |
| @@ -469,11 +463,11 @@ | ||
| 469 | 463 | */ |
| 470 | 464 | static int send_delta_native( |
| 471 | 465 | Xfer *pXfer, /* The transfer context */ |
| 472 | 466 | int rid, /* record id of the file to send */ |
| 473 | 467 | int isPrivate, /* True if rid is a private artifact */ |
| 474 | - Blob *pUuid /* The UUID of the file to send */ | |
| 468 | + Blob *pUuid /* The HASH of the file to send */ | |
| 475 | 469 | ){ |
| 476 | 470 | Blob src, delta; |
| 477 | 471 | int size = 0; |
| 478 | 472 | int srcId; |
| 479 | 473 | |
| @@ -500,15 +494,26 @@ | ||
| 500 | 494 | }else{ |
| 501 | 495 | size = 0; |
| 502 | 496 | } |
| 503 | 497 | return size; |
| 504 | 498 | } |
| 499 | + | |
| 500 | +/* | |
| 501 | +** Push an error message to alert the older client that the repository | |
| 502 | +** has SHA3 content and cannot be synced or cloned. | |
| 503 | +*/ | |
| 504 | +static void xfer_cannot_send_sha3_error(Xfer *pXfer){ | |
| 505 | + blob_appendf(pXfer->pOut, | |
| 506 | + "error Fossil\\sversion\\s2.0\\sor\\slater\\srequired.\n" | |
| 507 | + ); | |
| 508 | +} | |
| 509 | + | |
| 505 | 510 | |
| 506 | 511 | /* |
| 507 | 512 | ** Send the file identified by rid. |
| 508 | 513 | ** |
| 509 | -** The pUuid can be NULL in which case the correct UUID is computed | |
| 514 | +** The pUuid can be NULL in which case the correct hash is computed | |
| 510 | 515 | ** from the rid. |
| 511 | 516 | ** |
| 512 | 517 | ** Try to send the file as a native delta if nativeDelta is true, or |
| 513 | 518 | ** as a parent delta if nativeDelta is false. |
| 514 | 519 | ** |
| @@ -527,10 +532,14 @@ | ||
| 527 | 532 | } |
| 528 | 533 | blob_zero(&uuid); |
| 529 | 534 | db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid); |
| 530 | 535 | if( blob_size(&uuid)==0 ){ |
| 531 | 536 | return; |
| 537 | + } | |
| 538 | + if( blob_size(&uuid)>HNAME_LEN_SHA1 && pXfer->clientVersion<20000 ){ | |
| 539 | + xfer_cannot_send_sha3_error(pXfer); | |
| 540 | + return; | |
| 532 | 541 | } |
| 533 | 542 | if( pUuid ){ |
| 534 | 543 | if( blob_compare(pUuid, &uuid)!=0 ){ |
| 535 | 544 | blob_reset(&uuid); |
| 536 | 545 | return; |
| @@ -617,10 +626,15 @@ | ||
| 617 | 626 | szC = db_column_bytes(&q1, 2); |
| 618 | 627 | zContent = db_column_raw(&q1, 2); |
| 619 | 628 | srcIsPrivate = db_column_int(&q1, 3); |
| 620 | 629 | zDelta = db_column_text(&q1, 4); |
| 621 | 630 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 631 | + if( pXfer->clientVersion<20000 && db_column_bytes(&q1,0)!=HNAME_LEN_SHA1 ){ | |
| 632 | + xfer_cannot_send_sha3_error(pXfer); | |
| 633 | + db_reset(&q1); | |
| 634 | + return; | |
| 635 | + } | |
| 622 | 636 | blob_appendf(pXfer->pOut, "cfile %s ", zUuid); |
| 623 | 637 | if( !isPrivate && srcIsPrivate ){ |
| 624 | 638 | content_get(rid, &fullContent); |
| 625 | 639 | szU = blob_size(&fullContent); |
| 626 | 640 | blob_compress(&fullContent, &fullContent); |
| @@ -676,10 +690,15 @@ | ||
| 676 | 690 | ); |
| 677 | 691 | } |
| 678 | 692 | if( db_step(&q1)==SQLITE_ROW ){ |
| 679 | 693 | sqlite3_int64 mtime = db_column_int64(&q1, 0); |
| 680 | 694 | const char *zHash = db_column_text(&q1, 1); |
| 695 | + if( pXfer->clientVersion<20000 && db_column_bytes(&q1,1)>HNAME_LEN_SHA1 ){ | |
| 696 | + xfer_cannot_send_sha3_error(pXfer); | |
| 697 | + db_reset(&q1); | |
| 698 | + return; | |
| 699 | + } | |
| 681 | 700 | if( blob_size(pXfer->pOut)>=pXfer->mxSend ){ |
| 682 | 701 | /* If we have already reached the send size limit, send a (short) |
| 683 | 702 | ** uvigot card rather than a uvfile card. This only happens on the |
| 684 | 703 | ** server side. The uvigot card will provoke the client to resend |
| 685 | 704 | ** another uvgimme on the next cycle. */ |
| @@ -728,23 +747,23 @@ | ||
| 728 | 747 | } |
| 729 | 748 | db_finalize(&q); |
| 730 | 749 | } |
| 731 | 750 | |
| 732 | 751 | /* |
| 733 | -** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the | |
| 752 | +** Compute an hash on the tail of pMsg. Verify that it matches the | |
| 734 | 753 | ** the hash given in pHash. Return non-zero for an error and 0 on success. |
| 754 | +** | |
| 755 | +** The type of hash computed (SHA1, SHA3-256) is determined by | |
| 756 | +** the length of the input hash in pHash. | |
| 735 | 757 | */ |
| 736 | 758 | static int check_tail_hash(Blob *pHash, Blob *pMsg){ |
| 737 | 759 | Blob tail; |
| 738 | - Blob h2; | |
| 739 | 760 | int rc; |
| 740 | 761 | blob_tail(pMsg, &tail); |
| 741 | - sha1sum_blob(&tail, &h2); | |
| 742 | - rc = blob_compare(pHash, &h2); | |
| 743 | - blob_reset(&h2); | |
| 762 | + rc = hname_verify_hash(&tail, blob_buffer(pHash), blob_size(pHash)); | |
| 744 | 763 | blob_reset(&tail); |
| 745 | - return rc; | |
| 764 | + return rc==HNAME_ERROR; | |
| 746 | 765 | } |
| 747 | 766 | |
| 748 | 767 | /* |
| 749 | 768 | ** Check the signature on an application/x-fossil payload received by |
| 750 | 769 | ** the HTTP server. The signature is a line of the following form: |
| @@ -1198,12 +1217,12 @@ | ||
| 1198 | 1217 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 1199 | 1218 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 1200 | 1219 | if( blob_size(&xfer.line)==0 ) continue; |
| 1201 | 1220 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 1202 | 1221 | |
| 1203 | - /* file UUID SIZE \n CONTENT | |
| 1204 | - ** file UUID DELTASRC SIZE \n CONTENT | |
| 1222 | + /* file HASH SIZE \n CONTENT | |
| 1223 | + ** file HASH DELTASRC SIZE \n CONTENT | |
| 1205 | 1224 | ** |
| 1206 | 1225 | ** Accept a file from the client. |
| 1207 | 1226 | */ |
| 1208 | 1227 | if( blob_eq(&xfer.aToken[0], "file") ){ |
| 1209 | 1228 | if( !isPush ){ |
| @@ -1219,12 +1238,12 @@ | ||
| 1219 | 1238 | nErr++; |
| 1220 | 1239 | break; |
| 1221 | 1240 | } |
| 1222 | 1241 | }else |
| 1223 | 1242 | |
| 1224 | - /* cfile UUID USIZE CSIZE \n CONTENT | |
| 1225 | - ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT | |
| 1243 | + /* cfile HASH USIZE CSIZE \n CONTENT | |
| 1244 | + ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT | |
| 1226 | 1245 | ** |
| 1227 | 1246 | ** Accept a file from the client. |
| 1228 | 1247 | */ |
| 1229 | 1248 | if( blob_eq(&xfer.aToken[0], "cfile") ){ |
| 1230 | 1249 | if( !isPush ){ |
| @@ -1254,17 +1273,17 @@ | ||
| 1254 | 1273 | nErr++; |
| 1255 | 1274 | break; |
| 1256 | 1275 | } |
| 1257 | 1276 | }else |
| 1258 | 1277 | |
| 1259 | - /* gimme UUID | |
| 1278 | + /* gimme HASH | |
| 1260 | 1279 | ** |
| 1261 | 1280 | ** Client is requesting a file. Send it. |
| 1262 | 1281 | */ |
| 1263 | 1282 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 1264 | 1283 | && xfer.nToken==2 |
| 1265 | - && blob_is_uuid(&xfer.aToken[1]) | |
| 1284 | + && blob_is_hname(&xfer.aToken[1]) | |
| 1266 | 1285 | ){ |
| 1267 | 1286 | nGimme++; |
| 1268 | 1287 | if( isPull ){ |
| 1269 | 1288 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1270 | 1289 | if( rid ){ |
| @@ -1282,18 +1301,18 @@ | ||
| 1282 | 1301 | && blob_is_filename(&xfer.aToken[1]) |
| 1283 | 1302 | ){ |
| 1284 | 1303 | send_unversioned_file(&xfer, blob_str(&xfer.aToken[1]), 0); |
| 1285 | 1304 | }else |
| 1286 | 1305 | |
| 1287 | - /* igot UUID ?ISPRIVATE? | |
| 1306 | + /* igot HASH ?ISPRIVATE? | |
| 1288 | 1307 | ** |
| 1289 | 1308 | ** Client announces that it has a particular file. If the ISPRIVATE |
| 1290 | 1309 | ** argument exists and is non-zero, then the file is a private file. |
| 1291 | 1310 | */ |
| 1292 | 1311 | if( xfer.nToken>=2 |
| 1293 | 1312 | && blob_eq(&xfer.aToken[0], "igot") |
| 1294 | - && blob_is_uuid(&xfer.aToken[1]) | |
| 1313 | + && blob_is_hname(&xfer.aToken[1]) | |
| 1295 | 1314 | ){ |
| 1296 | 1315 | if( isPush ){ |
| 1297 | 1316 | if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){ |
| 1298 | 1317 | rid_from_uuid(&xfer.aToken[1], 1, 0); |
| 1299 | 1318 | }else if( g.perm.Private ){ |
| @@ -1307,16 +1326,15 @@ | ||
| 1307 | 1326 | |
| 1308 | 1327 | /* pull SERVERCODE PROJECTCODE |
| 1309 | 1328 | ** push SERVERCODE PROJECTCODE |
| 1310 | 1329 | ** |
| 1311 | 1330 | ** The client wants either send or receive. The server should |
| 1312 | - ** verify that the project code matches. | |
| 1331 | + ** verify that the project code matches. The server code is ignored. | |
| 1313 | 1332 | */ |
| 1314 | 1333 | if( xfer.nToken==3 |
| 1315 | 1334 | && (blob_eq(&xfer.aToken[0], "pull") || blob_eq(&xfer.aToken[0], "push")) |
| 1316 | - && blob_is_uuid(&xfer.aToken[1]) | |
| 1317 | - && blob_is_uuid(&xfer.aToken[2]) | |
| 1335 | + && blob_is_hname(&xfer.aToken[2]) | |
| 1318 | 1336 | ){ |
| 1319 | 1337 | const char *zPCode; |
| 1320 | 1338 | zPCode = db_get("project-code", 0); |
| 1321 | 1339 | if( zPCode==0 ){ |
| 1322 | 1340 | fossil_panic("missing project code"); |
| @@ -1534,19 +1552,27 @@ | ||
| 1534 | 1552 | ** Send igot cards for all known artifacts. |
| 1535 | 1553 | */ |
| 1536 | 1554 | if( blob_eq(&xfer.aToken[1], "send-catalog") ){ |
| 1537 | 1555 | xfer.resync = 0x7fffffff; |
| 1538 | 1556 | } |
| 1557 | + | |
| 1558 | + /* pragma client-version VERSION | |
| 1559 | + ** | |
| 1560 | + ** Let the server know what version of Fossil is running on the client. | |
| 1561 | + */ | |
| 1562 | + if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){ | |
| 1563 | + xfer.clientVersion = atoi(blob_str(&xfer.aToken[2])); | |
| 1564 | + } | |
| 1539 | 1565 | |
| 1540 | 1566 | /* pragma uv-hash HASH |
| 1541 | 1567 | ** |
| 1542 | 1568 | ** The client wants to make sure that unversioned files are all synced. |
| 1543 | 1569 | ** If the HASH does not match, send a complete catalog of |
| 1544 | 1570 | ** "uvigot" cards. |
| 1545 | 1571 | */ |
| 1546 | 1572 | if( blob_eq(&xfer.aToken[1], "uv-hash") |
| 1547 | - && blob_is_uuid(&xfer.aToken[2]) | |
| 1573 | + && blob_is_hname(&xfer.aToken[2]) | |
| 1548 | 1574 | ){ |
| 1549 | 1575 | if( !uvCatalogSent ){ |
| 1550 | 1576 | if( g.perm.Read && g.perm.WrUnver ){ |
| 1551 | 1577 | @ pragma uv-push-ok |
| 1552 | 1578 | send_unversioned_catalog(&xfer); |
| @@ -1742,10 +1768,11 @@ | ||
| 1742 | 1768 | memset(&xfer, 0, sizeof(xfer)); |
| 1743 | 1769 | xfer.pIn = &recv; |
| 1744 | 1770 | xfer.pOut = &send; |
| 1745 | 1771 | xfer.mxSend = db_get_int("max-upload", 250000); |
| 1746 | 1772 | xfer.maxTime = -1; |
| 1773 | + xfer.clientVersion = RELEASE_VERSION_NUMBER; | |
| 1747 | 1774 | if( syncFlags & SYNC_PRIVATE ){ |
| 1748 | 1775 | g.perm.Private = 1; |
| 1749 | 1776 | xfer.syncPrivate = 1; |
| 1750 | 1777 | } |
| 1751 | 1778 | |
| @@ -1783,10 +1810,11 @@ | ||
| 1783 | 1810 | } |
| 1784 | 1811 | |
| 1785 | 1812 | /* |
| 1786 | 1813 | ** Always begin with a clone, pull, or push message |
| 1787 | 1814 | */ |
| 1815 | + blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER); | |
| 1788 | 1816 | if( syncFlags & SYNC_CLONE ){ |
| 1789 | 1817 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 1790 | 1818 | syncFlags &= ~(SYNC_PUSH|SYNC_PULL); |
| 1791 | 1819 | nCardSent++; |
| 1792 | 1820 | /* TBD: Request all transferable configuration values */ |
| @@ -1819,10 +1847,11 @@ | ||
| 1819 | 1847 | db_record_repository_filename(0); |
| 1820 | 1848 | db_multi_exec( |
| 1821 | 1849 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1822 | 1850 | ); |
| 1823 | 1851 | manifest_crosslink_begin(); |
| 1852 | + | |
| 1824 | 1853 | |
| 1825 | 1854 | /* Send back the most recently received cookie. Let the server |
| 1826 | 1855 | ** figure out if this is a cookie that it cares about. |
| 1827 | 1856 | */ |
| 1828 | 1857 | zCookie = db_get("cookie", 0); |
| @@ -1976,10 +2005,11 @@ | ||
| 1976 | 2005 | xfer.nGimmeSent = 0; |
| 1977 | 2006 | xfer.nIGotSent = 0; |
| 1978 | 2007 | |
| 1979 | 2008 | lastPctDone = -1; |
| 1980 | 2009 | blob_reset(&send); |
| 2010 | + blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER); | |
| 1981 | 2011 | rArrivalTime = db_double(0.0, "SELECT julianday('now')"); |
| 1982 | 2012 | |
| 1983 | 2013 | /* Send the send-private pragma if we are trying to sync private data */ |
| 1984 | 2014 | if( syncFlags & SYNC_PRIVATE ){ |
| 1985 | 2015 | blob_append(&send, "pragma send-private\n", -1); |
| @@ -2028,22 +2058,22 @@ | ||
| 2028 | 2058 | lastPctDone = pctDone; |
| 2029 | 2059 | fflush(stdout); |
| 2030 | 2060 | } |
| 2031 | 2061 | } |
| 2032 | 2062 | |
| 2033 | - /* file UUID SIZE \n CONTENT | |
| 2034 | - ** file UUID DELTASRC SIZE \n CONTENT | |
| 2063 | + /* file HASH SIZE \n CONTENT | |
| 2064 | + ** file HASH DELTASRC SIZE \n CONTENT | |
| 2035 | 2065 | ** |
| 2036 | 2066 | ** Receive a file transmitted from the server. |
| 2037 | 2067 | */ |
| 2038 | 2068 | if( blob_eq(&xfer.aToken[0],"file") ){ |
| 2039 | 2069 | xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0); |
| 2040 | 2070 | nArtifactRcvd++; |
| 2041 | 2071 | }else |
| 2042 | 2072 | |
| 2043 | - /* cfile UUID USIZE CSIZE \n CONTENT | |
| 2044 | - ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT | |
| 2073 | + /* cfile HASH USIZE CSIZE \n CONTENT | |
| 2074 | + ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT | |
| 2045 | 2075 | ** |
| 2046 | 2076 | ** Receive a compressed file transmitted from the server. |
| 2047 | 2077 | */ |
| 2048 | 2078 | if( blob_eq(&xfer.aToken[0],"cfile") ){ |
| 2049 | 2079 | xfer_accept_compressed_file(&xfer, 0, 0); |
| @@ -2062,27 +2092,27 @@ | ||
| 2062 | 2092 | fossil_print("\rUnversioned-file received: %s\n", |
| 2063 | 2093 | blob_str(&xfer.aToken[1])); |
| 2064 | 2094 | } |
| 2065 | 2095 | }else |
| 2066 | 2096 | |
| 2067 | - /* gimme UUID | |
| 2097 | + /* gimme HASH | |
| 2068 | 2098 | ** |
| 2069 | 2099 | ** Server is requesting a file. If the file is a manifest, assume |
| 2070 | 2100 | ** that the server will also want to know all of the content files |
| 2071 | 2101 | ** associated with the manifest and send those too. |
| 2072 | 2102 | */ |
| 2073 | 2103 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 2074 | 2104 | && xfer.nToken==2 |
| 2075 | - && blob_is_uuid(&xfer.aToken[1]) | |
| 2105 | + && blob_is_hname(&xfer.aToken[1]) | |
| 2076 | 2106 | ){ |
| 2077 | 2107 | if( syncFlags & SYNC_PUSH ){ |
| 2078 | 2108 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2079 | 2109 | if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); |
| 2080 | 2110 | } |
| 2081 | 2111 | }else |
| 2082 | 2112 | |
| 2083 | - /* igot UUID ?PRIVATEFLAG? | |
| 2113 | + /* igot HASH ?PRIVATEFLAG? | |
| 2084 | 2114 | ** |
| 2085 | 2115 | ** Server announces that it has a particular file. If this is |
| 2086 | 2116 | ** not a file that we have and we are pulling, then create a |
| 2087 | 2117 | ** phantom to cause this file to be requested on the next cycle. |
| 2088 | 2118 | ** Always remember that the server has this file so that we do |
| @@ -2092,11 +2122,11 @@ | ||
| 2092 | 2122 | ** private. Pretend it does not exists if we are not pulling |
| 2093 | 2123 | ** private files. |
| 2094 | 2124 | */ |
| 2095 | 2125 | if( xfer.nToken>=2 |
| 2096 | 2126 | && blob_eq(&xfer.aToken[0], "igot") |
| 2097 | - && blob_is_uuid(&xfer.aToken[1]) | |
| 2127 | + && blob_is_hname(&xfer.aToken[1]) | |
| 2098 | 2128 | ){ |
| 2099 | 2129 | int rid; |
| 2100 | 2130 | int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1"); |
| 2101 | 2131 | rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2102 | 2132 | if( rid>0 ){ |
| @@ -2126,11 +2156,11 @@ | ||
| 2126 | 2156 | if( xfer.nToken==5 |
| 2127 | 2157 | && blob_eq(&xfer.aToken[0], "uvigot") |
| 2128 | 2158 | && blob_is_filename(&xfer.aToken[1]) |
| 2129 | 2159 | && blob_is_int64(&xfer.aToken[2], &mtime) |
| 2130 | 2160 | && blob_is_int(&xfer.aToken[4], &size) |
| 2131 | - && (blob_eq(&xfer.aToken[3],"-") || blob_is_uuid(&xfer.aToken[3])) | |
| 2161 | + && (blob_eq(&xfer.aToken[3],"-") || blob_is_hname(&xfer.aToken[3])) | |
| 2132 | 2162 | ){ |
| 2133 | 2163 | const char *zName = blob_str(&xfer.aToken[1]); |
| 2134 | 2164 | const char *zHash = blob_str(&xfer.aToken[3]); |
| 2135 | 2165 | int iStatus; |
| 2136 | 2166 | iStatus = unversioned_status(zName, mtime, zHash); |
| @@ -2188,11 +2218,11 @@ | ||
| 2188 | 2218 | ** the client what product to use for the new database. |
| 2189 | 2219 | */ |
| 2190 | 2220 | if( blob_eq(&xfer.aToken[0],"push") |
| 2191 | 2221 | && xfer.nToken==3 |
| 2192 | 2222 | && (syncFlags & SYNC_CLONE)!=0 |
| 2193 | - && blob_is_uuid(&xfer.aToken[2]) | |
| 2223 | + && blob_is_hname(&xfer.aToken[2]) | |
| 2194 | 2224 | ){ |
| 2195 | 2225 | if( zPCode==0 ){ |
| 2196 | 2226 | zPCode = mprintf("%b", &xfer.aToken[2]); |
| 2197 | 2227 | db_set("project-code", zPCode, 0); |
| 2198 | 2228 | } |
| 2199 | 2229 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -49,16 +49,17 @@ | |
| 49 | int nDanglingFile; /* Number of dangling deltas received */ |
| 50 | int mxSend; /* Stop sending "file" when pOut reaches this size */ |
| 51 | int resync; /* Send igot cards for all holdings */ |
| 52 | u8 syncPrivate; /* True to enable syncing private content */ |
| 53 | u8 nextIsPrivate; /* If true, next "file" received is a private */ |
| 54 | time_t maxTime; /* Time when this transfer should be finished */ |
| 55 | }; |
| 56 | |
| 57 | |
| 58 | /* |
| 59 | ** The input blob contains a UUID. Convert it into a record ID. |
| 60 | ** Create a phantom record if no prior record exists and |
| 61 | ** phantomize is true. |
| 62 | ** |
| 63 | ** Compare to uuid_to_rid(). This routine takes a blob argument |
| 64 | ** and does less error checking. |
| @@ -100,12 +101,12 @@ | |
| 100 | ** message. This routine finishes parsing that message and does |
| 101 | ** a record insert of the file. |
| 102 | ** |
| 103 | ** The file line is in one of the following two forms: |
| 104 | ** |
| 105 | ** file UUID SIZE \n CONTENT |
| 106 | ** file UUID DELTASRC SIZE \n CONTENT |
| 107 | ** |
| 108 | ** The content is SIZE bytes immediately following the newline. |
| 109 | ** If DELTASRC exists, then the CONTENT is a delta against the |
| 110 | ** content of DELTASRC. |
| 111 | ** |
| @@ -122,29 +123,30 @@ | |
| 122 | int *pnUuidList |
| 123 | ){ |
| 124 | int n; |
| 125 | int rid; |
| 126 | int srcid = 0; |
| 127 | Blob content, hash; |
| 128 | int isPriv; |
| 129 | |
| 130 | isPriv = pXfer->nextIsPrivate; |
| 131 | pXfer->nextIsPrivate = 0; |
| 132 | if( pXfer->nToken<3 |
| 133 | || pXfer->nToken>4 |
| 134 | || !blob_is_uuid(&pXfer->aToken[1]) |
| 135 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n) |
| 136 | || n<0 |
| 137 | || (pXfer->nToken==4 && !blob_is_uuid(&pXfer->aToken[2])) |
| 138 | ){ |
| 139 | blob_appendf(&pXfer->err, "malformed file line"); |
| 140 | return; |
| 141 | } |
| 142 | blob_zero(&content); |
| 143 | blob_zero(&hash); |
| 144 | blob_extract(pXfer->pIn, n, &content); |
| 145 | if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ |
| 146 | /* Ignore files that have been shunned */ |
| 147 | blob_reset(&content); |
| 148 | return; |
| 149 | } |
| 150 | if( isPriv && !g.perm.Private ){ |
| @@ -158,26 +160,26 @@ | |
| 158 | pXfer->nDeltaRcvd++; |
| 159 | }else{ |
| 160 | srcid = 0; |
| 161 | pXfer->nFileRcvd++; |
| 162 | } |
| 163 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 164 | 0, isPriv); |
| 165 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]), |
| 166 | blob_size(&pXfer->aToken[1])); |
| 167 | remote_has(rid); |
| 168 | blob_reset(&content); |
| 169 | return; |
| 170 | } |
| 171 | if( pXfer->nToken==4 ){ |
| 172 | Blob src, next; |
| 173 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| 174 | if( content_get(srcid, &src)==0 ){ |
| 175 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 176 | 0, isPriv); |
| 177 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]), |
| 178 | blob_size(&pXfer->aToken[1])); |
| 179 | pXfer->nDanglingFile++; |
| 180 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 181 | if( !isPriv ) content_make_public(rid); |
| 182 | blob_reset(&src); |
| 183 | blob_reset(&content); |
| @@ -189,19 +191,15 @@ | |
| 189 | blob_reset(&content); |
| 190 | content = next; |
| 191 | }else{ |
| 192 | pXfer->nFileRcvd++; |
| 193 | } |
| 194 | sha1sum_blob(&content, &hash); |
| 195 | if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){ |
| 196 | blob_appendf(&pXfer->err, |
| 197 | "wrong hash on received artifact: expected %s but got %s", |
| 198 | blob_str(&pXfer->aToken[1]), blob_str(&hash)); |
| 199 | } |
| 200 | rid = content_put_ex(&content, blob_str(&hash), 0, 0, isPriv); |
| 201 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(&hash), blob_size(&hash)); |
| 202 | blob_reset(&hash); |
| 203 | if( rid==0 ){ |
| 204 | blob_appendf(&pXfer->err, "%s", g.zErrMsg); |
| 205 | blob_reset(&content); |
| 206 | }else{ |
| 207 | if( !isPriv ) content_make_public(rid); |
| @@ -217,18 +215,18 @@ | |
| 217 | ** a record insert of the file. The difference between "file" and |
| 218 | ** "cfile" is that with "cfile" the content is already compressed. |
| 219 | ** |
| 220 | ** The file line is in one of the following two forms: |
| 221 | ** |
| 222 | ** cfile UUID USIZE CSIZE \n CONTENT |
| 223 | ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT |
| 224 | ** |
| 225 | ** The content is CSIZE bytes immediately following the newline. |
| 226 | ** If DELTASRC exists, then the CONTENT is a delta against the |
| 227 | ** content of DELTASRC. |
| 228 | ** |
| 229 | ** The original size of the UUID artifact is USIZE. |
| 230 | ** |
| 231 | ** If any error occurs, write a message into pErr which has already |
| 232 | ** be initialized to an empty string. |
| 233 | ** |
| 234 | ** Any artifact successfully received by this routine is considered to |
| @@ -248,15 +246,15 @@ | |
| 248 | |
| 249 | isPriv = pXfer->nextIsPrivate; |
| 250 | pXfer->nextIsPrivate = 0; |
| 251 | if( pXfer->nToken<4 |
| 252 | || pXfer->nToken>5 |
| 253 | || !blob_is_uuid(&pXfer->aToken[1]) |
| 254 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU) |
| 255 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC) |
| 256 | || szC<0 || szU<0 |
| 257 | || (pXfer->nToken==5 && !blob_is_uuid(&pXfer->aToken[2])) |
| 258 | ){ |
| 259 | blob_appendf(&pXfer->err, "malformed cfile line"); |
| 260 | return; |
| 261 | } |
| 262 | if( isPriv && !g.perm.Private ){ |
| @@ -297,11 +295,11 @@ | |
| 297 | ** |
| 298 | ** If the 0x0001 bit of FLAGS is set, that means the file has been |
| 299 | ** deleted, SIZE is zero, the HASH is "-", and the "\n CONTENT" is omitted. |
| 300 | ** |
| 301 | ** SIZE is the number of bytes of CONTENT. The CONTENT is uncompressed. |
| 302 | ** HASH is the SHA1 hash of CONTENT. |
| 303 | ** |
| 304 | ** If the 0x0004 bit of FLAGS is set, that means the CONTENT is omitted. |
| 305 | ** The sender might have omitted the content because it is too big to |
| 306 | ** transmit, or because it is unchanged and this record exists purely |
| 307 | ** to update the MTIME. |
| @@ -310,11 +308,10 @@ | |
| 310 | sqlite3_int64 mtime; /* The MTIME */ |
| 311 | Blob *pHash; /* The HASH value */ |
| 312 | int sz; /* The SIZE */ |
| 313 | int flags; /* The FLAGS */ |
| 314 | Blob content; /* The CONTENT */ |
| 315 | Blob hash; /* Hash computed from CONTENT to compare with HASH */ |
| 316 | Blob x; /* Compressed content */ |
| 317 | Stmt q; /* SQL statements for comparison and insert */ |
| 318 | int isDelete; /* HASH is "-" indicating this is a delete */ |
| 319 | int nullContent; /* True of CONTENT is NULL */ |
| 320 | int iStatus; /* Result from unversioned_status() */ |
| @@ -321,25 +318,23 @@ | |
| 321 | |
| 322 | pHash = &pXfer->aToken[3]; |
| 323 | if( pXfer->nToken==5 |
| 324 | || !blob_is_filename(&pXfer->aToken[1]) |
| 325 | || !blob_is_int64(&pXfer->aToken[2], &mtime) |
| 326 | || (!blob_eq(pHash,"-") && !blob_is_uuid(pHash)) |
| 327 | || !blob_is_int(&pXfer->aToken[4], &sz) |
| 328 | || !blob_is_int(&pXfer->aToken[5], &flags) |
| 329 | ){ |
| 330 | blob_appendf(&pXfer->err, "malformed uvfile line"); |
| 331 | return; |
| 332 | } |
| 333 | blob_init(&content, 0, 0); |
| 334 | blob_init(&hash, 0, 0); |
| 335 | blob_init(&x, 0, 0); |
| 336 | if( sz>0 && (flags & 0x0005)==0 ){ |
| 337 | blob_extract(pXfer->pIn, sz, &content); |
| 338 | nullContent = 0; |
| 339 | sha1sum_blob(&content, &hash); |
| 340 | if( blob_compare(&hash, pHash)!=0 ){ |
| 341 | blob_appendf(&pXfer->err, "in uvfile line, HASH does not match CONTENT"); |
| 342 | goto end_accept_unversioned_file; |
| 343 | } |
| 344 | }else{ |
| 345 | nullContent = 1; |
| @@ -399,11 +394,10 @@ | |
| 399 | db_unset("uv-hash", 0); |
| 400 | |
| 401 | end_accept_unversioned_file: |
| 402 | blob_reset(&x); |
| 403 | blob_reset(&content); |
| 404 | blob_reset(&hash); |
| 405 | } |
| 406 | |
| 407 | /* |
| 408 | ** Try to send a file as a delta against its parent. |
| 409 | ** If successful, return the number of bytes in the delta. |
| @@ -415,11 +409,11 @@ | |
| 415 | static int send_delta_parent( |
| 416 | Xfer *pXfer, /* The transfer context */ |
| 417 | int rid, /* record id of the file to send */ |
| 418 | int isPrivate, /* True if rid is a private artifact */ |
| 419 | Blob *pContent, /* The content of the file to send */ |
| 420 | Blob *pUuid /* The UUID of the file to send */ |
| 421 | ){ |
| 422 | static const char *const azQuery[] = { |
| 423 | "SELECT pid FROM plink x" |
| 424 | " WHERE cid=%d" |
| 425 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)", |
| @@ -469,11 +463,11 @@ | |
| 469 | */ |
| 470 | static int send_delta_native( |
| 471 | Xfer *pXfer, /* The transfer context */ |
| 472 | int rid, /* record id of the file to send */ |
| 473 | int isPrivate, /* True if rid is a private artifact */ |
| 474 | Blob *pUuid /* The UUID of the file to send */ |
| 475 | ){ |
| 476 | Blob src, delta; |
| 477 | int size = 0; |
| 478 | int srcId; |
| 479 | |
| @@ -500,15 +494,26 @@ | |
| 500 | }else{ |
| 501 | size = 0; |
| 502 | } |
| 503 | return size; |
| 504 | } |
| 505 | |
| 506 | /* |
| 507 | ** Send the file identified by rid. |
| 508 | ** |
| 509 | ** The pUuid can be NULL in which case the correct UUID is computed |
| 510 | ** from the rid. |
| 511 | ** |
| 512 | ** Try to send the file as a native delta if nativeDelta is true, or |
| 513 | ** as a parent delta if nativeDelta is false. |
| 514 | ** |
| @@ -527,10 +532,14 @@ | |
| 527 | } |
| 528 | blob_zero(&uuid); |
| 529 | db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid); |
| 530 | if( blob_size(&uuid)==0 ){ |
| 531 | return; |
| 532 | } |
| 533 | if( pUuid ){ |
| 534 | if( blob_compare(pUuid, &uuid)!=0 ){ |
| 535 | blob_reset(&uuid); |
| 536 | return; |
| @@ -617,10 +626,15 @@ | |
| 617 | szC = db_column_bytes(&q1, 2); |
| 618 | zContent = db_column_raw(&q1, 2); |
| 619 | srcIsPrivate = db_column_int(&q1, 3); |
| 620 | zDelta = db_column_text(&q1, 4); |
| 621 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 622 | blob_appendf(pXfer->pOut, "cfile %s ", zUuid); |
| 623 | if( !isPrivate && srcIsPrivate ){ |
| 624 | content_get(rid, &fullContent); |
| 625 | szU = blob_size(&fullContent); |
| 626 | blob_compress(&fullContent, &fullContent); |
| @@ -676,10 +690,15 @@ | |
| 676 | ); |
| 677 | } |
| 678 | if( db_step(&q1)==SQLITE_ROW ){ |
| 679 | sqlite3_int64 mtime = db_column_int64(&q1, 0); |
| 680 | const char *zHash = db_column_text(&q1, 1); |
| 681 | if( blob_size(pXfer->pOut)>=pXfer->mxSend ){ |
| 682 | /* If we have already reached the send size limit, send a (short) |
| 683 | ** uvigot card rather than a uvfile card. This only happens on the |
| 684 | ** server side. The uvigot card will provoke the client to resend |
| 685 | ** another uvgimme on the next cycle. */ |
| @@ -728,23 +747,23 @@ | |
| 728 | } |
| 729 | db_finalize(&q); |
| 730 | } |
| 731 | |
| 732 | /* |
| 733 | ** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the |
| 734 | ** the hash given in pHash. Return non-zero for an error and 0 on success. |
| 735 | */ |
| 736 | static int check_tail_hash(Blob *pHash, Blob *pMsg){ |
| 737 | Blob tail; |
| 738 | Blob h2; |
| 739 | int rc; |
| 740 | blob_tail(pMsg, &tail); |
| 741 | sha1sum_blob(&tail, &h2); |
| 742 | rc = blob_compare(pHash, &h2); |
| 743 | blob_reset(&h2); |
| 744 | blob_reset(&tail); |
| 745 | return rc; |
| 746 | } |
| 747 | |
| 748 | /* |
| 749 | ** Check the signature on an application/x-fossil payload received by |
| 750 | ** the HTTP server. The signature is a line of the following form: |
| @@ -1198,12 +1217,12 @@ | |
| 1198 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 1199 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 1200 | if( blob_size(&xfer.line)==0 ) continue; |
| 1201 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 1202 | |
| 1203 | /* file UUID SIZE \n CONTENT |
| 1204 | ** file UUID DELTASRC SIZE \n CONTENT |
| 1205 | ** |
| 1206 | ** Accept a file from the client. |
| 1207 | */ |
| 1208 | if( blob_eq(&xfer.aToken[0], "file") ){ |
| 1209 | if( !isPush ){ |
| @@ -1219,12 +1238,12 @@ | |
| 1219 | nErr++; |
| 1220 | break; |
| 1221 | } |
| 1222 | }else |
| 1223 | |
| 1224 | /* cfile UUID USIZE CSIZE \n CONTENT |
| 1225 | ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT |
| 1226 | ** |
| 1227 | ** Accept a file from the client. |
| 1228 | */ |
| 1229 | if( blob_eq(&xfer.aToken[0], "cfile") ){ |
| 1230 | if( !isPush ){ |
| @@ -1254,17 +1273,17 @@ | |
| 1254 | nErr++; |
| 1255 | break; |
| 1256 | } |
| 1257 | }else |
| 1258 | |
| 1259 | /* gimme UUID |
| 1260 | ** |
| 1261 | ** Client is requesting a file. Send it. |
| 1262 | */ |
| 1263 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 1264 | && xfer.nToken==2 |
| 1265 | && blob_is_uuid(&xfer.aToken[1]) |
| 1266 | ){ |
| 1267 | nGimme++; |
| 1268 | if( isPull ){ |
| 1269 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1270 | if( rid ){ |
| @@ -1282,18 +1301,18 @@ | |
| 1282 | && blob_is_filename(&xfer.aToken[1]) |
| 1283 | ){ |
| 1284 | send_unversioned_file(&xfer, blob_str(&xfer.aToken[1]), 0); |
| 1285 | }else |
| 1286 | |
| 1287 | /* igot UUID ?ISPRIVATE? |
| 1288 | ** |
| 1289 | ** Client announces that it has a particular file. If the ISPRIVATE |
| 1290 | ** argument exists and is non-zero, then the file is a private file. |
| 1291 | */ |
| 1292 | if( xfer.nToken>=2 |
| 1293 | && blob_eq(&xfer.aToken[0], "igot") |
| 1294 | && blob_is_uuid(&xfer.aToken[1]) |
| 1295 | ){ |
| 1296 | if( isPush ){ |
| 1297 | if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){ |
| 1298 | rid_from_uuid(&xfer.aToken[1], 1, 0); |
| 1299 | }else if( g.perm.Private ){ |
| @@ -1307,16 +1326,15 @@ | |
| 1307 | |
| 1308 | /* pull SERVERCODE PROJECTCODE |
| 1309 | ** push SERVERCODE PROJECTCODE |
| 1310 | ** |
| 1311 | ** The client wants either send or receive. The server should |
| 1312 | ** verify that the project code matches. |
| 1313 | */ |
| 1314 | if( xfer.nToken==3 |
| 1315 | && (blob_eq(&xfer.aToken[0], "pull") || blob_eq(&xfer.aToken[0], "push")) |
| 1316 | && blob_is_uuid(&xfer.aToken[1]) |
| 1317 | && blob_is_uuid(&xfer.aToken[2]) |
| 1318 | ){ |
| 1319 | const char *zPCode; |
| 1320 | zPCode = db_get("project-code", 0); |
| 1321 | if( zPCode==0 ){ |
| 1322 | fossil_panic("missing project code"); |
| @@ -1534,19 +1552,27 @@ | |
| 1534 | ** Send igot cards for all known artifacts. |
| 1535 | */ |
| 1536 | if( blob_eq(&xfer.aToken[1], "send-catalog") ){ |
| 1537 | xfer.resync = 0x7fffffff; |
| 1538 | } |
| 1539 | |
| 1540 | /* pragma uv-hash HASH |
| 1541 | ** |
| 1542 | ** The client wants to make sure that unversioned files are all synced. |
| 1543 | ** If the HASH does not match, send a complete catalog of |
| 1544 | ** "uvigot" cards. |
| 1545 | */ |
| 1546 | if( blob_eq(&xfer.aToken[1], "uv-hash") |
| 1547 | && blob_is_uuid(&xfer.aToken[2]) |
| 1548 | ){ |
| 1549 | if( !uvCatalogSent ){ |
| 1550 | if( g.perm.Read && g.perm.WrUnver ){ |
| 1551 | @ pragma uv-push-ok |
| 1552 | send_unversioned_catalog(&xfer); |
| @@ -1742,10 +1768,11 @@ | |
| 1742 | memset(&xfer, 0, sizeof(xfer)); |
| 1743 | xfer.pIn = &recv; |
| 1744 | xfer.pOut = &send; |
| 1745 | xfer.mxSend = db_get_int("max-upload", 250000); |
| 1746 | xfer.maxTime = -1; |
| 1747 | if( syncFlags & SYNC_PRIVATE ){ |
| 1748 | g.perm.Private = 1; |
| 1749 | xfer.syncPrivate = 1; |
| 1750 | } |
| 1751 | |
| @@ -1783,10 +1810,11 @@ | |
| 1783 | } |
| 1784 | |
| 1785 | /* |
| 1786 | ** Always begin with a clone, pull, or push message |
| 1787 | */ |
| 1788 | if( syncFlags & SYNC_CLONE ){ |
| 1789 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 1790 | syncFlags &= ~(SYNC_PUSH|SYNC_PULL); |
| 1791 | nCardSent++; |
| 1792 | /* TBD: Request all transferable configuration values */ |
| @@ -1819,10 +1847,11 @@ | |
| 1819 | db_record_repository_filename(0); |
| 1820 | db_multi_exec( |
| 1821 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1822 | ); |
| 1823 | manifest_crosslink_begin(); |
| 1824 | |
| 1825 | /* Send back the most recently received cookie. Let the server |
| 1826 | ** figure out if this is a cookie that it cares about. |
| 1827 | */ |
| 1828 | zCookie = db_get("cookie", 0); |
| @@ -1976,10 +2005,11 @@ | |
| 1976 | xfer.nGimmeSent = 0; |
| 1977 | xfer.nIGotSent = 0; |
| 1978 | |
| 1979 | lastPctDone = -1; |
| 1980 | blob_reset(&send); |
| 1981 | rArrivalTime = db_double(0.0, "SELECT julianday('now')"); |
| 1982 | |
| 1983 | /* Send the send-private pragma if we are trying to sync private data */ |
| 1984 | if( syncFlags & SYNC_PRIVATE ){ |
| 1985 | blob_append(&send, "pragma send-private\n", -1); |
| @@ -2028,22 +2058,22 @@ | |
| 2028 | lastPctDone = pctDone; |
| 2029 | fflush(stdout); |
| 2030 | } |
| 2031 | } |
| 2032 | |
| 2033 | /* file UUID SIZE \n CONTENT |
| 2034 | ** file UUID DELTASRC SIZE \n CONTENT |
| 2035 | ** |
| 2036 | ** Receive a file transmitted from the server. |
| 2037 | */ |
| 2038 | if( blob_eq(&xfer.aToken[0],"file") ){ |
| 2039 | xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0); |
| 2040 | nArtifactRcvd++; |
| 2041 | }else |
| 2042 | |
| 2043 | /* cfile UUID USIZE CSIZE \n CONTENT |
| 2044 | ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT |
| 2045 | ** |
| 2046 | ** Receive a compressed file transmitted from the server. |
| 2047 | */ |
| 2048 | if( blob_eq(&xfer.aToken[0],"cfile") ){ |
| 2049 | xfer_accept_compressed_file(&xfer, 0, 0); |
| @@ -2062,27 +2092,27 @@ | |
| 2062 | fossil_print("\rUnversioned-file received: %s\n", |
| 2063 | blob_str(&xfer.aToken[1])); |
| 2064 | } |
| 2065 | }else |
| 2066 | |
| 2067 | /* gimme UUID |
| 2068 | ** |
| 2069 | ** Server is requesting a file. If the file is a manifest, assume |
| 2070 | ** that the server will also want to know all of the content files |
| 2071 | ** associated with the manifest and send those too. |
| 2072 | */ |
| 2073 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 2074 | && xfer.nToken==2 |
| 2075 | && blob_is_uuid(&xfer.aToken[1]) |
| 2076 | ){ |
| 2077 | if( syncFlags & SYNC_PUSH ){ |
| 2078 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2079 | if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); |
| 2080 | } |
| 2081 | }else |
| 2082 | |
| 2083 | /* igot UUID ?PRIVATEFLAG? |
| 2084 | ** |
| 2085 | ** Server announces that it has a particular file. If this is |
| 2086 | ** not a file that we have and we are pulling, then create a |
| 2087 | ** phantom to cause this file to be requested on the next cycle. |
| 2088 | ** Always remember that the server has this file so that we do |
| @@ -2092,11 +2122,11 @@ | |
| 2092 | ** private. Pretend it does not exists if we are not pulling |
| 2093 | ** private files. |
| 2094 | */ |
| 2095 | if( xfer.nToken>=2 |
| 2096 | && blob_eq(&xfer.aToken[0], "igot") |
| 2097 | && blob_is_uuid(&xfer.aToken[1]) |
| 2098 | ){ |
| 2099 | int rid; |
| 2100 | int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1"); |
| 2101 | rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2102 | if( rid>0 ){ |
| @@ -2126,11 +2156,11 @@ | |
| 2126 | if( xfer.nToken==5 |
| 2127 | && blob_eq(&xfer.aToken[0], "uvigot") |
| 2128 | && blob_is_filename(&xfer.aToken[1]) |
| 2129 | && blob_is_int64(&xfer.aToken[2], &mtime) |
| 2130 | && blob_is_int(&xfer.aToken[4], &size) |
| 2131 | && (blob_eq(&xfer.aToken[3],"-") || blob_is_uuid(&xfer.aToken[3])) |
| 2132 | ){ |
| 2133 | const char *zName = blob_str(&xfer.aToken[1]); |
| 2134 | const char *zHash = blob_str(&xfer.aToken[3]); |
| 2135 | int iStatus; |
| 2136 | iStatus = unversioned_status(zName, mtime, zHash); |
| @@ -2188,11 +2218,11 @@ | |
| 2188 | ** the client what product to use for the new database. |
| 2189 | */ |
| 2190 | if( blob_eq(&xfer.aToken[0],"push") |
| 2191 | && xfer.nToken==3 |
| 2192 | && (syncFlags & SYNC_CLONE)!=0 |
| 2193 | && blob_is_uuid(&xfer.aToken[2]) |
| 2194 | ){ |
| 2195 | if( zPCode==0 ){ |
| 2196 | zPCode = mprintf("%b", &xfer.aToken[2]); |
| 2197 | db_set("project-code", zPCode, 0); |
| 2198 | } |
| 2199 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -49,16 +49,17 @@ | |
| 49 | int nDanglingFile; /* Number of dangling deltas received */ |
| 50 | int mxSend; /* Stop sending "file" when pOut reaches this size */ |
| 51 | int resync; /* Send igot cards for all holdings */ |
| 52 | u8 syncPrivate; /* True to enable syncing private content */ |
| 53 | u8 nextIsPrivate; /* If true, next "file" received is a private */ |
| 54 | u32 clientVersion; /* Version of the client software */ |
| 55 | time_t maxTime; /* Time when this transfer should be finished */ |
| 56 | }; |
| 57 | |
| 58 | |
| 59 | /* |
| 60 | ** The input blob contains an artifact. Convert it into a record ID. |
| 61 | ** Create a phantom record if no prior record exists and |
| 62 | ** phantomize is true. |
| 63 | ** |
| 64 | ** Compare to uuid_to_rid(). This routine takes a blob argument |
| 65 | ** and does less error checking. |
| @@ -100,12 +101,12 @@ | |
| 101 | ** message. This routine finishes parsing that message and does |
| 102 | ** a record insert of the file. |
| 103 | ** |
| 104 | ** The file line is in one of the following two forms: |
| 105 | ** |
| 106 | ** file HASH SIZE \n CONTENT |
| 107 | ** file HASH DELTASRC SIZE \n CONTENT |
| 108 | ** |
| 109 | ** The content is SIZE bytes immediately following the newline. |
| 110 | ** If DELTASRC exists, then the CONTENT is a delta against the |
| 111 | ** content of DELTASRC. |
| 112 | ** |
| @@ -122,29 +123,30 @@ | |
| 123 | int *pnUuidList |
| 124 | ){ |
| 125 | int n; |
| 126 | int rid; |
| 127 | int srcid = 0; |
| 128 | Blob content; |
| 129 | int isPriv; |
| 130 | Blob *pUuid; |
| 131 | |
| 132 | isPriv = pXfer->nextIsPrivate; |
| 133 | pXfer->nextIsPrivate = 0; |
| 134 | if( pXfer->nToken<3 |
| 135 | || pXfer->nToken>4 |
| 136 | || !blob_is_hname(&pXfer->aToken[1]) |
| 137 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n) |
| 138 | || n<0 |
| 139 | || (pXfer->nToken==4 && !blob_is_hname(&pXfer->aToken[2])) |
| 140 | ){ |
| 141 | blob_appendf(&pXfer->err, "malformed file line"); |
| 142 | return; |
| 143 | } |
| 144 | blob_zero(&content); |
| 145 | blob_extract(pXfer->pIn, n, &content); |
| 146 | pUuid = &pXfer->aToken[1]; |
| 147 | if( !cloneFlag && uuid_is_shunned(blob_str(pUuid)) ){ |
| 148 | /* Ignore files that have been shunned */ |
| 149 | blob_reset(&content); |
| 150 | return; |
| 151 | } |
| 152 | if( isPriv && !g.perm.Private ){ |
| @@ -158,26 +160,26 @@ | |
| 160 | pXfer->nDeltaRcvd++; |
| 161 | }else{ |
| 162 | srcid = 0; |
| 163 | pXfer->nFileRcvd++; |
| 164 | } |
| 165 | rid = content_put_ex(&content, blob_str(pUuid), srcid, |
| 166 | 0, isPriv); |
| 167 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), |
| 168 | blob_size(pUuid)); |
| 169 | remote_has(rid); |
| 170 | blob_reset(&content); |
| 171 | return; |
| 172 | } |
| 173 | if( pXfer->nToken==4 ){ |
| 174 | Blob src, next; |
| 175 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| 176 | if( content_get(srcid, &src)==0 ){ |
| 177 | rid = content_put_ex(&content, blob_str(pUuid), srcid, |
| 178 | 0, isPriv); |
| 179 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), |
| 180 | blob_size(pUuid)); |
| 181 | pXfer->nDanglingFile++; |
| 182 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 183 | if( !isPriv ) content_make_public(rid); |
| 184 | blob_reset(&src); |
| 185 | blob_reset(&content); |
| @@ -189,19 +191,15 @@ | |
| 191 | blob_reset(&content); |
| 192 | content = next; |
| 193 | }else{ |
| 194 | pXfer->nFileRcvd++; |
| 195 | } |
| 196 | if( hname_verify_hash(&content, blob_buffer(pUuid), blob_size(pUuid))==0 ){ |
| 197 | blob_appendf(&pXfer->err, "wrong hash on received artifact: %b", pUuid); |
| 198 | } |
| 199 | rid = content_put_ex(&content, blob_str(pUuid), 0, 0, isPriv); |
| 200 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), blob_size(pUuid)); |
| 201 | if( rid==0 ){ |
| 202 | blob_appendf(&pXfer->err, "%s", g.zErrMsg); |
| 203 | blob_reset(&content); |
| 204 | }else{ |
| 205 | if( !isPriv ) content_make_public(rid); |
| @@ -217,18 +215,18 @@ | |
| 215 | ** a record insert of the file. The difference between "file" and |
| 216 | ** "cfile" is that with "cfile" the content is already compressed. |
| 217 | ** |
| 218 | ** The file line is in one of the following two forms: |
| 219 | ** |
| 220 | ** cfile HASH USIZE CSIZE \n CONTENT |
| 221 | ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT |
| 222 | ** |
| 223 | ** The content is CSIZE bytes immediately following the newline. |
| 224 | ** If DELTASRC exists, then the CONTENT is a delta against the |
| 225 | ** content of DELTASRC. |
| 226 | ** |
| 227 | ** The original size of the HASH artifact is USIZE. |
| 228 | ** |
| 229 | ** If any error occurs, write a message into pErr which has already |
| 230 | ** be initialized to an empty string. |
| 231 | ** |
| 232 | ** Any artifact successfully received by this routine is considered to |
| @@ -248,15 +246,15 @@ | |
| 246 | |
| 247 | isPriv = pXfer->nextIsPrivate; |
| 248 | pXfer->nextIsPrivate = 0; |
| 249 | if( pXfer->nToken<4 |
| 250 | || pXfer->nToken>5 |
| 251 | || !blob_is_hname(&pXfer->aToken[1]) |
| 252 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU) |
| 253 | || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC) |
| 254 | || szC<0 || szU<0 |
| 255 | || (pXfer->nToken==5 && !blob_is_hname(&pXfer->aToken[2])) |
| 256 | ){ |
| 257 | blob_appendf(&pXfer->err, "malformed cfile line"); |
| 258 | return; |
| 259 | } |
| 260 | if( isPriv && !g.perm.Private ){ |
| @@ -297,11 +295,11 @@ | |
| 295 | ** |
| 296 | ** If the 0x0001 bit of FLAGS is set, that means the file has been |
| 297 | ** deleted, SIZE is zero, the HASH is "-", and the "\n CONTENT" is omitted. |
| 298 | ** |
| 299 | ** SIZE is the number of bytes of CONTENT. The CONTENT is uncompressed. |
| 300 | ** HASH is the artifact hash of CONTENT. |
| 301 | ** |
| 302 | ** If the 0x0004 bit of FLAGS is set, that means the CONTENT is omitted. |
| 303 | ** The sender might have omitted the content because it is too big to |
| 304 | ** transmit, or because it is unchanged and this record exists purely |
| 305 | ** to update the MTIME. |
| @@ -310,11 +308,10 @@ | |
| 308 | sqlite3_int64 mtime; /* The MTIME */ |
| 309 | Blob *pHash; /* The HASH value */ |
| 310 | int sz; /* The SIZE */ |
| 311 | int flags; /* The FLAGS */ |
| 312 | Blob content; /* The CONTENT */ |
| 313 | Blob x; /* Compressed content */ |
| 314 | Stmt q; /* SQL statements for comparison and insert */ |
| 315 | int isDelete; /* HASH is "-" indicating this is a delete */ |
| 316 | int nullContent; /* True of CONTENT is NULL */ |
| 317 | int iStatus; /* Result from unversioned_status() */ |
| @@ -321,25 +318,23 @@ | |
| 318 | |
| 319 | pHash = &pXfer->aToken[3]; |
| 320 | if( pXfer->nToken==5 |
| 321 | || !blob_is_filename(&pXfer->aToken[1]) |
| 322 | || !blob_is_int64(&pXfer->aToken[2], &mtime) |
| 323 | || (!blob_eq(pHash,"-") && !blob_is_hname(pHash)) |
| 324 | || !blob_is_int(&pXfer->aToken[4], &sz) |
| 325 | || !blob_is_int(&pXfer->aToken[5], &flags) |
| 326 | ){ |
| 327 | blob_appendf(&pXfer->err, "malformed uvfile line"); |
| 328 | return; |
| 329 | } |
| 330 | blob_init(&content, 0, 0); |
| 331 | blob_init(&x, 0, 0); |
| 332 | if( sz>0 && (flags & 0x0005)==0 ){ |
| 333 | blob_extract(pXfer->pIn, sz, &content); |
| 334 | nullContent = 0; |
| 335 | if( hname_verify_hash(&content, blob_buffer(pHash), blob_size(pHash))==0 ){ |
| 336 | blob_appendf(&pXfer->err, "in uvfile line, HASH does not match CONTENT"); |
| 337 | goto end_accept_unversioned_file; |
| 338 | } |
| 339 | }else{ |
| 340 | nullContent = 1; |
| @@ -399,11 +394,10 @@ | |
| 394 | db_unset("uv-hash", 0); |
| 395 | |
| 396 | end_accept_unversioned_file: |
| 397 | blob_reset(&x); |
| 398 | blob_reset(&content); |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | ** Try to send a file as a delta against its parent. |
| 403 | ** If successful, return the number of bytes in the delta. |
| @@ -415,11 +409,11 @@ | |
| 409 | static int send_delta_parent( |
| 410 | Xfer *pXfer, /* The transfer context */ |
| 411 | int rid, /* record id of the file to send */ |
| 412 | int isPrivate, /* True if rid is a private artifact */ |
| 413 | Blob *pContent, /* The content of the file to send */ |
| 414 | Blob *pUuid /* The HASH of the file to send */ |
| 415 | ){ |
| 416 | static const char *const azQuery[] = { |
| 417 | "SELECT pid FROM plink x" |
| 418 | " WHERE cid=%d" |
| 419 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)", |
| @@ -469,11 +463,11 @@ | |
| 463 | */ |
| 464 | static int send_delta_native( |
| 465 | Xfer *pXfer, /* The transfer context */ |
| 466 | int rid, /* record id of the file to send */ |
| 467 | int isPrivate, /* True if rid is a private artifact */ |
| 468 | Blob *pUuid /* The HASH of the file to send */ |
| 469 | ){ |
| 470 | Blob src, delta; |
| 471 | int size = 0; |
| 472 | int srcId; |
| 473 | |
| @@ -500,15 +494,26 @@ | |
| 494 | }else{ |
| 495 | size = 0; |
| 496 | } |
| 497 | return size; |
| 498 | } |
| 499 | |
| 500 | /* |
| 501 | ** Push an error message to alert the older client that the repository |
| 502 | ** has SHA3 content and cannot be synced or cloned. |
| 503 | */ |
| 504 | static void xfer_cannot_send_sha3_error(Xfer *pXfer){ |
| 505 | blob_appendf(pXfer->pOut, |
| 506 | "error Fossil\\sversion\\s2.0\\sor\\slater\\srequired.\n" |
| 507 | ); |
| 508 | } |
| 509 | |
| 510 | |
| 511 | /* |
| 512 | ** Send the file identified by rid. |
| 513 | ** |
| 514 | ** The pUuid can be NULL in which case the correct hash is computed |
| 515 | ** from the rid. |
| 516 | ** |
| 517 | ** Try to send the file as a native delta if nativeDelta is true, or |
| 518 | ** as a parent delta if nativeDelta is false. |
| 519 | ** |
| @@ -527,10 +532,14 @@ | |
| 532 | } |
| 533 | blob_zero(&uuid); |
| 534 | db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid); |
| 535 | if( blob_size(&uuid)==0 ){ |
| 536 | return; |
| 537 | } |
| 538 | if( blob_size(&uuid)>HNAME_LEN_SHA1 && pXfer->clientVersion<20000 ){ |
| 539 | xfer_cannot_send_sha3_error(pXfer); |
| 540 | return; |
| 541 | } |
| 542 | if( pUuid ){ |
| 543 | if( blob_compare(pUuid, &uuid)!=0 ){ |
| 544 | blob_reset(&uuid); |
| 545 | return; |
| @@ -617,10 +626,15 @@ | |
| 626 | szC = db_column_bytes(&q1, 2); |
| 627 | zContent = db_column_raw(&q1, 2); |
| 628 | srcIsPrivate = db_column_int(&q1, 3); |
| 629 | zDelta = db_column_text(&q1, 4); |
| 630 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 631 | if( pXfer->clientVersion<20000 && db_column_bytes(&q1,0)!=HNAME_LEN_SHA1 ){ |
| 632 | xfer_cannot_send_sha3_error(pXfer); |
| 633 | db_reset(&q1); |
| 634 | return; |
| 635 | } |
| 636 | blob_appendf(pXfer->pOut, "cfile %s ", zUuid); |
| 637 | if( !isPrivate && srcIsPrivate ){ |
| 638 | content_get(rid, &fullContent); |
| 639 | szU = blob_size(&fullContent); |
| 640 | blob_compress(&fullContent, &fullContent); |
| @@ -676,10 +690,15 @@ | |
| 690 | ); |
| 691 | } |
| 692 | if( db_step(&q1)==SQLITE_ROW ){ |
| 693 | sqlite3_int64 mtime = db_column_int64(&q1, 0); |
| 694 | const char *zHash = db_column_text(&q1, 1); |
| 695 | if( pXfer->clientVersion<20000 && db_column_bytes(&q1,1)>HNAME_LEN_SHA1 ){ |
| 696 | xfer_cannot_send_sha3_error(pXfer); |
| 697 | db_reset(&q1); |
| 698 | return; |
| 699 | } |
| 700 | if( blob_size(pXfer->pOut)>=pXfer->mxSend ){ |
| 701 | /* If we have already reached the send size limit, send a (short) |
| 702 | ** uvigot card rather than a uvfile card. This only happens on the |
| 703 | ** server side. The uvigot card will provoke the client to resend |
| 704 | ** another uvgimme on the next cycle. */ |
| @@ -728,23 +747,23 @@ | |
| 747 | } |
| 748 | db_finalize(&q); |
| 749 | } |
| 750 | |
| 751 | /* |
| 752 | ** Compute an hash on the tail of pMsg. Verify that it matches the |
| 753 | ** the hash given in pHash. Return non-zero for an error and 0 on success. |
| 754 | ** |
| 755 | ** The type of hash computed (SHA1, SHA3-256) is determined by |
| 756 | ** the length of the input hash in pHash. |
| 757 | */ |
| 758 | static int check_tail_hash(Blob *pHash, Blob *pMsg){ |
| 759 | Blob tail; |
| 760 | int rc; |
| 761 | blob_tail(pMsg, &tail); |
| 762 | rc = hname_verify_hash(&tail, blob_buffer(pHash), blob_size(pHash)); |
| 763 | blob_reset(&tail); |
| 764 | return rc==HNAME_ERROR; |
| 765 | } |
| 766 | |
| 767 | /* |
| 768 | ** Check the signature on an application/x-fossil payload received by |
| 769 | ** the HTTP server. The signature is a line of the following form: |
| @@ -1198,12 +1217,12 @@ | |
| 1217 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 1218 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 1219 | if( blob_size(&xfer.line)==0 ) continue; |
| 1220 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 1221 | |
| 1222 | /* file HASH SIZE \n CONTENT |
| 1223 | ** file HASH DELTASRC SIZE \n CONTENT |
| 1224 | ** |
| 1225 | ** Accept a file from the client. |
| 1226 | */ |
| 1227 | if( blob_eq(&xfer.aToken[0], "file") ){ |
| 1228 | if( !isPush ){ |
| @@ -1219,12 +1238,12 @@ | |
| 1238 | nErr++; |
| 1239 | break; |
| 1240 | } |
| 1241 | }else |
| 1242 | |
| 1243 | /* cfile HASH USIZE CSIZE \n CONTENT |
| 1244 | ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT |
| 1245 | ** |
| 1246 | ** Accept a file from the client. |
| 1247 | */ |
| 1248 | if( blob_eq(&xfer.aToken[0], "cfile") ){ |
| 1249 | if( !isPush ){ |
| @@ -1254,17 +1273,17 @@ | |
| 1273 | nErr++; |
| 1274 | break; |
| 1275 | } |
| 1276 | }else |
| 1277 | |
| 1278 | /* gimme HASH |
| 1279 | ** |
| 1280 | ** Client is requesting a file. Send it. |
| 1281 | */ |
| 1282 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 1283 | && xfer.nToken==2 |
| 1284 | && blob_is_hname(&xfer.aToken[1]) |
| 1285 | ){ |
| 1286 | nGimme++; |
| 1287 | if( isPull ){ |
| 1288 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1289 | if( rid ){ |
| @@ -1282,18 +1301,18 @@ | |
| 1301 | && blob_is_filename(&xfer.aToken[1]) |
| 1302 | ){ |
| 1303 | send_unversioned_file(&xfer, blob_str(&xfer.aToken[1]), 0); |
| 1304 | }else |
| 1305 | |
| 1306 | /* igot HASH ?ISPRIVATE? |
| 1307 | ** |
| 1308 | ** Client announces that it has a particular file. If the ISPRIVATE |
| 1309 | ** argument exists and is non-zero, then the file is a private file. |
| 1310 | */ |
| 1311 | if( xfer.nToken>=2 |
| 1312 | && blob_eq(&xfer.aToken[0], "igot") |
| 1313 | && blob_is_hname(&xfer.aToken[1]) |
| 1314 | ){ |
| 1315 | if( isPush ){ |
| 1316 | if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){ |
| 1317 | rid_from_uuid(&xfer.aToken[1], 1, 0); |
| 1318 | }else if( g.perm.Private ){ |
| @@ -1307,16 +1326,15 @@ | |
| 1326 | |
| 1327 | /* pull SERVERCODE PROJECTCODE |
| 1328 | ** push SERVERCODE PROJECTCODE |
| 1329 | ** |
| 1330 | ** The client wants either send or receive. The server should |
| 1331 | ** verify that the project code matches. The server code is ignored. |
| 1332 | */ |
| 1333 | if( xfer.nToken==3 |
| 1334 | && (blob_eq(&xfer.aToken[0], "pull") || blob_eq(&xfer.aToken[0], "push")) |
| 1335 | && blob_is_hname(&xfer.aToken[2]) |
| 1336 | ){ |
| 1337 | const char *zPCode; |
| 1338 | zPCode = db_get("project-code", 0); |
| 1339 | if( zPCode==0 ){ |
| 1340 | fossil_panic("missing project code"); |
| @@ -1534,19 +1552,27 @@ | |
| 1552 | ** Send igot cards for all known artifacts. |
| 1553 | */ |
| 1554 | if( blob_eq(&xfer.aToken[1], "send-catalog") ){ |
| 1555 | xfer.resync = 0x7fffffff; |
| 1556 | } |
| 1557 | |
| 1558 | /* pragma client-version VERSION |
| 1559 | ** |
| 1560 | ** Let the server know what version of Fossil is running on the client. |
| 1561 | */ |
| 1562 | if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){ |
| 1563 | xfer.clientVersion = atoi(blob_str(&xfer.aToken[2])); |
| 1564 | } |
| 1565 | |
| 1566 | /* pragma uv-hash HASH |
| 1567 | ** |
| 1568 | ** The client wants to make sure that unversioned files are all synced. |
| 1569 | ** If the HASH does not match, send a complete catalog of |
| 1570 | ** "uvigot" cards. |
| 1571 | */ |
| 1572 | if( blob_eq(&xfer.aToken[1], "uv-hash") |
| 1573 | && blob_is_hname(&xfer.aToken[2]) |
| 1574 | ){ |
| 1575 | if( !uvCatalogSent ){ |
| 1576 | if( g.perm.Read && g.perm.WrUnver ){ |
| 1577 | @ pragma uv-push-ok |
| 1578 | send_unversioned_catalog(&xfer); |
| @@ -1742,10 +1768,11 @@ | |
| 1768 | memset(&xfer, 0, sizeof(xfer)); |
| 1769 | xfer.pIn = &recv; |
| 1770 | xfer.pOut = &send; |
| 1771 | xfer.mxSend = db_get_int("max-upload", 250000); |
| 1772 | xfer.maxTime = -1; |
| 1773 | xfer.clientVersion = RELEASE_VERSION_NUMBER; |
| 1774 | if( syncFlags & SYNC_PRIVATE ){ |
| 1775 | g.perm.Private = 1; |
| 1776 | xfer.syncPrivate = 1; |
| 1777 | } |
| 1778 | |
| @@ -1783,10 +1810,11 @@ | |
| 1810 | } |
| 1811 | |
| 1812 | /* |
| 1813 | ** Always begin with a clone, pull, or push message |
| 1814 | */ |
| 1815 | blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER); |
| 1816 | if( syncFlags & SYNC_CLONE ){ |
| 1817 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 1818 | syncFlags &= ~(SYNC_PUSH|SYNC_PULL); |
| 1819 | nCardSent++; |
| 1820 | /* TBD: Request all transferable configuration values */ |
| @@ -1819,10 +1847,11 @@ | |
| 1847 | db_record_repository_filename(0); |
| 1848 | db_multi_exec( |
| 1849 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1850 | ); |
| 1851 | manifest_crosslink_begin(); |
| 1852 | |
| 1853 | |
| 1854 | /* Send back the most recently received cookie. Let the server |
| 1855 | ** figure out if this is a cookie that it cares about. |
| 1856 | */ |
| 1857 | zCookie = db_get("cookie", 0); |
| @@ -1976,10 +2005,11 @@ | |
| 2005 | xfer.nGimmeSent = 0; |
| 2006 | xfer.nIGotSent = 0; |
| 2007 | |
| 2008 | lastPctDone = -1; |
| 2009 | blob_reset(&send); |
| 2010 | blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER); |
| 2011 | rArrivalTime = db_double(0.0, "SELECT julianday('now')"); |
| 2012 | |
| 2013 | /* Send the send-private pragma if we are trying to sync private data */ |
| 2014 | if( syncFlags & SYNC_PRIVATE ){ |
| 2015 | blob_append(&send, "pragma send-private\n", -1); |
| @@ -2028,22 +2058,22 @@ | |
| 2058 | lastPctDone = pctDone; |
| 2059 | fflush(stdout); |
| 2060 | } |
| 2061 | } |
| 2062 | |
| 2063 | /* file HASH SIZE \n CONTENT |
| 2064 | ** file HASH DELTASRC SIZE \n CONTENT |
| 2065 | ** |
| 2066 | ** Receive a file transmitted from the server. |
| 2067 | */ |
| 2068 | if( blob_eq(&xfer.aToken[0],"file") ){ |
| 2069 | xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0); |
| 2070 | nArtifactRcvd++; |
| 2071 | }else |
| 2072 | |
| 2073 | /* cfile HASH USIZE CSIZE \n CONTENT |
| 2074 | ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT |
| 2075 | ** |
| 2076 | ** Receive a compressed file transmitted from the server. |
| 2077 | */ |
| 2078 | if( blob_eq(&xfer.aToken[0],"cfile") ){ |
| 2079 | xfer_accept_compressed_file(&xfer, 0, 0); |
| @@ -2062,27 +2092,27 @@ | |
| 2092 | fossil_print("\rUnversioned-file received: %s\n", |
| 2093 | blob_str(&xfer.aToken[1])); |
| 2094 | } |
| 2095 | }else |
| 2096 | |
| 2097 | /* gimme HASH |
| 2098 | ** |
| 2099 | ** Server is requesting a file. If the file is a manifest, assume |
| 2100 | ** that the server will also want to know all of the content files |
| 2101 | ** associated with the manifest and send those too. |
| 2102 | */ |
| 2103 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 2104 | && xfer.nToken==2 |
| 2105 | && blob_is_hname(&xfer.aToken[1]) |
| 2106 | ){ |
| 2107 | if( syncFlags & SYNC_PUSH ){ |
| 2108 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2109 | if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); |
| 2110 | } |
| 2111 | }else |
| 2112 | |
| 2113 | /* igot HASH ?PRIVATEFLAG? |
| 2114 | ** |
| 2115 | ** Server announces that it has a particular file. If this is |
| 2116 | ** not a file that we have and we are pulling, then create a |
| 2117 | ** phantom to cause this file to be requested on the next cycle. |
| 2118 | ** Always remember that the server has this file so that we do |
| @@ -2092,11 +2122,11 @@ | |
| 2122 | ** private. Pretend it does not exists if we are not pulling |
| 2123 | ** private files. |
| 2124 | */ |
| 2125 | if( xfer.nToken>=2 |
| 2126 | && blob_eq(&xfer.aToken[0], "igot") |
| 2127 | && blob_is_hname(&xfer.aToken[1]) |
| 2128 | ){ |
| 2129 | int rid; |
| 2130 | int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1"); |
| 2131 | rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2132 | if( rid>0 ){ |
| @@ -2126,11 +2156,11 @@ | |
| 2156 | if( xfer.nToken==5 |
| 2157 | && blob_eq(&xfer.aToken[0], "uvigot") |
| 2158 | && blob_is_filename(&xfer.aToken[1]) |
| 2159 | && blob_is_int64(&xfer.aToken[2], &mtime) |
| 2160 | && blob_is_int(&xfer.aToken[4], &size) |
| 2161 | && (blob_eq(&xfer.aToken[3],"-") || blob_is_hname(&xfer.aToken[3])) |
| 2162 | ){ |
| 2163 | const char *zName = blob_str(&xfer.aToken[1]); |
| 2164 | const char *zHash = blob_str(&xfer.aToken[3]); |
| 2165 | int iStatus; |
| 2166 | iStatus = unversioned_status(zName, mtime, zHash); |
| @@ -2188,11 +2218,11 @@ | |
| 2218 | ** the client what product to use for the new database. |
| 2219 | */ |
| 2220 | if( blob_eq(&xfer.aToken[0],"push") |
| 2221 | && xfer.nToken==3 |
| 2222 | && (syncFlags & SYNC_CLONE)!=0 |
| 2223 | && blob_is_hname(&xfer.aToken[2]) |
| 2224 | ){ |
| 2225 | if( zPCode==0 ){ |
| 2226 | zPCode = mprintf("%b", &xfer.aToken[2]); |
| 2227 | db_set("project-code", zPCode, 0); |
| 2228 | } |
| 2229 |
+2
-5
| --- src/zip.c | ||
| +++ src/zip.c | ||
| @@ -339,11 +339,11 @@ | ||
| 339 | 339 | content_get(rid, &mfile); |
| 340 | 340 | if( blob_size(&mfile)==0 ){ |
| 341 | 341 | blob_zero(pZip); |
| 342 | 342 | return; |
| 343 | 343 | } |
| 344 | - blob_zero(&hash); | |
| 344 | + blob_set_dynamic(&hash, rid_to_uuid(rid)); | |
| 345 | 345 | blob_zero(&filename); |
| 346 | 346 | zip_open(); |
| 347 | 347 | |
| 348 | 348 | if( zDir && zDir[0] ){ |
| 349 | 349 | blob_appendf(&filename, "%s/", zDir); |
| @@ -378,13 +378,10 @@ | ||
| 378 | 378 | if( eflg & MFESTFLG_RAW ){ |
| 379 | 379 | blob_append(&filename, "manifest", -1); |
| 380 | 380 | zName = blob_str(&filename); |
| 381 | 381 | zip_add_folders(zName); |
| 382 | 382 | } |
| 383 | - if( eflg & MFESTFLG_UUID ){ | |
| 384 | - sha1sum_blob(&mfile, &hash); | |
| 385 | - } | |
| 386 | 383 | if( eflg & MFESTFLG_RAW ){ |
| 387 | 384 | sterilize_manifest(&mfile); |
| 388 | 385 | zip_add_file(zName, &mfile, 0); |
| 389 | 386 | } |
| 390 | 387 | } |
| @@ -394,11 +391,10 @@ | ||
| 394 | 391 | blob_resize(&filename, nPrefix); |
| 395 | 392 | blob_append(&filename, "manifest.uuid", -1); |
| 396 | 393 | zName = blob_str(&filename); |
| 397 | 394 | zip_add_folders(zName); |
| 398 | 395 | zip_add_file(zName, &hash, 0); |
| 399 | - blob_reset(&hash); | |
| 400 | 396 | } |
| 401 | 397 | if( eflg & MFESTFLG_TAGS ){ |
| 402 | 398 | Blob tagslist; |
| 403 | 399 | blob_zero(&tagslist); |
| 404 | 400 | get_checkin_taglist(rid, &tagslist); |
| @@ -429,10 +425,11 @@ | ||
| 429 | 425 | }else{ |
| 430 | 426 | blob_reset(&mfile); |
| 431 | 427 | } |
| 432 | 428 | manifest_destroy(pManifest); |
| 433 | 429 | blob_reset(&filename); |
| 430 | + blob_reset(&hash); | |
| 434 | 431 | zip_close(pZip); |
| 435 | 432 | } |
| 436 | 433 | |
| 437 | 434 | /* |
| 438 | 435 | ** COMMAND: zip* |
| 439 | 436 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -339,11 +339,11 @@ | |
| 339 | content_get(rid, &mfile); |
| 340 | if( blob_size(&mfile)==0 ){ |
| 341 | blob_zero(pZip); |
| 342 | return; |
| 343 | } |
| 344 | blob_zero(&hash); |
| 345 | blob_zero(&filename); |
| 346 | zip_open(); |
| 347 | |
| 348 | if( zDir && zDir[0] ){ |
| 349 | blob_appendf(&filename, "%s/", zDir); |
| @@ -378,13 +378,10 @@ | |
| 378 | if( eflg & MFESTFLG_RAW ){ |
| 379 | blob_append(&filename, "manifest", -1); |
| 380 | zName = blob_str(&filename); |
| 381 | zip_add_folders(zName); |
| 382 | } |
| 383 | if( eflg & MFESTFLG_UUID ){ |
| 384 | sha1sum_blob(&mfile, &hash); |
| 385 | } |
| 386 | if( eflg & MFESTFLG_RAW ){ |
| 387 | sterilize_manifest(&mfile); |
| 388 | zip_add_file(zName, &mfile, 0); |
| 389 | } |
| 390 | } |
| @@ -394,11 +391,10 @@ | |
| 394 | blob_resize(&filename, nPrefix); |
| 395 | blob_append(&filename, "manifest.uuid", -1); |
| 396 | zName = blob_str(&filename); |
| 397 | zip_add_folders(zName); |
| 398 | zip_add_file(zName, &hash, 0); |
| 399 | blob_reset(&hash); |
| 400 | } |
| 401 | if( eflg & MFESTFLG_TAGS ){ |
| 402 | Blob tagslist; |
| 403 | blob_zero(&tagslist); |
| 404 | get_checkin_taglist(rid, &tagslist); |
| @@ -429,10 +425,11 @@ | |
| 429 | }else{ |
| 430 | blob_reset(&mfile); |
| 431 | } |
| 432 | manifest_destroy(pManifest); |
| 433 | blob_reset(&filename); |
| 434 | zip_close(pZip); |
| 435 | } |
| 436 | |
| 437 | /* |
| 438 | ** COMMAND: zip* |
| 439 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -339,11 +339,11 @@ | |
| 339 | content_get(rid, &mfile); |
| 340 | if( blob_size(&mfile)==0 ){ |
| 341 | blob_zero(pZip); |
| 342 | return; |
| 343 | } |
| 344 | blob_set_dynamic(&hash, rid_to_uuid(rid)); |
| 345 | blob_zero(&filename); |
| 346 | zip_open(); |
| 347 | |
| 348 | if( zDir && zDir[0] ){ |
| 349 | blob_appendf(&filename, "%s/", zDir); |
| @@ -378,13 +378,10 @@ | |
| 378 | if( eflg & MFESTFLG_RAW ){ |
| 379 | blob_append(&filename, "manifest", -1); |
| 380 | zName = blob_str(&filename); |
| 381 | zip_add_folders(zName); |
| 382 | } |
| 383 | if( eflg & MFESTFLG_RAW ){ |
| 384 | sterilize_manifest(&mfile); |
| 385 | zip_add_file(zName, &mfile, 0); |
| 386 | } |
| 387 | } |
| @@ -394,11 +391,10 @@ | |
| 391 | blob_resize(&filename, nPrefix); |
| 392 | blob_append(&filename, "manifest.uuid", -1); |
| 393 | zName = blob_str(&filename); |
| 394 | zip_add_folders(zName); |
| 395 | zip_add_file(zName, &hash, 0); |
| 396 | } |
| 397 | if( eflg & MFESTFLG_TAGS ){ |
| 398 | Blob tagslist; |
| 399 | blob_zero(&tagslist); |
| 400 | get_checkin_taglist(rid, &tagslist); |
| @@ -429,10 +425,11 @@ | |
| 425 | }else{ |
| 426 | blob_reset(&mfile); |
| 427 | } |
| 428 | manifest_destroy(pManifest); |
| 429 | blob_reset(&filename); |
| 430 | blob_reset(&hash); |
| 431 | zip_close(pZip); |
| 432 | } |
| 433 | |
| 434 | /* |
| 435 | ** COMMAND: zip* |
| 436 |
+4
-4
| --- test/json.test | ||
| +++ test/json.test | ||
| @@ -749,14 +749,14 @@ | ||
| 749 | 749 | |
| 750 | 750 | |
| 751 | 751 | # FOSSIL-1103 FSL_JSON_E_UNKNOWN |
| 752 | 752 | # Unknown error |
| 753 | 753 | |
| 754 | -write_file bad.sql { | |
| 755 | -CREATE TABLE spam(a integer, b text); | |
| 756 | -} | |
| 757 | -exec $::fossilexe sqlite3 --no-repository bad.fossil <bad.sql | |
| 754 | +#write_file bad.sql { | |
| 755 | +#CREATE TABLE spam(a integer, b text); | |
| 756 | +#} | |
| 757 | +#exec $::fossilexe sqlite3 --no-repository bad.fossil <bad.sql | |
| 758 | 758 | #fossil_json HAI -R bad.fossil -expectError |
| 759 | 759 | |
| 760 | 760 | # FOSSIL-1104 FSL_JSON_E_TIMEOUT |
| 761 | 761 | # Timeout reached |
| 762 | 762 | # FOSSIL-1105 FSL_JSON_E_ASSERT |
| 763 | 763 |
| --- test/json.test | |
| +++ test/json.test | |
| @@ -749,14 +749,14 @@ | |
| 749 | |
| 750 | |
| 751 | # FOSSIL-1103 FSL_JSON_E_UNKNOWN |
| 752 | # Unknown error |
| 753 | |
| 754 | write_file bad.sql { |
| 755 | CREATE TABLE spam(a integer, b text); |
| 756 | } |
| 757 | exec $::fossilexe sqlite3 --no-repository bad.fossil <bad.sql |
| 758 | #fossil_json HAI -R bad.fossil -expectError |
| 759 | |
| 760 | # FOSSIL-1104 FSL_JSON_E_TIMEOUT |
| 761 | # Timeout reached |
| 762 | # FOSSIL-1105 FSL_JSON_E_ASSERT |
| 763 |
| --- test/json.test | |
| +++ test/json.test | |
| @@ -749,14 +749,14 @@ | |
| 749 | |
| 750 | |
| 751 | # FOSSIL-1103 FSL_JSON_E_UNKNOWN |
| 752 | # Unknown error |
| 753 | |
| 754 | #write_file bad.sql { |
| 755 | #CREATE TABLE spam(a integer, b text); |
| 756 | #} |
| 757 | #exec $::fossilexe sqlite3 --no-repository bad.fossil <bad.sql |
| 758 | #fossil_json HAI -R bad.fossil -expectError |
| 759 | |
| 760 | # FOSSIL-1104 FSL_JSON_E_TIMEOUT |
| 761 | # Timeout reached |
| 762 | # FOSSIL-1105 FSL_JSON_E_ASSERT |
| 763 |
+12
-6
| --- test/wiki.test | ||
| +++ test/wiki.test | ||
| @@ -21,16 +21,22 @@ | ||
| 21 | 21 | test_setup |
| 22 | 22 | |
| 23 | 23 | # Return true if two files are similar (i.e. not only compress trailing spaces |
| 24 | 24 | # from a line, but remove any final LF from the file as well) |
| 25 | 25 | proc similar_file {a b} { |
| 26 | - set x [read_file $a] | |
| 27 | - regsub -all { +\n} $x \n x | |
| 28 | - regsub -all {\n$} $x {} x | |
| 29 | - set y [read_file $b] | |
| 30 | - regsub -all { +\n} $y \n y | |
| 31 | - regsub -all {\n$} $y {} y | |
| 26 | + set x "" | |
| 27 | + if {[file exists $a]} { | |
| 28 | + set x [read_file $a] | |
| 29 | + regsub -all { +\n} $x \n x | |
| 30 | + regsub -all {\n$} $x {} x | |
| 31 | + } | |
| 32 | + set y "" | |
| 33 | + if {[file exists $b]} { | |
| 34 | + set y [read_file $b] | |
| 35 | + regsub -all { +\n} $y \n y | |
| 36 | + regsub -all {\n$} $y {} y | |
| 37 | + } | |
| 32 | 38 | return [expr {$x==$y}] |
| 33 | 39 | } |
| 34 | 40 | |
| 35 | 41 | # Return the mime type in the manifest for a given wiki page |
| 36 | 42 | # Defaults to "error: some text" if the manifest can't be located and |
| 37 | 43 |
| --- test/wiki.test | |
| +++ test/wiki.test | |
| @@ -21,16 +21,22 @@ | |
| 21 | test_setup |
| 22 | |
| 23 | # Return true if two files are similar (i.e. not only compress trailing spaces |
| 24 | # from a line, but remove any final LF from the file as well) |
| 25 | proc similar_file {a b} { |
| 26 | set x [read_file $a] |
| 27 | regsub -all { +\n} $x \n x |
| 28 | regsub -all {\n$} $x {} x |
| 29 | set y [read_file $b] |
| 30 | regsub -all { +\n} $y \n y |
| 31 | regsub -all {\n$} $y {} y |
| 32 | return [expr {$x==$y}] |
| 33 | } |
| 34 | |
| 35 | # Return the mime type in the manifest for a given wiki page |
| 36 | # Defaults to "error: some text" if the manifest can't be located and |
| 37 |
| --- test/wiki.test | |
| +++ test/wiki.test | |
| @@ -21,16 +21,22 @@ | |
| 21 | test_setup |
| 22 | |
| 23 | # Return true if two files are similar (i.e. not only compress trailing spaces |
| 24 | # from a line, but remove any final LF from the file as well) |
| 25 | proc similar_file {a b} { |
| 26 | set x "" |
| 27 | if {[file exists $a]} { |
| 28 | set x [read_file $a] |
| 29 | regsub -all { +\n} $x \n x |
| 30 | regsub -all {\n$} $x {} x |
| 31 | } |
| 32 | set y "" |
| 33 | if {[file exists $b]} { |
| 34 | set y [read_file $b] |
| 35 | regsub -all { +\n} $y \n y |
| 36 | regsub -all {\n$} $y {} y |
| 37 | } |
| 38 | return [expr {$x==$y}] |
| 39 | } |
| 40 | |
| 41 | # Return the mime type in the manifest for a given wiki page |
| 42 | # Defaults to "error: some text" if the manifest can't be located and |
| 43 |
+1
-1
| --- tools/man_page_command_list.tcl | ||
| +++ tools/man_page_command_list.tcl | ||
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | #!/usr/bin/env tclsh |
| 2 | -# command_man_list.tcl - generates common command list for fossil.1 | |
| 2 | +# man_page_command_list.tcl - generates common command list for fossil.1 | |
| 3 | 3 | |
| 4 | 4 | # Tunable configuration. |
| 5 | 5 | set columns 5 |
| 6 | 6 | set width 15 |
| 7 | 7 | |
| 8 | 8 |
| --- tools/man_page_command_list.tcl | |
| +++ tools/man_page_command_list.tcl | |
| @@ -1,7 +1,7 @@ | |
| 1 | #!/usr/bin/env tclsh |
| 2 | # command_man_list.tcl - generates common command list for fossil.1 |
| 3 | |
| 4 | # Tunable configuration. |
| 5 | set columns 5 |
| 6 | set width 15 |
| 7 | |
| 8 |
| --- tools/man_page_command_list.tcl | |
| +++ tools/man_page_command_list.tcl | |
| @@ -1,7 +1,7 @@ | |
| 1 | #!/usr/bin/env tclsh |
| 2 | # man_page_command_list.tcl - generates common command list for fossil.1 |
| 3 | |
| 4 | # Tunable configuration. |
| 5 | set columns 5 |
| 6 | set width 15 |
| 7 | |
| 8 |
+22
-4
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -28,13 +28,13 @@ | ||
| 28 | 28 | |
| 29 | 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 |
| 30 | 30 | |
| 31 | 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | 32 | |
| 33 | -SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 33 | +SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 34 | 34 | |
| 35 | -OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 35 | +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 36 | 36 | |
| 37 | 37 | |
| 38 | 38 | RC=$(DMDIR)\bin\rcc |
| 39 | 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | 40 | |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | |
| 50 | 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | 52 | |
| 53 | 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | - +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 54 | + +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 sha1hard sha3 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 55 | 55 | +echo fossil >> $@ |
| 56 | 56 | +echo fossil >> $@ |
| 57 | 57 | +echo $(LIBS) >> $@ |
| 58 | 58 | +echo. >> $@ |
| 59 | 59 | +echo fossil >> $@ |
| @@ -356,10 +356,16 @@ | ||
| 356 | 356 | $(OBJDIR)\gzip$O : gzip_.c gzip.h |
| 357 | 357 | $(TCC) -o$@ -c gzip_.c |
| 358 | 358 | |
| 359 | 359 | gzip_.c : $(SRCDIR)\gzip.c |
| 360 | 360 | +translate$E $** > $@ |
| 361 | + | |
| 362 | +$(OBJDIR)\hname$O : hname_.c hname.h | |
| 363 | + $(TCC) -o$@ -c hname_.c | |
| 364 | + | |
| 365 | +hname_.c : $(SRCDIR)\hname.c | |
| 366 | + +translate$E $** > $@ | |
| 361 | 367 | |
| 362 | 368 | $(OBJDIR)\http$O : http_.c http.h |
| 363 | 369 | $(TCC) -o$@ -c http_.c |
| 364 | 370 | |
| 365 | 371 | http_.c : $(SRCDIR)\http.c |
| @@ -656,10 +662,22 @@ | ||
| 656 | 662 | $(OBJDIR)\sha1$O : sha1_.c sha1.h |
| 657 | 663 | $(TCC) -o$@ -c sha1_.c |
| 658 | 664 | |
| 659 | 665 | sha1_.c : $(SRCDIR)\sha1.c |
| 660 | 666 | +translate$E $** > $@ |
| 667 | + | |
| 668 | +$(OBJDIR)\sha1hard$O : sha1hard_.c sha1hard.h | |
| 669 | + $(TCC) -o$@ -c sha1hard_.c | |
| 670 | + | |
| 671 | +sha1hard_.c : $(SRCDIR)\sha1hard.c | |
| 672 | + +translate$E $** > $@ | |
| 673 | + | |
| 674 | +$(OBJDIR)\sha3$O : sha3_.c sha3.h | |
| 675 | + $(TCC) -o$@ -c sha3_.c | |
| 676 | + | |
| 677 | +sha3_.c : $(SRCDIR)\sha3.c | |
| 678 | + +translate$E $** > $@ | |
| 661 | 679 | |
| 662 | 680 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 663 | 681 | $(TCC) -o$@ -c shun_.c |
| 664 | 682 | |
| 665 | 683 | shun_.c : $(SRCDIR)\shun.c |
| @@ -856,7 +874,7 @@ | ||
| 856 | 874 | |
| 857 | 875 | zip_.c : $(SRCDIR)\zip.c |
| 858 | 876 | +translate$E $** > $@ |
| 859 | 877 | |
| 860 | 878 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 861 | - +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 879 | + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 862 | 880 | @copy /Y nul: headers |
| 863 | 881 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -28,13 +28,13 @@ | |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 36 | |
| 37 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -356,10 +356,16 @@ | |
| 356 | $(OBJDIR)\gzip$O : gzip_.c gzip.h |
| 357 | $(TCC) -o$@ -c gzip_.c |
| 358 | |
| 359 | gzip_.c : $(SRCDIR)\gzip.c |
| 360 | +translate$E $** > $@ |
| 361 | |
| 362 | $(OBJDIR)\http$O : http_.c http.h |
| 363 | $(TCC) -o$@ -c http_.c |
| 364 | |
| 365 | http_.c : $(SRCDIR)\http.c |
| @@ -656,10 +662,22 @@ | |
| 656 | $(OBJDIR)\sha1$O : sha1_.c sha1.h |
| 657 | $(TCC) -o$@ -c sha1_.c |
| 658 | |
| 659 | sha1_.c : $(SRCDIR)\sha1.c |
| 660 | +translate$E $** > $@ |
| 661 | |
| 662 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 663 | $(TCC) -o$@ -c shun_.c |
| 664 | |
| 665 | shun_.c : $(SRCDIR)\shun.c |
| @@ -856,7 +874,7 @@ | |
| 856 | |
| 857 | zip_.c : $(SRCDIR)\zip.c |
| 858 | +translate$E $** > $@ |
| 859 | |
| 860 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 861 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 862 | @copy /Y nul: headers |
| 863 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -28,13 +28,13 @@ | |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 36 | |
| 37 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 sha1hard sha3 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -356,10 +356,16 @@ | |
| 356 | $(OBJDIR)\gzip$O : gzip_.c gzip.h |
| 357 | $(TCC) -o$@ -c gzip_.c |
| 358 | |
| 359 | gzip_.c : $(SRCDIR)\gzip.c |
| 360 | +translate$E $** > $@ |
| 361 | |
| 362 | $(OBJDIR)\hname$O : hname_.c hname.h |
| 363 | $(TCC) -o$@ -c hname_.c |
| 364 | |
| 365 | hname_.c : $(SRCDIR)\hname.c |
| 366 | +translate$E $** > $@ |
| 367 | |
| 368 | $(OBJDIR)\http$O : http_.c http.h |
| 369 | $(TCC) -o$@ -c http_.c |
| 370 | |
| 371 | http_.c : $(SRCDIR)\http.c |
| @@ -656,10 +662,22 @@ | |
| 662 | $(OBJDIR)\sha1$O : sha1_.c sha1.h |
| 663 | $(TCC) -o$@ -c sha1_.c |
| 664 | |
| 665 | sha1_.c : $(SRCDIR)\sha1.c |
| 666 | +translate$E $** > $@ |
| 667 | |
| 668 | $(OBJDIR)\sha1hard$O : sha1hard_.c sha1hard.h |
| 669 | $(TCC) -o$@ -c sha1hard_.c |
| 670 | |
| 671 | sha1hard_.c : $(SRCDIR)\sha1hard.c |
| 672 | +translate$E $** > $@ |
| 673 | |
| 674 | $(OBJDIR)\sha3$O : sha3_.c sha3.h |
| 675 | $(TCC) -o$@ -c sha3_.c |
| 676 | |
| 677 | sha3_.c : $(SRCDIR)\sha3.c |
| 678 | +translate$E $** > $@ |
| 679 | |
| 680 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 681 | $(TCC) -o$@ -c shun_.c |
| 682 | |
| 683 | shun_.c : $(SRCDIR)\shun.c |
| @@ -856,7 +874,7 @@ | |
| 874 | |
| 875 | zip_.c : $(SRCDIR)\zip.c |
| 876 | +translate$E $** > $@ |
| 877 | |
| 878 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 879 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 880 | @copy /Y nul: headers |
| 881 |
+36
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -461,10 +461,11 @@ | ||
| 461 | 461 | $(SRCDIR)/fshell.c \ |
| 462 | 462 | $(SRCDIR)/fusefs.c \ |
| 463 | 463 | $(SRCDIR)/glob.c \ |
| 464 | 464 | $(SRCDIR)/graph.c \ |
| 465 | 465 | $(SRCDIR)/gzip.c \ |
| 466 | + $(SRCDIR)/hname.c \ | |
| 466 | 467 | $(SRCDIR)/http.c \ |
| 467 | 468 | $(SRCDIR)/http_socket.c \ |
| 468 | 469 | $(SRCDIR)/http_ssl.c \ |
| 469 | 470 | $(SRCDIR)/http_transport.c \ |
| 470 | 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | ||
| 511 | 512 | $(SRCDIR)/rss.c \ |
| 512 | 513 | $(SRCDIR)/schema.c \ |
| 513 | 514 | $(SRCDIR)/search.c \ |
| 514 | 515 | $(SRCDIR)/setup.c \ |
| 515 | 516 | $(SRCDIR)/sha1.c \ |
| 517 | + $(SRCDIR)/sha1hard.c \ | |
| 518 | + $(SRCDIR)/sha3.c \ | |
| 516 | 519 | $(SRCDIR)/shun.c \ |
| 517 | 520 | $(SRCDIR)/sitemap.c \ |
| 518 | 521 | $(SRCDIR)/skins.c \ |
| 519 | 522 | $(SRCDIR)/sqlcmd.c \ |
| 520 | 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | ||
| 636 | 639 | $(OBJDIR)/fshell_.c \ |
| 637 | 640 | $(OBJDIR)/fusefs_.c \ |
| 638 | 641 | $(OBJDIR)/glob_.c \ |
| 639 | 642 | $(OBJDIR)/graph_.c \ |
| 640 | 643 | $(OBJDIR)/gzip_.c \ |
| 644 | + $(OBJDIR)/hname_.c \ | |
| 641 | 645 | $(OBJDIR)/http_.c \ |
| 642 | 646 | $(OBJDIR)/http_socket_.c \ |
| 643 | 647 | $(OBJDIR)/http_ssl_.c \ |
| 644 | 648 | $(OBJDIR)/http_transport_.c \ |
| 645 | 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | ||
| 686 | 690 | $(OBJDIR)/rss_.c \ |
| 687 | 691 | $(OBJDIR)/schema_.c \ |
| 688 | 692 | $(OBJDIR)/search_.c \ |
| 689 | 693 | $(OBJDIR)/setup_.c \ |
| 690 | 694 | $(OBJDIR)/sha1_.c \ |
| 695 | + $(OBJDIR)/sha1hard_.c \ | |
| 696 | + $(OBJDIR)/sha3_.c \ | |
| 691 | 697 | $(OBJDIR)/shun_.c \ |
| 692 | 698 | $(OBJDIR)/sitemap_.c \ |
| 693 | 699 | $(OBJDIR)/skins_.c \ |
| 694 | 700 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | ||
| 760 | 766 | $(OBJDIR)/fshell.o \ |
| 761 | 767 | $(OBJDIR)/fusefs.o \ |
| 762 | 768 | $(OBJDIR)/glob.o \ |
| 763 | 769 | $(OBJDIR)/graph.o \ |
| 764 | 770 | $(OBJDIR)/gzip.o \ |
| 771 | + $(OBJDIR)/hname.o \ | |
| 765 | 772 | $(OBJDIR)/http.o \ |
| 766 | 773 | $(OBJDIR)/http_socket.o \ |
| 767 | 774 | $(OBJDIR)/http_ssl.o \ |
| 768 | 775 | $(OBJDIR)/http_transport.o \ |
| 769 | 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | ||
| 810 | 817 | $(OBJDIR)/rss.o \ |
| 811 | 818 | $(OBJDIR)/schema.o \ |
| 812 | 819 | $(OBJDIR)/search.o \ |
| 813 | 820 | $(OBJDIR)/setup.o \ |
| 814 | 821 | $(OBJDIR)/sha1.o \ |
| 822 | + $(OBJDIR)/sha1hard.o \ | |
| 823 | + $(OBJDIR)/sha3.o \ | |
| 815 | 824 | $(OBJDIR)/shun.o \ |
| 816 | 825 | $(OBJDIR)/sitemap.o \ |
| 817 | 826 | $(OBJDIR)/skins.o \ |
| 818 | 827 | $(OBJDIR)/sqlcmd.o \ |
| 819 | 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | ||
| 1095 | 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | + $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ | |
| 1100 | 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | ||
| 1145 | 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | + $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ | |
| 1161 | + $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ | |
| 1150 | 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | ||
| 1498 | 1510 | |
| 1499 | 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | 1513 | |
| 1502 | 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | + | |
| 1516 | +$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) | |
| 1517 | + $(TRANSLATE) $(SRCDIR)/hname.c >$@ | |
| 1518 | + | |
| 1519 | +$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h | |
| 1520 | + $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c | |
| 1521 | + | |
| 1522 | +$(OBJDIR)/hname.h: $(OBJDIR)/headers | |
| 1503 | 1523 | |
| 1504 | 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | 1526 | |
| 1507 | 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | ||
| 1898 | 1918 | |
| 1899 | 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | 1921 | |
| 1902 | 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | + | |
| 1924 | +$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) | |
| 1925 | + $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ | |
| 1926 | + | |
| 1927 | +$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h | |
| 1928 | + $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c | |
| 1929 | + | |
| 1930 | +$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers | |
| 1931 | + | |
| 1932 | +$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) | |
| 1933 | + $(TRANSLATE) $(SRCDIR)/sha3.c >$@ | |
| 1934 | + | |
| 1935 | +$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h | |
| 1936 | + $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c | |
| 1937 | + | |
| 1938 | +$(OBJDIR)/sha3.h: $(OBJDIR)/headers | |
| 1903 | 1939 | |
| 1904 | 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | 1942 | |
| 1907 | 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 | 1944 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/http.c \ |
| 467 | $(SRCDIR)/http_socket.c \ |
| 468 | $(SRCDIR)/http_ssl.c \ |
| 469 | $(SRCDIR)/http_transport.c \ |
| 470 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 511 | $(SRCDIR)/rss.c \ |
| 512 | $(SRCDIR)/schema.c \ |
| 513 | $(SRCDIR)/search.c \ |
| 514 | $(SRCDIR)/setup.c \ |
| 515 | $(SRCDIR)/sha1.c \ |
| 516 | $(SRCDIR)/shun.c \ |
| 517 | $(SRCDIR)/sitemap.c \ |
| 518 | $(SRCDIR)/skins.c \ |
| 519 | $(SRCDIR)/sqlcmd.c \ |
| 520 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 636 | $(OBJDIR)/fshell_.c \ |
| 637 | $(OBJDIR)/fusefs_.c \ |
| 638 | $(OBJDIR)/glob_.c \ |
| 639 | $(OBJDIR)/graph_.c \ |
| 640 | $(OBJDIR)/gzip_.c \ |
| 641 | $(OBJDIR)/http_.c \ |
| 642 | $(OBJDIR)/http_socket_.c \ |
| 643 | $(OBJDIR)/http_ssl_.c \ |
| 644 | $(OBJDIR)/http_transport_.c \ |
| 645 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 686 | $(OBJDIR)/rss_.c \ |
| 687 | $(OBJDIR)/schema_.c \ |
| 688 | $(OBJDIR)/search_.c \ |
| 689 | $(OBJDIR)/setup_.c \ |
| 690 | $(OBJDIR)/sha1_.c \ |
| 691 | $(OBJDIR)/shun_.c \ |
| 692 | $(OBJDIR)/sitemap_.c \ |
| 693 | $(OBJDIR)/skins_.c \ |
| 694 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 760 | $(OBJDIR)/fshell.o \ |
| 761 | $(OBJDIR)/fusefs.o \ |
| 762 | $(OBJDIR)/glob.o \ |
| 763 | $(OBJDIR)/graph.o \ |
| 764 | $(OBJDIR)/gzip.o \ |
| 765 | $(OBJDIR)/http.o \ |
| 766 | $(OBJDIR)/http_socket.o \ |
| 767 | $(OBJDIR)/http_ssl.o \ |
| 768 | $(OBJDIR)/http_transport.o \ |
| 769 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 810 | $(OBJDIR)/rss.o \ |
| 811 | $(OBJDIR)/schema.o \ |
| 812 | $(OBJDIR)/search.o \ |
| 813 | $(OBJDIR)/setup.o \ |
| 814 | $(OBJDIR)/sha1.o \ |
| 815 | $(OBJDIR)/shun.o \ |
| 816 | $(OBJDIR)/sitemap.o \ |
| 817 | $(OBJDIR)/skins.o \ |
| 818 | $(OBJDIR)/sqlcmd.o \ |
| 819 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1095 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1100 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1145 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1150 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1498 | |
| 1499 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | |
| 1502 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1503 | |
| 1504 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | |
| 1507 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1898 | |
| 1899 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | |
| 1902 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1903 | |
| 1904 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | |
| 1907 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/hname.c \ |
| 467 | $(SRCDIR)/http.c \ |
| 468 | $(SRCDIR)/http_socket.c \ |
| 469 | $(SRCDIR)/http_ssl.c \ |
| 470 | $(SRCDIR)/http_transport.c \ |
| 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 512 | $(SRCDIR)/rss.c \ |
| 513 | $(SRCDIR)/schema.c \ |
| 514 | $(SRCDIR)/search.c \ |
| 515 | $(SRCDIR)/setup.c \ |
| 516 | $(SRCDIR)/sha1.c \ |
| 517 | $(SRCDIR)/sha1hard.c \ |
| 518 | $(SRCDIR)/sha3.c \ |
| 519 | $(SRCDIR)/shun.c \ |
| 520 | $(SRCDIR)/sitemap.c \ |
| 521 | $(SRCDIR)/skins.c \ |
| 522 | $(SRCDIR)/sqlcmd.c \ |
| 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 639 | $(OBJDIR)/fshell_.c \ |
| 640 | $(OBJDIR)/fusefs_.c \ |
| 641 | $(OBJDIR)/glob_.c \ |
| 642 | $(OBJDIR)/graph_.c \ |
| 643 | $(OBJDIR)/gzip_.c \ |
| 644 | $(OBJDIR)/hname_.c \ |
| 645 | $(OBJDIR)/http_.c \ |
| 646 | $(OBJDIR)/http_socket_.c \ |
| 647 | $(OBJDIR)/http_ssl_.c \ |
| 648 | $(OBJDIR)/http_transport_.c \ |
| 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 690 | $(OBJDIR)/rss_.c \ |
| 691 | $(OBJDIR)/schema_.c \ |
| 692 | $(OBJDIR)/search_.c \ |
| 693 | $(OBJDIR)/setup_.c \ |
| 694 | $(OBJDIR)/sha1_.c \ |
| 695 | $(OBJDIR)/sha1hard_.c \ |
| 696 | $(OBJDIR)/sha3_.c \ |
| 697 | $(OBJDIR)/shun_.c \ |
| 698 | $(OBJDIR)/sitemap_.c \ |
| 699 | $(OBJDIR)/skins_.c \ |
| 700 | $(OBJDIR)/sqlcmd_.c \ |
| 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 766 | $(OBJDIR)/fshell.o \ |
| 767 | $(OBJDIR)/fusefs.o \ |
| 768 | $(OBJDIR)/glob.o \ |
| 769 | $(OBJDIR)/graph.o \ |
| 770 | $(OBJDIR)/gzip.o \ |
| 771 | $(OBJDIR)/hname.o \ |
| 772 | $(OBJDIR)/http.o \ |
| 773 | $(OBJDIR)/http_socket.o \ |
| 774 | $(OBJDIR)/http_ssl.o \ |
| 775 | $(OBJDIR)/http_transport.o \ |
| 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 817 | $(OBJDIR)/rss.o \ |
| 818 | $(OBJDIR)/schema.o \ |
| 819 | $(OBJDIR)/search.o \ |
| 820 | $(OBJDIR)/setup.o \ |
| 821 | $(OBJDIR)/sha1.o \ |
| 822 | $(OBJDIR)/sha1hard.o \ |
| 823 | $(OBJDIR)/sha3.o \ |
| 824 | $(OBJDIR)/shun.o \ |
| 825 | $(OBJDIR)/sitemap.o \ |
| 826 | $(OBJDIR)/skins.o \ |
| 827 | $(OBJDIR)/sqlcmd.o \ |
| 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ |
| 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ |
| 1161 | $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ |
| 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1510 | |
| 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1513 | |
| 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | |
| 1516 | $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) |
| 1517 | $(TRANSLATE) $(SRCDIR)/hname.c >$@ |
| 1518 | |
| 1519 | $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h |
| 1520 | $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c |
| 1521 | |
| 1522 | $(OBJDIR)/hname.h: $(OBJDIR)/headers |
| 1523 | |
| 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1526 | |
| 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1918 | |
| 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1921 | |
| 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | |
| 1924 | $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) |
| 1925 | $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ |
| 1926 | |
| 1927 | $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h |
| 1928 | $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c |
| 1929 | |
| 1930 | $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers |
| 1931 | |
| 1932 | $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) |
| 1933 | $(TRANSLATE) $(SRCDIR)/sha3.c >$@ |
| 1934 | |
| 1935 | $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h |
| 1936 | $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c |
| 1937 | |
| 1938 | $(OBJDIR)/sha3.h: $(OBJDIR)/headers |
| 1939 | |
| 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1942 | |
| 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1944 |
+36
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -461,10 +461,11 @@ | ||
| 461 | 461 | $(SRCDIR)/fshell.c \ |
| 462 | 462 | $(SRCDIR)/fusefs.c \ |
| 463 | 463 | $(SRCDIR)/glob.c \ |
| 464 | 464 | $(SRCDIR)/graph.c \ |
| 465 | 465 | $(SRCDIR)/gzip.c \ |
| 466 | + $(SRCDIR)/hname.c \ | |
| 466 | 467 | $(SRCDIR)/http.c \ |
| 467 | 468 | $(SRCDIR)/http_socket.c \ |
| 468 | 469 | $(SRCDIR)/http_ssl.c \ |
| 469 | 470 | $(SRCDIR)/http_transport.c \ |
| 470 | 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | ||
| 511 | 512 | $(SRCDIR)/rss.c \ |
| 512 | 513 | $(SRCDIR)/schema.c \ |
| 513 | 514 | $(SRCDIR)/search.c \ |
| 514 | 515 | $(SRCDIR)/setup.c \ |
| 515 | 516 | $(SRCDIR)/sha1.c \ |
| 517 | + $(SRCDIR)/sha1hard.c \ | |
| 518 | + $(SRCDIR)/sha3.c \ | |
| 516 | 519 | $(SRCDIR)/shun.c \ |
| 517 | 520 | $(SRCDIR)/sitemap.c \ |
| 518 | 521 | $(SRCDIR)/skins.c \ |
| 519 | 522 | $(SRCDIR)/sqlcmd.c \ |
| 520 | 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | ||
| 636 | 639 | $(OBJDIR)/fshell_.c \ |
| 637 | 640 | $(OBJDIR)/fusefs_.c \ |
| 638 | 641 | $(OBJDIR)/glob_.c \ |
| 639 | 642 | $(OBJDIR)/graph_.c \ |
| 640 | 643 | $(OBJDIR)/gzip_.c \ |
| 644 | + $(OBJDIR)/hname_.c \ | |
| 641 | 645 | $(OBJDIR)/http_.c \ |
| 642 | 646 | $(OBJDIR)/http_socket_.c \ |
| 643 | 647 | $(OBJDIR)/http_ssl_.c \ |
| 644 | 648 | $(OBJDIR)/http_transport_.c \ |
| 645 | 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | ||
| 686 | 690 | $(OBJDIR)/rss_.c \ |
| 687 | 691 | $(OBJDIR)/schema_.c \ |
| 688 | 692 | $(OBJDIR)/search_.c \ |
| 689 | 693 | $(OBJDIR)/setup_.c \ |
| 690 | 694 | $(OBJDIR)/sha1_.c \ |
| 695 | + $(OBJDIR)/sha1hard_.c \ | |
| 696 | + $(OBJDIR)/sha3_.c \ | |
| 691 | 697 | $(OBJDIR)/shun_.c \ |
| 692 | 698 | $(OBJDIR)/sitemap_.c \ |
| 693 | 699 | $(OBJDIR)/skins_.c \ |
| 694 | 700 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | ||
| 760 | 766 | $(OBJDIR)/fshell.o \ |
| 761 | 767 | $(OBJDIR)/fusefs.o \ |
| 762 | 768 | $(OBJDIR)/glob.o \ |
| 763 | 769 | $(OBJDIR)/graph.o \ |
| 764 | 770 | $(OBJDIR)/gzip.o \ |
| 771 | + $(OBJDIR)/hname.o \ | |
| 765 | 772 | $(OBJDIR)/http.o \ |
| 766 | 773 | $(OBJDIR)/http_socket.o \ |
| 767 | 774 | $(OBJDIR)/http_ssl.o \ |
| 768 | 775 | $(OBJDIR)/http_transport.o \ |
| 769 | 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | ||
| 810 | 817 | $(OBJDIR)/rss.o \ |
| 811 | 818 | $(OBJDIR)/schema.o \ |
| 812 | 819 | $(OBJDIR)/search.o \ |
| 813 | 820 | $(OBJDIR)/setup.o \ |
| 814 | 821 | $(OBJDIR)/sha1.o \ |
| 822 | + $(OBJDIR)/sha1hard.o \ | |
| 823 | + $(OBJDIR)/sha3.o \ | |
| 815 | 824 | $(OBJDIR)/shun.o \ |
| 816 | 825 | $(OBJDIR)/sitemap.o \ |
| 817 | 826 | $(OBJDIR)/skins.o \ |
| 818 | 827 | $(OBJDIR)/sqlcmd.o \ |
| 819 | 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | ||
| 1095 | 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | + $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ | |
| 1100 | 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | ||
| 1145 | 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | + $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ | |
| 1161 | + $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ | |
| 1150 | 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | ||
| 1498 | 1510 | |
| 1499 | 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | 1513 | |
| 1502 | 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | + | |
| 1516 | +$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) | |
| 1517 | + $(TRANSLATE) $(SRCDIR)/hname.c >$@ | |
| 1518 | + | |
| 1519 | +$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h | |
| 1520 | + $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c | |
| 1521 | + | |
| 1522 | +$(OBJDIR)/hname.h: $(OBJDIR)/headers | |
| 1503 | 1523 | |
| 1504 | 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | 1526 | |
| 1507 | 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | ||
| 1898 | 1918 | |
| 1899 | 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | 1921 | |
| 1902 | 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | + | |
| 1924 | +$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) | |
| 1925 | + $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ | |
| 1926 | + | |
| 1927 | +$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h | |
| 1928 | + $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c | |
| 1929 | + | |
| 1930 | +$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers | |
| 1931 | + | |
| 1932 | +$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) | |
| 1933 | + $(TRANSLATE) $(SRCDIR)/sha3.c >$@ | |
| 1934 | + | |
| 1935 | +$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h | |
| 1936 | + $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c | |
| 1937 | + | |
| 1938 | +$(OBJDIR)/sha3.h: $(OBJDIR)/headers | |
| 1903 | 1939 | |
| 1904 | 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | 1942 | |
| 1907 | 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 | 1944 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/http.c \ |
| 467 | $(SRCDIR)/http_socket.c \ |
| 468 | $(SRCDIR)/http_ssl.c \ |
| 469 | $(SRCDIR)/http_transport.c \ |
| 470 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 511 | $(SRCDIR)/rss.c \ |
| 512 | $(SRCDIR)/schema.c \ |
| 513 | $(SRCDIR)/search.c \ |
| 514 | $(SRCDIR)/setup.c \ |
| 515 | $(SRCDIR)/sha1.c \ |
| 516 | $(SRCDIR)/shun.c \ |
| 517 | $(SRCDIR)/sitemap.c \ |
| 518 | $(SRCDIR)/skins.c \ |
| 519 | $(SRCDIR)/sqlcmd.c \ |
| 520 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 636 | $(OBJDIR)/fshell_.c \ |
| 637 | $(OBJDIR)/fusefs_.c \ |
| 638 | $(OBJDIR)/glob_.c \ |
| 639 | $(OBJDIR)/graph_.c \ |
| 640 | $(OBJDIR)/gzip_.c \ |
| 641 | $(OBJDIR)/http_.c \ |
| 642 | $(OBJDIR)/http_socket_.c \ |
| 643 | $(OBJDIR)/http_ssl_.c \ |
| 644 | $(OBJDIR)/http_transport_.c \ |
| 645 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 686 | $(OBJDIR)/rss_.c \ |
| 687 | $(OBJDIR)/schema_.c \ |
| 688 | $(OBJDIR)/search_.c \ |
| 689 | $(OBJDIR)/setup_.c \ |
| 690 | $(OBJDIR)/sha1_.c \ |
| 691 | $(OBJDIR)/shun_.c \ |
| 692 | $(OBJDIR)/sitemap_.c \ |
| 693 | $(OBJDIR)/skins_.c \ |
| 694 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 760 | $(OBJDIR)/fshell.o \ |
| 761 | $(OBJDIR)/fusefs.o \ |
| 762 | $(OBJDIR)/glob.o \ |
| 763 | $(OBJDIR)/graph.o \ |
| 764 | $(OBJDIR)/gzip.o \ |
| 765 | $(OBJDIR)/http.o \ |
| 766 | $(OBJDIR)/http_socket.o \ |
| 767 | $(OBJDIR)/http_ssl.o \ |
| 768 | $(OBJDIR)/http_transport.o \ |
| 769 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 810 | $(OBJDIR)/rss.o \ |
| 811 | $(OBJDIR)/schema.o \ |
| 812 | $(OBJDIR)/search.o \ |
| 813 | $(OBJDIR)/setup.o \ |
| 814 | $(OBJDIR)/sha1.o \ |
| 815 | $(OBJDIR)/shun.o \ |
| 816 | $(OBJDIR)/sitemap.o \ |
| 817 | $(OBJDIR)/skins.o \ |
| 818 | $(OBJDIR)/sqlcmd.o \ |
| 819 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1095 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1100 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1145 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1150 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1498 | |
| 1499 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | |
| 1502 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1503 | |
| 1504 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | |
| 1507 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1898 | |
| 1899 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | |
| 1902 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1903 | |
| 1904 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | |
| 1907 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/hname.c \ |
| 467 | $(SRCDIR)/http.c \ |
| 468 | $(SRCDIR)/http_socket.c \ |
| 469 | $(SRCDIR)/http_ssl.c \ |
| 470 | $(SRCDIR)/http_transport.c \ |
| 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 512 | $(SRCDIR)/rss.c \ |
| 513 | $(SRCDIR)/schema.c \ |
| 514 | $(SRCDIR)/search.c \ |
| 515 | $(SRCDIR)/setup.c \ |
| 516 | $(SRCDIR)/sha1.c \ |
| 517 | $(SRCDIR)/sha1hard.c \ |
| 518 | $(SRCDIR)/sha3.c \ |
| 519 | $(SRCDIR)/shun.c \ |
| 520 | $(SRCDIR)/sitemap.c \ |
| 521 | $(SRCDIR)/skins.c \ |
| 522 | $(SRCDIR)/sqlcmd.c \ |
| 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 639 | $(OBJDIR)/fshell_.c \ |
| 640 | $(OBJDIR)/fusefs_.c \ |
| 641 | $(OBJDIR)/glob_.c \ |
| 642 | $(OBJDIR)/graph_.c \ |
| 643 | $(OBJDIR)/gzip_.c \ |
| 644 | $(OBJDIR)/hname_.c \ |
| 645 | $(OBJDIR)/http_.c \ |
| 646 | $(OBJDIR)/http_socket_.c \ |
| 647 | $(OBJDIR)/http_ssl_.c \ |
| 648 | $(OBJDIR)/http_transport_.c \ |
| 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 690 | $(OBJDIR)/rss_.c \ |
| 691 | $(OBJDIR)/schema_.c \ |
| 692 | $(OBJDIR)/search_.c \ |
| 693 | $(OBJDIR)/setup_.c \ |
| 694 | $(OBJDIR)/sha1_.c \ |
| 695 | $(OBJDIR)/sha1hard_.c \ |
| 696 | $(OBJDIR)/sha3_.c \ |
| 697 | $(OBJDIR)/shun_.c \ |
| 698 | $(OBJDIR)/sitemap_.c \ |
| 699 | $(OBJDIR)/skins_.c \ |
| 700 | $(OBJDIR)/sqlcmd_.c \ |
| 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 766 | $(OBJDIR)/fshell.o \ |
| 767 | $(OBJDIR)/fusefs.o \ |
| 768 | $(OBJDIR)/glob.o \ |
| 769 | $(OBJDIR)/graph.o \ |
| 770 | $(OBJDIR)/gzip.o \ |
| 771 | $(OBJDIR)/hname.o \ |
| 772 | $(OBJDIR)/http.o \ |
| 773 | $(OBJDIR)/http_socket.o \ |
| 774 | $(OBJDIR)/http_ssl.o \ |
| 775 | $(OBJDIR)/http_transport.o \ |
| 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 817 | $(OBJDIR)/rss.o \ |
| 818 | $(OBJDIR)/schema.o \ |
| 819 | $(OBJDIR)/search.o \ |
| 820 | $(OBJDIR)/setup.o \ |
| 821 | $(OBJDIR)/sha1.o \ |
| 822 | $(OBJDIR)/sha1hard.o \ |
| 823 | $(OBJDIR)/sha3.o \ |
| 824 | $(OBJDIR)/shun.o \ |
| 825 | $(OBJDIR)/sitemap.o \ |
| 826 | $(OBJDIR)/skins.o \ |
| 827 | $(OBJDIR)/sqlcmd.o \ |
| 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ |
| 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ |
| 1161 | $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ |
| 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1510 | |
| 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1513 | |
| 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | |
| 1516 | $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) |
| 1517 | $(TRANSLATE) $(SRCDIR)/hname.c >$@ |
| 1518 | |
| 1519 | $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h |
| 1520 | $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c |
| 1521 | |
| 1522 | $(OBJDIR)/hname.h: $(OBJDIR)/headers |
| 1523 | |
| 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1526 | |
| 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1918 | |
| 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1921 | |
| 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | |
| 1924 | $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) |
| 1925 | $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ |
| 1926 | |
| 1927 | $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h |
| 1928 | $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c |
| 1929 | |
| 1930 | $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers |
| 1931 | |
| 1932 | $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) |
| 1933 | $(TRANSLATE) $(SRCDIR)/sha3.c >$@ |
| 1934 | |
| 1935 | $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h |
| 1936 | $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c |
| 1937 | |
| 1938 | $(OBJDIR)/sha3.h: $(OBJDIR)/headers |
| 1939 | |
| 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1942 | |
| 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1944 |
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -461,10 +461,11 @@ | ||
| 461 | 461 | $(SRCDIR)/fshell.c \ |
| 462 | 462 | $(SRCDIR)/fusefs.c \ |
| 463 | 463 | $(SRCDIR)/glob.c \ |
| 464 | 464 | $(SRCDIR)/graph.c \ |
| 465 | 465 | $(SRCDIR)/gzip.c \ |
| 466 | + $(SRCDIR)/hname.c \ | |
| 466 | 467 | $(SRCDIR)/http.c \ |
| 467 | 468 | $(SRCDIR)/http_socket.c \ |
| 468 | 469 | $(SRCDIR)/http_ssl.c \ |
| 469 | 470 | $(SRCDIR)/http_transport.c \ |
| 470 | 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | ||
| 511 | 512 | $(SRCDIR)/rss.c \ |
| 512 | 513 | $(SRCDIR)/schema.c \ |
| 513 | 514 | $(SRCDIR)/search.c \ |
| 514 | 515 | $(SRCDIR)/setup.c \ |
| 515 | 516 | $(SRCDIR)/sha1.c \ |
| 517 | + $(SRCDIR)/sha1hard.c \ | |
| 518 | + $(SRCDIR)/sha3.c \ | |
| 516 | 519 | $(SRCDIR)/shun.c \ |
| 517 | 520 | $(SRCDIR)/sitemap.c \ |
| 518 | 521 | $(SRCDIR)/skins.c \ |
| 519 | 522 | $(SRCDIR)/sqlcmd.c \ |
| 520 | 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | ||
| 636 | 639 | $(OBJDIR)/fshell_.c \ |
| 637 | 640 | $(OBJDIR)/fusefs_.c \ |
| 638 | 641 | $(OBJDIR)/glob_.c \ |
| 639 | 642 | $(OBJDIR)/graph_.c \ |
| 640 | 643 | $(OBJDIR)/gzip_.c \ |
| 644 | + $(OBJDIR)/hname_.c \ | |
| 641 | 645 | $(OBJDIR)/http_.c \ |
| 642 | 646 | $(OBJDIR)/http_socket_.c \ |
| 643 | 647 | $(OBJDIR)/http_ssl_.c \ |
| 644 | 648 | $(OBJDIR)/http_transport_.c \ |
| 645 | 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | ||
| 686 | 690 | $(OBJDIR)/rss_.c \ |
| 687 | 691 | $(OBJDIR)/schema_.c \ |
| 688 | 692 | $(OBJDIR)/search_.c \ |
| 689 | 693 | $(OBJDIR)/setup_.c \ |
| 690 | 694 | $(OBJDIR)/sha1_.c \ |
| 695 | + $(OBJDIR)/sha1hard_.c \ | |
| 696 | + $(OBJDIR)/sha3_.c \ | |
| 691 | 697 | $(OBJDIR)/shun_.c \ |
| 692 | 698 | $(OBJDIR)/sitemap_.c \ |
| 693 | 699 | $(OBJDIR)/skins_.c \ |
| 694 | 700 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | ||
| 760 | 766 | $(OBJDIR)/fshell.o \ |
| 761 | 767 | $(OBJDIR)/fusefs.o \ |
| 762 | 768 | $(OBJDIR)/glob.o \ |
| 763 | 769 | $(OBJDIR)/graph.o \ |
| 764 | 770 | $(OBJDIR)/gzip.o \ |
| 771 | + $(OBJDIR)/hname.o \ | |
| 765 | 772 | $(OBJDIR)/http.o \ |
| 766 | 773 | $(OBJDIR)/http_socket.o \ |
| 767 | 774 | $(OBJDIR)/http_ssl.o \ |
| 768 | 775 | $(OBJDIR)/http_transport.o \ |
| 769 | 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | ||
| 810 | 817 | $(OBJDIR)/rss.o \ |
| 811 | 818 | $(OBJDIR)/schema.o \ |
| 812 | 819 | $(OBJDIR)/search.o \ |
| 813 | 820 | $(OBJDIR)/setup.o \ |
| 814 | 821 | $(OBJDIR)/sha1.o \ |
| 822 | + $(OBJDIR)/sha1hard.o \ | |
| 823 | + $(OBJDIR)/sha3.o \ | |
| 815 | 824 | $(OBJDIR)/shun.o \ |
| 816 | 825 | $(OBJDIR)/sitemap.o \ |
| 817 | 826 | $(OBJDIR)/skins.o \ |
| 818 | 827 | $(OBJDIR)/sqlcmd.o \ |
| 819 | 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | ||
| 1095 | 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | + $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ | |
| 1100 | 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | ||
| 1145 | 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | + $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ | |
| 1161 | + $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ | |
| 1150 | 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | ||
| 1498 | 1510 | |
| 1499 | 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | 1513 | |
| 1502 | 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | + | |
| 1516 | +$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) | |
| 1517 | + $(TRANSLATE) $(SRCDIR)/hname.c >$@ | |
| 1518 | + | |
| 1519 | +$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h | |
| 1520 | + $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c | |
| 1521 | + | |
| 1522 | +$(OBJDIR)/hname.h: $(OBJDIR)/headers | |
| 1503 | 1523 | |
| 1504 | 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | 1526 | |
| 1507 | 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | ||
| 1898 | 1918 | |
| 1899 | 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | 1921 | |
| 1902 | 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | + | |
| 1924 | +$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) | |
| 1925 | + $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ | |
| 1926 | + | |
| 1927 | +$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h | |
| 1928 | + $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c | |
| 1929 | + | |
| 1930 | +$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers | |
| 1931 | + | |
| 1932 | +$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) | |
| 1933 | + $(TRANSLATE) $(SRCDIR)/sha3.c >$@ | |
| 1934 | + | |
| 1935 | +$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h | |
| 1936 | + $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c | |
| 1937 | + | |
| 1938 | +$(OBJDIR)/sha3.h: $(OBJDIR)/headers | |
| 1903 | 1939 | |
| 1904 | 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | 1942 | |
| 1907 | 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 | 1944 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/http.c \ |
| 467 | $(SRCDIR)/http_socket.c \ |
| 468 | $(SRCDIR)/http_ssl.c \ |
| 469 | $(SRCDIR)/http_transport.c \ |
| 470 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 511 | $(SRCDIR)/rss.c \ |
| 512 | $(SRCDIR)/schema.c \ |
| 513 | $(SRCDIR)/search.c \ |
| 514 | $(SRCDIR)/setup.c \ |
| 515 | $(SRCDIR)/sha1.c \ |
| 516 | $(SRCDIR)/shun.c \ |
| 517 | $(SRCDIR)/sitemap.c \ |
| 518 | $(SRCDIR)/skins.c \ |
| 519 | $(SRCDIR)/sqlcmd.c \ |
| 520 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 636 | $(OBJDIR)/fshell_.c \ |
| 637 | $(OBJDIR)/fusefs_.c \ |
| 638 | $(OBJDIR)/glob_.c \ |
| 639 | $(OBJDIR)/graph_.c \ |
| 640 | $(OBJDIR)/gzip_.c \ |
| 641 | $(OBJDIR)/http_.c \ |
| 642 | $(OBJDIR)/http_socket_.c \ |
| 643 | $(OBJDIR)/http_ssl_.c \ |
| 644 | $(OBJDIR)/http_transport_.c \ |
| 645 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 686 | $(OBJDIR)/rss_.c \ |
| 687 | $(OBJDIR)/schema_.c \ |
| 688 | $(OBJDIR)/search_.c \ |
| 689 | $(OBJDIR)/setup_.c \ |
| 690 | $(OBJDIR)/sha1_.c \ |
| 691 | $(OBJDIR)/shun_.c \ |
| 692 | $(OBJDIR)/sitemap_.c \ |
| 693 | $(OBJDIR)/skins_.c \ |
| 694 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 760 | $(OBJDIR)/fshell.o \ |
| 761 | $(OBJDIR)/fusefs.o \ |
| 762 | $(OBJDIR)/glob.o \ |
| 763 | $(OBJDIR)/graph.o \ |
| 764 | $(OBJDIR)/gzip.o \ |
| 765 | $(OBJDIR)/http.o \ |
| 766 | $(OBJDIR)/http_socket.o \ |
| 767 | $(OBJDIR)/http_ssl.o \ |
| 768 | $(OBJDIR)/http_transport.o \ |
| 769 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 810 | $(OBJDIR)/rss.o \ |
| 811 | $(OBJDIR)/schema.o \ |
| 812 | $(OBJDIR)/search.o \ |
| 813 | $(OBJDIR)/setup.o \ |
| 814 | $(OBJDIR)/sha1.o \ |
| 815 | $(OBJDIR)/shun.o \ |
| 816 | $(OBJDIR)/sitemap.o \ |
| 817 | $(OBJDIR)/skins.o \ |
| 818 | $(OBJDIR)/sqlcmd.o \ |
| 819 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1095 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1100 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1145 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1150 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1498 | |
| 1499 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | |
| 1502 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1503 | |
| 1504 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | |
| 1507 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1898 | |
| 1899 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | |
| 1902 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1903 | |
| 1904 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | |
| 1907 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/hname.c \ |
| 467 | $(SRCDIR)/http.c \ |
| 468 | $(SRCDIR)/http_socket.c \ |
| 469 | $(SRCDIR)/http_ssl.c \ |
| 470 | $(SRCDIR)/http_transport.c \ |
| 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 512 | $(SRCDIR)/rss.c \ |
| 513 | $(SRCDIR)/schema.c \ |
| 514 | $(SRCDIR)/search.c \ |
| 515 | $(SRCDIR)/setup.c \ |
| 516 | $(SRCDIR)/sha1.c \ |
| 517 | $(SRCDIR)/sha1hard.c \ |
| 518 | $(SRCDIR)/sha3.c \ |
| 519 | $(SRCDIR)/shun.c \ |
| 520 | $(SRCDIR)/sitemap.c \ |
| 521 | $(SRCDIR)/skins.c \ |
| 522 | $(SRCDIR)/sqlcmd.c \ |
| 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 639 | $(OBJDIR)/fshell_.c \ |
| 640 | $(OBJDIR)/fusefs_.c \ |
| 641 | $(OBJDIR)/glob_.c \ |
| 642 | $(OBJDIR)/graph_.c \ |
| 643 | $(OBJDIR)/gzip_.c \ |
| 644 | $(OBJDIR)/hname_.c \ |
| 645 | $(OBJDIR)/http_.c \ |
| 646 | $(OBJDIR)/http_socket_.c \ |
| 647 | $(OBJDIR)/http_ssl_.c \ |
| 648 | $(OBJDIR)/http_transport_.c \ |
| 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 690 | $(OBJDIR)/rss_.c \ |
| 691 | $(OBJDIR)/schema_.c \ |
| 692 | $(OBJDIR)/search_.c \ |
| 693 | $(OBJDIR)/setup_.c \ |
| 694 | $(OBJDIR)/sha1_.c \ |
| 695 | $(OBJDIR)/sha1hard_.c \ |
| 696 | $(OBJDIR)/sha3_.c \ |
| 697 | $(OBJDIR)/shun_.c \ |
| 698 | $(OBJDIR)/sitemap_.c \ |
| 699 | $(OBJDIR)/skins_.c \ |
| 700 | $(OBJDIR)/sqlcmd_.c \ |
| 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 766 | $(OBJDIR)/fshell.o \ |
| 767 | $(OBJDIR)/fusefs.o \ |
| 768 | $(OBJDIR)/glob.o \ |
| 769 | $(OBJDIR)/graph.o \ |
| 770 | $(OBJDIR)/gzip.o \ |
| 771 | $(OBJDIR)/hname.o \ |
| 772 | $(OBJDIR)/http.o \ |
| 773 | $(OBJDIR)/http_socket.o \ |
| 774 | $(OBJDIR)/http_ssl.o \ |
| 775 | $(OBJDIR)/http_transport.o \ |
| 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 817 | $(OBJDIR)/rss.o \ |
| 818 | $(OBJDIR)/schema.o \ |
| 819 | $(OBJDIR)/search.o \ |
| 820 | $(OBJDIR)/setup.o \ |
| 821 | $(OBJDIR)/sha1.o \ |
| 822 | $(OBJDIR)/sha1hard.o \ |
| 823 | $(OBJDIR)/sha3.o \ |
| 824 | $(OBJDIR)/shun.o \ |
| 825 | $(OBJDIR)/sitemap.o \ |
| 826 | $(OBJDIR)/skins.o \ |
| 827 | $(OBJDIR)/sqlcmd.o \ |
| 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ |
| 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ |
| 1161 | $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ |
| 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1510 | |
| 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1513 | |
| 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | |
| 1516 | $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) |
| 1517 | $(TRANSLATE) $(SRCDIR)/hname.c >$@ |
| 1518 | |
| 1519 | $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h |
| 1520 | $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c |
| 1521 | |
| 1522 | $(OBJDIR)/hname.h: $(OBJDIR)/headers |
| 1523 | |
| 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1526 | |
| 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1918 | |
| 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1921 | |
| 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | |
| 1924 | $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) |
| 1925 | $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ |
| 1926 | |
| 1927 | $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h |
| 1928 | $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c |
| 1929 | |
| 1930 | $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers |
| 1931 | |
| 1932 | $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) |
| 1933 | $(TRANSLATE) $(SRCDIR)/sha3.c >$@ |
| 1934 | |
| 1935 | $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h |
| 1936 | $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c |
| 1937 | |
| 1938 | $(OBJDIR)/sha3.h: $(OBJDIR)/headers |
| 1939 | |
| 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1942 | |
| 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1944 |
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -461,10 +461,11 @@ | ||
| 461 | 461 | $(SRCDIR)/fshell.c \ |
| 462 | 462 | $(SRCDIR)/fusefs.c \ |
| 463 | 463 | $(SRCDIR)/glob.c \ |
| 464 | 464 | $(SRCDIR)/graph.c \ |
| 465 | 465 | $(SRCDIR)/gzip.c \ |
| 466 | + $(SRCDIR)/hname.c \ | |
| 466 | 467 | $(SRCDIR)/http.c \ |
| 467 | 468 | $(SRCDIR)/http_socket.c \ |
| 468 | 469 | $(SRCDIR)/http_ssl.c \ |
| 469 | 470 | $(SRCDIR)/http_transport.c \ |
| 470 | 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | ||
| 511 | 512 | $(SRCDIR)/rss.c \ |
| 512 | 513 | $(SRCDIR)/schema.c \ |
| 513 | 514 | $(SRCDIR)/search.c \ |
| 514 | 515 | $(SRCDIR)/setup.c \ |
| 515 | 516 | $(SRCDIR)/sha1.c \ |
| 517 | + $(SRCDIR)/sha1hard.c \ | |
| 518 | + $(SRCDIR)/sha3.c \ | |
| 516 | 519 | $(SRCDIR)/shun.c \ |
| 517 | 520 | $(SRCDIR)/sitemap.c \ |
| 518 | 521 | $(SRCDIR)/skins.c \ |
| 519 | 522 | $(SRCDIR)/sqlcmd.c \ |
| 520 | 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | ||
| 636 | 639 | $(OBJDIR)/fshell_.c \ |
| 637 | 640 | $(OBJDIR)/fusefs_.c \ |
| 638 | 641 | $(OBJDIR)/glob_.c \ |
| 639 | 642 | $(OBJDIR)/graph_.c \ |
| 640 | 643 | $(OBJDIR)/gzip_.c \ |
| 644 | + $(OBJDIR)/hname_.c \ | |
| 641 | 645 | $(OBJDIR)/http_.c \ |
| 642 | 646 | $(OBJDIR)/http_socket_.c \ |
| 643 | 647 | $(OBJDIR)/http_ssl_.c \ |
| 644 | 648 | $(OBJDIR)/http_transport_.c \ |
| 645 | 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | ||
| 686 | 690 | $(OBJDIR)/rss_.c \ |
| 687 | 691 | $(OBJDIR)/schema_.c \ |
| 688 | 692 | $(OBJDIR)/search_.c \ |
| 689 | 693 | $(OBJDIR)/setup_.c \ |
| 690 | 694 | $(OBJDIR)/sha1_.c \ |
| 695 | + $(OBJDIR)/sha1hard_.c \ | |
| 696 | + $(OBJDIR)/sha3_.c \ | |
| 691 | 697 | $(OBJDIR)/shun_.c \ |
| 692 | 698 | $(OBJDIR)/sitemap_.c \ |
| 693 | 699 | $(OBJDIR)/skins_.c \ |
| 694 | 700 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | ||
| 760 | 766 | $(OBJDIR)/fshell.o \ |
| 761 | 767 | $(OBJDIR)/fusefs.o \ |
| 762 | 768 | $(OBJDIR)/glob.o \ |
| 763 | 769 | $(OBJDIR)/graph.o \ |
| 764 | 770 | $(OBJDIR)/gzip.o \ |
| 771 | + $(OBJDIR)/hname.o \ | |
| 765 | 772 | $(OBJDIR)/http.o \ |
| 766 | 773 | $(OBJDIR)/http_socket.o \ |
| 767 | 774 | $(OBJDIR)/http_ssl.o \ |
| 768 | 775 | $(OBJDIR)/http_transport.o \ |
| 769 | 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | ||
| 810 | 817 | $(OBJDIR)/rss.o \ |
| 811 | 818 | $(OBJDIR)/schema.o \ |
| 812 | 819 | $(OBJDIR)/search.o \ |
| 813 | 820 | $(OBJDIR)/setup.o \ |
| 814 | 821 | $(OBJDIR)/sha1.o \ |
| 822 | + $(OBJDIR)/sha1hard.o \ | |
| 823 | + $(OBJDIR)/sha3.o \ | |
| 815 | 824 | $(OBJDIR)/shun.o \ |
| 816 | 825 | $(OBJDIR)/sitemap.o \ |
| 817 | 826 | $(OBJDIR)/skins.o \ |
| 818 | 827 | $(OBJDIR)/sqlcmd.o \ |
| 819 | 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | ||
| 1095 | 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | + $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ | |
| 1100 | 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | ||
| 1145 | 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | + $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ | |
| 1161 | + $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ | |
| 1150 | 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | ||
| 1498 | 1510 | |
| 1499 | 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | 1513 | |
| 1502 | 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | + | |
| 1516 | +$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) | |
| 1517 | + $(TRANSLATE) $(SRCDIR)/hname.c >$@ | |
| 1518 | + | |
| 1519 | +$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h | |
| 1520 | + $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c | |
| 1521 | + | |
| 1522 | +$(OBJDIR)/hname.h: $(OBJDIR)/headers | |
| 1503 | 1523 | |
| 1504 | 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | 1526 | |
| 1507 | 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | ||
| 1898 | 1918 | |
| 1899 | 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | 1921 | |
| 1902 | 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | + | |
| 1924 | +$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) | |
| 1925 | + $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ | |
| 1926 | + | |
| 1927 | +$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h | |
| 1928 | + $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c | |
| 1929 | + | |
| 1930 | +$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers | |
| 1931 | + | |
| 1932 | +$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) | |
| 1933 | + $(TRANSLATE) $(SRCDIR)/sha3.c >$@ | |
| 1934 | + | |
| 1935 | +$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h | |
| 1936 | + $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c | |
| 1937 | + | |
| 1938 | +$(OBJDIR)/sha3.h: $(OBJDIR)/headers | |
| 1903 | 1939 | |
| 1904 | 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | 1942 | |
| 1907 | 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 | 1944 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/http.c \ |
| 467 | $(SRCDIR)/http_socket.c \ |
| 468 | $(SRCDIR)/http_ssl.c \ |
| 469 | $(SRCDIR)/http_transport.c \ |
| 470 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 511 | $(SRCDIR)/rss.c \ |
| 512 | $(SRCDIR)/schema.c \ |
| 513 | $(SRCDIR)/search.c \ |
| 514 | $(SRCDIR)/setup.c \ |
| 515 | $(SRCDIR)/sha1.c \ |
| 516 | $(SRCDIR)/shun.c \ |
| 517 | $(SRCDIR)/sitemap.c \ |
| 518 | $(SRCDIR)/skins.c \ |
| 519 | $(SRCDIR)/sqlcmd.c \ |
| 520 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 636 | $(OBJDIR)/fshell_.c \ |
| 637 | $(OBJDIR)/fusefs_.c \ |
| 638 | $(OBJDIR)/glob_.c \ |
| 639 | $(OBJDIR)/graph_.c \ |
| 640 | $(OBJDIR)/gzip_.c \ |
| 641 | $(OBJDIR)/http_.c \ |
| 642 | $(OBJDIR)/http_socket_.c \ |
| 643 | $(OBJDIR)/http_ssl_.c \ |
| 644 | $(OBJDIR)/http_transport_.c \ |
| 645 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 686 | $(OBJDIR)/rss_.c \ |
| 687 | $(OBJDIR)/schema_.c \ |
| 688 | $(OBJDIR)/search_.c \ |
| 689 | $(OBJDIR)/setup_.c \ |
| 690 | $(OBJDIR)/sha1_.c \ |
| 691 | $(OBJDIR)/shun_.c \ |
| 692 | $(OBJDIR)/sitemap_.c \ |
| 693 | $(OBJDIR)/skins_.c \ |
| 694 | $(OBJDIR)/sqlcmd_.c \ |
| 695 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 760 | $(OBJDIR)/fshell.o \ |
| 761 | $(OBJDIR)/fusefs.o \ |
| 762 | $(OBJDIR)/glob.o \ |
| 763 | $(OBJDIR)/graph.o \ |
| 764 | $(OBJDIR)/gzip.o \ |
| 765 | $(OBJDIR)/http.o \ |
| 766 | $(OBJDIR)/http_socket.o \ |
| 767 | $(OBJDIR)/http_ssl.o \ |
| 768 | $(OBJDIR)/http_transport.o \ |
| 769 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 810 | $(OBJDIR)/rss.o \ |
| 811 | $(OBJDIR)/schema.o \ |
| 812 | $(OBJDIR)/search.o \ |
| 813 | $(OBJDIR)/setup.o \ |
| 814 | $(OBJDIR)/sha1.o \ |
| 815 | $(OBJDIR)/shun.o \ |
| 816 | $(OBJDIR)/sitemap.o \ |
| 817 | $(OBJDIR)/skins.o \ |
| 818 | $(OBJDIR)/sqlcmd.o \ |
| 819 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1095 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1096 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1097 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1098 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1099 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1100 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1101 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1102 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1103 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1104 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1145 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1146 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1147 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1148 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1149 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1150 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1151 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1152 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1153 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1154 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1498 | |
| 1499 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1500 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1501 | |
| 1502 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1503 | |
| 1504 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1505 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1506 | |
| 1507 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1898 | |
| 1899 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1900 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1901 | |
| 1902 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1903 | |
| 1904 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1905 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1906 | |
| 1907 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1908 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -461,10 +461,11 @@ | |
| 461 | $(SRCDIR)/fshell.c \ |
| 462 | $(SRCDIR)/fusefs.c \ |
| 463 | $(SRCDIR)/glob.c \ |
| 464 | $(SRCDIR)/graph.c \ |
| 465 | $(SRCDIR)/gzip.c \ |
| 466 | $(SRCDIR)/hname.c \ |
| 467 | $(SRCDIR)/http.c \ |
| 468 | $(SRCDIR)/http_socket.c \ |
| 469 | $(SRCDIR)/http_ssl.c \ |
| 470 | $(SRCDIR)/http_transport.c \ |
| 471 | $(SRCDIR)/import.c \ |
| @@ -511,10 +512,12 @@ | |
| 512 | $(SRCDIR)/rss.c \ |
| 513 | $(SRCDIR)/schema.c \ |
| 514 | $(SRCDIR)/search.c \ |
| 515 | $(SRCDIR)/setup.c \ |
| 516 | $(SRCDIR)/sha1.c \ |
| 517 | $(SRCDIR)/sha1hard.c \ |
| 518 | $(SRCDIR)/sha3.c \ |
| 519 | $(SRCDIR)/shun.c \ |
| 520 | $(SRCDIR)/sitemap.c \ |
| 521 | $(SRCDIR)/skins.c \ |
| 522 | $(SRCDIR)/sqlcmd.c \ |
| 523 | $(SRCDIR)/stash.c \ |
| @@ -636,10 +639,11 @@ | |
| 639 | $(OBJDIR)/fshell_.c \ |
| 640 | $(OBJDIR)/fusefs_.c \ |
| 641 | $(OBJDIR)/glob_.c \ |
| 642 | $(OBJDIR)/graph_.c \ |
| 643 | $(OBJDIR)/gzip_.c \ |
| 644 | $(OBJDIR)/hname_.c \ |
| 645 | $(OBJDIR)/http_.c \ |
| 646 | $(OBJDIR)/http_socket_.c \ |
| 647 | $(OBJDIR)/http_ssl_.c \ |
| 648 | $(OBJDIR)/http_transport_.c \ |
| 649 | $(OBJDIR)/import_.c \ |
| @@ -686,10 +690,12 @@ | |
| 690 | $(OBJDIR)/rss_.c \ |
| 691 | $(OBJDIR)/schema_.c \ |
| 692 | $(OBJDIR)/search_.c \ |
| 693 | $(OBJDIR)/setup_.c \ |
| 694 | $(OBJDIR)/sha1_.c \ |
| 695 | $(OBJDIR)/sha1hard_.c \ |
| 696 | $(OBJDIR)/sha3_.c \ |
| 697 | $(OBJDIR)/shun_.c \ |
| 698 | $(OBJDIR)/sitemap_.c \ |
| 699 | $(OBJDIR)/skins_.c \ |
| 700 | $(OBJDIR)/sqlcmd_.c \ |
| 701 | $(OBJDIR)/stash_.c \ |
| @@ -760,10 +766,11 @@ | |
| 766 | $(OBJDIR)/fshell.o \ |
| 767 | $(OBJDIR)/fusefs.o \ |
| 768 | $(OBJDIR)/glob.o \ |
| 769 | $(OBJDIR)/graph.o \ |
| 770 | $(OBJDIR)/gzip.o \ |
| 771 | $(OBJDIR)/hname.o \ |
| 772 | $(OBJDIR)/http.o \ |
| 773 | $(OBJDIR)/http_socket.o \ |
| 774 | $(OBJDIR)/http_ssl.o \ |
| 775 | $(OBJDIR)/http_transport.o \ |
| 776 | $(OBJDIR)/import.o \ |
| @@ -810,10 +817,12 @@ | |
| 817 | $(OBJDIR)/rss.o \ |
| 818 | $(OBJDIR)/schema.o \ |
| 819 | $(OBJDIR)/search.o \ |
| 820 | $(OBJDIR)/setup.o \ |
| 821 | $(OBJDIR)/sha1.o \ |
| 822 | $(OBJDIR)/sha1hard.o \ |
| 823 | $(OBJDIR)/sha3.o \ |
| 824 | $(OBJDIR)/shun.o \ |
| 825 | $(OBJDIR)/sitemap.o \ |
| 826 | $(OBJDIR)/skins.o \ |
| 827 | $(OBJDIR)/sqlcmd.o \ |
| 828 | $(OBJDIR)/stash.o \ |
| @@ -1095,10 +1104,11 @@ | |
| 1104 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| 1105 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 1106 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 1107 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 1108 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 1109 | $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ |
| 1110 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| 1111 | $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ |
| 1112 | $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| 1113 | $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ |
| 1114 | $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ |
| @@ -1145,10 +1155,12 @@ | |
| 1155 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1156 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1157 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1158 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1159 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1160 | $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ |
| 1161 | $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ |
| 1162 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1163 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1164 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1165 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1166 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| @@ -1498,10 +1510,18 @@ | |
| 1510 | |
| 1511 | $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h |
| 1512 | $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c |
| 1513 | |
| 1514 | $(OBJDIR)/gzip.h: $(OBJDIR)/headers |
| 1515 | |
| 1516 | $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE) |
| 1517 | $(TRANSLATE) $(SRCDIR)/hname.c >$@ |
| 1518 | |
| 1519 | $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h |
| 1520 | $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c |
| 1521 | |
| 1522 | $(OBJDIR)/hname.h: $(OBJDIR)/headers |
| 1523 | |
| 1524 | $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE) |
| 1525 | $(TRANSLATE) $(SRCDIR)/http.c >$@ |
| 1526 | |
| 1527 | $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h |
| @@ -1898,10 +1918,26 @@ | |
| 1918 | |
| 1919 | $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h |
| 1920 | $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c |
| 1921 | |
| 1922 | $(OBJDIR)/sha1.h: $(OBJDIR)/headers |
| 1923 | |
| 1924 | $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE) |
| 1925 | $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@ |
| 1926 | |
| 1927 | $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h |
| 1928 | $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c |
| 1929 | |
| 1930 | $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers |
| 1931 | |
| 1932 | $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE) |
| 1933 | $(TRANSLATE) $(SRCDIR)/sha3.c >$@ |
| 1934 | |
| 1935 | $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h |
| 1936 | $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c |
| 1937 | |
| 1938 | $(OBJDIR)/sha3.h: $(OBJDIR)/headers |
| 1939 | |
| 1940 | $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE) |
| 1941 | $(TRANSLATE) $(SRCDIR)/shun.c >$@ |
| 1942 | |
| 1943 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1944 |
+30
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -386,10 +386,11 @@ | ||
| 386 | 386 | fshell_.c \ |
| 387 | 387 | fusefs_.c \ |
| 388 | 388 | glob_.c \ |
| 389 | 389 | graph_.c \ |
| 390 | 390 | gzip_.c \ |
| 391 | + hname_.c \ | |
| 391 | 392 | http_.c \ |
| 392 | 393 | http_socket_.c \ |
| 393 | 394 | http_ssl_.c \ |
| 394 | 395 | http_transport_.c \ |
| 395 | 396 | import_.c \ |
| @@ -436,10 +437,12 @@ | ||
| 436 | 437 | rss_.c \ |
| 437 | 438 | schema_.c \ |
| 438 | 439 | search_.c \ |
| 439 | 440 | setup_.c \ |
| 440 | 441 | sha1_.c \ |
| 442 | + sha1hard_.c \ | |
| 443 | + sha3_.c \ | |
| 441 | 444 | shun_.c \ |
| 442 | 445 | sitemap_.c \ |
| 443 | 446 | skins_.c \ |
| 444 | 447 | sqlcmd_.c \ |
| 445 | 448 | stash_.c \ |
| @@ -560,10 +563,11 @@ | ||
| 560 | 563 | $(OX)\fshell$O \ |
| 561 | 564 | $(OX)\fusefs$O \ |
| 562 | 565 | $(OX)\glob$O \ |
| 563 | 566 | $(OX)\graph$O \ |
| 564 | 567 | $(OX)\gzip$O \ |
| 568 | + $(OX)\hname$O \ | |
| 565 | 569 | $(OX)\http$O \ |
| 566 | 570 | $(OX)\http_socket$O \ |
| 567 | 571 | $(OX)\http_ssl$O \ |
| 568 | 572 | $(OX)\http_transport$O \ |
| 569 | 573 | $(OX)\import$O \ |
| @@ -610,10 +614,12 @@ | ||
| 610 | 614 | $(OX)\rss$O \ |
| 611 | 615 | $(OX)\schema$O \ |
| 612 | 616 | $(OX)\search$O \ |
| 613 | 617 | $(OX)\setup$O \ |
| 614 | 618 | $(OX)\sha1$O \ |
| 619 | + $(OX)\sha1hard$O \ | |
| 620 | + $(OX)\sha3$O \ | |
| 615 | 621 | $(OX)\shell$O \ |
| 616 | 622 | $(OX)\shun$O \ |
| 617 | 623 | $(OX)\sitemap$O \ |
| 618 | 624 | $(OX)\skins$O \ |
| 619 | 625 | $(OX)\sqlcmd$O \ |
| @@ -743,10 +749,11 @@ | ||
| 743 | 749 | echo $(OX)\fshell.obj >> $@ |
| 744 | 750 | echo $(OX)\fusefs.obj >> $@ |
| 745 | 751 | echo $(OX)\glob.obj >> $@ |
| 746 | 752 | echo $(OX)\graph.obj >> $@ |
| 747 | 753 | echo $(OX)\gzip.obj >> $@ |
| 754 | + echo $(OX)\hname.obj >> $@ | |
| 748 | 755 | echo $(OX)\http.obj >> $@ |
| 749 | 756 | echo $(OX)\http_socket.obj >> $@ |
| 750 | 757 | echo $(OX)\http_ssl.obj >> $@ |
| 751 | 758 | echo $(OX)\http_transport.obj >> $@ |
| 752 | 759 | echo $(OX)\import.obj >> $@ |
| @@ -793,10 +800,12 @@ | ||
| 793 | 800 | echo $(OX)\rss.obj >> $@ |
| 794 | 801 | echo $(OX)\schema.obj >> $@ |
| 795 | 802 | echo $(OX)\search.obj >> $@ |
| 796 | 803 | echo $(OX)\setup.obj >> $@ |
| 797 | 804 | echo $(OX)\sha1.obj >> $@ |
| 805 | + echo $(OX)\sha1hard.obj >> $@ | |
| 806 | + echo $(OX)\sha3.obj >> $@ | |
| 798 | 807 | echo $(OX)\shell.obj >> $@ |
| 799 | 808 | echo $(OX)\shun.obj >> $@ |
| 800 | 809 | echo $(OX)\sitemap.obj >> $@ |
| 801 | 810 | echo $(OX)\skins.obj >> $@ |
| 802 | 811 | echo $(OX)\sqlcmd.obj >> $@ |
| @@ -1175,10 +1184,16 @@ | ||
| 1175 | 1184 | $(OX)\gzip$O : gzip_.c gzip.h |
| 1176 | 1185 | $(TCC) /Fo$@ -c gzip_.c |
| 1177 | 1186 | |
| 1178 | 1187 | gzip_.c : $(SRCDIR)\gzip.c |
| 1179 | 1188 | translate$E $** > $@ |
| 1189 | + | |
| 1190 | +$(OX)\hname$O : hname_.c hname.h | |
| 1191 | + $(TCC) /Fo$@ -c hname_.c | |
| 1192 | + | |
| 1193 | +hname_.c : $(SRCDIR)\hname.c | |
| 1194 | + translate$E $** > $@ | |
| 1180 | 1195 | |
| 1181 | 1196 | $(OX)\http$O : http_.c http.h |
| 1182 | 1197 | $(TCC) /Fo$@ -c http_.c |
| 1183 | 1198 | |
| 1184 | 1199 | http_.c : $(SRCDIR)\http.c |
| @@ -1475,10 +1490,22 @@ | ||
| 1475 | 1490 | $(OX)\sha1$O : sha1_.c sha1.h |
| 1476 | 1491 | $(TCC) /Fo$@ -c sha1_.c |
| 1477 | 1492 | |
| 1478 | 1493 | sha1_.c : $(SRCDIR)\sha1.c |
| 1479 | 1494 | translate$E $** > $@ |
| 1495 | + | |
| 1496 | +$(OX)\sha1hard$O : sha1hard_.c sha1hard.h | |
| 1497 | + $(TCC) /Fo$@ -c sha1hard_.c | |
| 1498 | + | |
| 1499 | +sha1hard_.c : $(SRCDIR)\sha1hard.c | |
| 1500 | + translate$E $** > $@ | |
| 1501 | + | |
| 1502 | +$(OX)\sha3$O : sha3_.c sha3.h | |
| 1503 | + $(TCC) /Fo$@ -c sha3_.c | |
| 1504 | + | |
| 1505 | +sha3_.c : $(SRCDIR)\sha3.c | |
| 1506 | + translate$E $** > $@ | |
| 1480 | 1507 | |
| 1481 | 1508 | $(OX)\shun$O : shun_.c shun.h |
| 1482 | 1509 | $(TCC) /Fo$@ -c shun_.c |
| 1483 | 1510 | |
| 1484 | 1511 | shun_.c : $(SRCDIR)\shun.c |
| @@ -1717,10 +1744,11 @@ | ||
| 1717 | 1744 | fshell_.c:fshell.h \ |
| 1718 | 1745 | fusefs_.c:fusefs.h \ |
| 1719 | 1746 | glob_.c:glob.h \ |
| 1720 | 1747 | graph_.c:graph.h \ |
| 1721 | 1748 | gzip_.c:gzip.h \ |
| 1749 | + hname_.c:hname.h \ | |
| 1722 | 1750 | http_.c:http.h \ |
| 1723 | 1751 | http_socket_.c:http_socket.h \ |
| 1724 | 1752 | http_ssl_.c:http_ssl.h \ |
| 1725 | 1753 | http_transport_.c:http_transport.h \ |
| 1726 | 1754 | import_.c:import.h \ |
| @@ -1767,10 +1795,12 @@ | ||
| 1767 | 1795 | rss_.c:rss.h \ |
| 1768 | 1796 | schema_.c:schema.h \ |
| 1769 | 1797 | search_.c:search.h \ |
| 1770 | 1798 | setup_.c:setup.h \ |
| 1771 | 1799 | sha1_.c:sha1.h \ |
| 1800 | + sha1hard_.c:sha1hard.h \ | |
| 1801 | + sha3_.c:sha3.h \ | |
| 1772 | 1802 | shun_.c:shun.h \ |
| 1773 | 1803 | sitemap_.c:sitemap.h \ |
| 1774 | 1804 | skins_.c:skins.h \ |
| 1775 | 1805 | sqlcmd_.c:sqlcmd.h \ |
| 1776 | 1806 | stash_.c:stash.h \ |
| 1777 | 1807 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -386,10 +386,11 @@ | |
| 386 | fshell_.c \ |
| 387 | fusefs_.c \ |
| 388 | glob_.c \ |
| 389 | graph_.c \ |
| 390 | gzip_.c \ |
| 391 | http_.c \ |
| 392 | http_socket_.c \ |
| 393 | http_ssl_.c \ |
| 394 | http_transport_.c \ |
| 395 | import_.c \ |
| @@ -436,10 +437,12 @@ | |
| 436 | rss_.c \ |
| 437 | schema_.c \ |
| 438 | search_.c \ |
| 439 | setup_.c \ |
| 440 | sha1_.c \ |
| 441 | shun_.c \ |
| 442 | sitemap_.c \ |
| 443 | skins_.c \ |
| 444 | sqlcmd_.c \ |
| 445 | stash_.c \ |
| @@ -560,10 +563,11 @@ | |
| 560 | $(OX)\fshell$O \ |
| 561 | $(OX)\fusefs$O \ |
| 562 | $(OX)\glob$O \ |
| 563 | $(OX)\graph$O \ |
| 564 | $(OX)\gzip$O \ |
| 565 | $(OX)\http$O \ |
| 566 | $(OX)\http_socket$O \ |
| 567 | $(OX)\http_ssl$O \ |
| 568 | $(OX)\http_transport$O \ |
| 569 | $(OX)\import$O \ |
| @@ -610,10 +614,12 @@ | |
| 610 | $(OX)\rss$O \ |
| 611 | $(OX)\schema$O \ |
| 612 | $(OX)\search$O \ |
| 613 | $(OX)\setup$O \ |
| 614 | $(OX)\sha1$O \ |
| 615 | $(OX)\shell$O \ |
| 616 | $(OX)\shun$O \ |
| 617 | $(OX)\sitemap$O \ |
| 618 | $(OX)\skins$O \ |
| 619 | $(OX)\sqlcmd$O \ |
| @@ -743,10 +749,11 @@ | |
| 743 | echo $(OX)\fshell.obj >> $@ |
| 744 | echo $(OX)\fusefs.obj >> $@ |
| 745 | echo $(OX)\glob.obj >> $@ |
| 746 | echo $(OX)\graph.obj >> $@ |
| 747 | echo $(OX)\gzip.obj >> $@ |
| 748 | echo $(OX)\http.obj >> $@ |
| 749 | echo $(OX)\http_socket.obj >> $@ |
| 750 | echo $(OX)\http_ssl.obj >> $@ |
| 751 | echo $(OX)\http_transport.obj >> $@ |
| 752 | echo $(OX)\import.obj >> $@ |
| @@ -793,10 +800,12 @@ | |
| 793 | echo $(OX)\rss.obj >> $@ |
| 794 | echo $(OX)\schema.obj >> $@ |
| 795 | echo $(OX)\search.obj >> $@ |
| 796 | echo $(OX)\setup.obj >> $@ |
| 797 | echo $(OX)\sha1.obj >> $@ |
| 798 | echo $(OX)\shell.obj >> $@ |
| 799 | echo $(OX)\shun.obj >> $@ |
| 800 | echo $(OX)\sitemap.obj >> $@ |
| 801 | echo $(OX)\skins.obj >> $@ |
| 802 | echo $(OX)\sqlcmd.obj >> $@ |
| @@ -1175,10 +1184,16 @@ | |
| 1175 | $(OX)\gzip$O : gzip_.c gzip.h |
| 1176 | $(TCC) /Fo$@ -c gzip_.c |
| 1177 | |
| 1178 | gzip_.c : $(SRCDIR)\gzip.c |
| 1179 | translate$E $** > $@ |
| 1180 | |
| 1181 | $(OX)\http$O : http_.c http.h |
| 1182 | $(TCC) /Fo$@ -c http_.c |
| 1183 | |
| 1184 | http_.c : $(SRCDIR)\http.c |
| @@ -1475,10 +1490,22 @@ | |
| 1475 | $(OX)\sha1$O : sha1_.c sha1.h |
| 1476 | $(TCC) /Fo$@ -c sha1_.c |
| 1477 | |
| 1478 | sha1_.c : $(SRCDIR)\sha1.c |
| 1479 | translate$E $** > $@ |
| 1480 | |
| 1481 | $(OX)\shun$O : shun_.c shun.h |
| 1482 | $(TCC) /Fo$@ -c shun_.c |
| 1483 | |
| 1484 | shun_.c : $(SRCDIR)\shun.c |
| @@ -1717,10 +1744,11 @@ | |
| 1717 | fshell_.c:fshell.h \ |
| 1718 | fusefs_.c:fusefs.h \ |
| 1719 | glob_.c:glob.h \ |
| 1720 | graph_.c:graph.h \ |
| 1721 | gzip_.c:gzip.h \ |
| 1722 | http_.c:http.h \ |
| 1723 | http_socket_.c:http_socket.h \ |
| 1724 | http_ssl_.c:http_ssl.h \ |
| 1725 | http_transport_.c:http_transport.h \ |
| 1726 | import_.c:import.h \ |
| @@ -1767,10 +1795,12 @@ | |
| 1767 | rss_.c:rss.h \ |
| 1768 | schema_.c:schema.h \ |
| 1769 | search_.c:search.h \ |
| 1770 | setup_.c:setup.h \ |
| 1771 | sha1_.c:sha1.h \ |
| 1772 | shun_.c:shun.h \ |
| 1773 | sitemap_.c:sitemap.h \ |
| 1774 | skins_.c:skins.h \ |
| 1775 | sqlcmd_.c:sqlcmd.h \ |
| 1776 | stash_.c:stash.h \ |
| 1777 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -386,10 +386,11 @@ | |
| 386 | fshell_.c \ |
| 387 | fusefs_.c \ |
| 388 | glob_.c \ |
| 389 | graph_.c \ |
| 390 | gzip_.c \ |
| 391 | hname_.c \ |
| 392 | http_.c \ |
| 393 | http_socket_.c \ |
| 394 | http_ssl_.c \ |
| 395 | http_transport_.c \ |
| 396 | import_.c \ |
| @@ -436,10 +437,12 @@ | |
| 437 | rss_.c \ |
| 438 | schema_.c \ |
| 439 | search_.c \ |
| 440 | setup_.c \ |
| 441 | sha1_.c \ |
| 442 | sha1hard_.c \ |
| 443 | sha3_.c \ |
| 444 | shun_.c \ |
| 445 | sitemap_.c \ |
| 446 | skins_.c \ |
| 447 | sqlcmd_.c \ |
| 448 | stash_.c \ |
| @@ -560,10 +563,11 @@ | |
| 563 | $(OX)\fshell$O \ |
| 564 | $(OX)\fusefs$O \ |
| 565 | $(OX)\glob$O \ |
| 566 | $(OX)\graph$O \ |
| 567 | $(OX)\gzip$O \ |
| 568 | $(OX)\hname$O \ |
| 569 | $(OX)\http$O \ |
| 570 | $(OX)\http_socket$O \ |
| 571 | $(OX)\http_ssl$O \ |
| 572 | $(OX)\http_transport$O \ |
| 573 | $(OX)\import$O \ |
| @@ -610,10 +614,12 @@ | |
| 614 | $(OX)\rss$O \ |
| 615 | $(OX)\schema$O \ |
| 616 | $(OX)\search$O \ |
| 617 | $(OX)\setup$O \ |
| 618 | $(OX)\sha1$O \ |
| 619 | $(OX)\sha1hard$O \ |
| 620 | $(OX)\sha3$O \ |
| 621 | $(OX)\shell$O \ |
| 622 | $(OX)\shun$O \ |
| 623 | $(OX)\sitemap$O \ |
| 624 | $(OX)\skins$O \ |
| 625 | $(OX)\sqlcmd$O \ |
| @@ -743,10 +749,11 @@ | |
| 749 | echo $(OX)\fshell.obj >> $@ |
| 750 | echo $(OX)\fusefs.obj >> $@ |
| 751 | echo $(OX)\glob.obj >> $@ |
| 752 | echo $(OX)\graph.obj >> $@ |
| 753 | echo $(OX)\gzip.obj >> $@ |
| 754 | echo $(OX)\hname.obj >> $@ |
| 755 | echo $(OX)\http.obj >> $@ |
| 756 | echo $(OX)\http_socket.obj >> $@ |
| 757 | echo $(OX)\http_ssl.obj >> $@ |
| 758 | echo $(OX)\http_transport.obj >> $@ |
| 759 | echo $(OX)\import.obj >> $@ |
| @@ -793,10 +800,12 @@ | |
| 800 | echo $(OX)\rss.obj >> $@ |
| 801 | echo $(OX)\schema.obj >> $@ |
| 802 | echo $(OX)\search.obj >> $@ |
| 803 | echo $(OX)\setup.obj >> $@ |
| 804 | echo $(OX)\sha1.obj >> $@ |
| 805 | echo $(OX)\sha1hard.obj >> $@ |
| 806 | echo $(OX)\sha3.obj >> $@ |
| 807 | echo $(OX)\shell.obj >> $@ |
| 808 | echo $(OX)\shun.obj >> $@ |
| 809 | echo $(OX)\sitemap.obj >> $@ |
| 810 | echo $(OX)\skins.obj >> $@ |
| 811 | echo $(OX)\sqlcmd.obj >> $@ |
| @@ -1175,10 +1184,16 @@ | |
| 1184 | $(OX)\gzip$O : gzip_.c gzip.h |
| 1185 | $(TCC) /Fo$@ -c gzip_.c |
| 1186 | |
| 1187 | gzip_.c : $(SRCDIR)\gzip.c |
| 1188 | translate$E $** > $@ |
| 1189 | |
| 1190 | $(OX)\hname$O : hname_.c hname.h |
| 1191 | $(TCC) /Fo$@ -c hname_.c |
| 1192 | |
| 1193 | hname_.c : $(SRCDIR)\hname.c |
| 1194 | translate$E $** > $@ |
| 1195 | |
| 1196 | $(OX)\http$O : http_.c http.h |
| 1197 | $(TCC) /Fo$@ -c http_.c |
| 1198 | |
| 1199 | http_.c : $(SRCDIR)\http.c |
| @@ -1475,10 +1490,22 @@ | |
| 1490 | $(OX)\sha1$O : sha1_.c sha1.h |
| 1491 | $(TCC) /Fo$@ -c sha1_.c |
| 1492 | |
| 1493 | sha1_.c : $(SRCDIR)\sha1.c |
| 1494 | translate$E $** > $@ |
| 1495 | |
| 1496 | $(OX)\sha1hard$O : sha1hard_.c sha1hard.h |
| 1497 | $(TCC) /Fo$@ -c sha1hard_.c |
| 1498 | |
| 1499 | sha1hard_.c : $(SRCDIR)\sha1hard.c |
| 1500 | translate$E $** > $@ |
| 1501 | |
| 1502 | $(OX)\sha3$O : sha3_.c sha3.h |
| 1503 | $(TCC) /Fo$@ -c sha3_.c |
| 1504 | |
| 1505 | sha3_.c : $(SRCDIR)\sha3.c |
| 1506 | translate$E $** > $@ |
| 1507 | |
| 1508 | $(OX)\shun$O : shun_.c shun.h |
| 1509 | $(TCC) /Fo$@ -c shun_.c |
| 1510 | |
| 1511 | shun_.c : $(SRCDIR)\shun.c |
| @@ -1717,10 +1744,11 @@ | |
| 1744 | fshell_.c:fshell.h \ |
| 1745 | fusefs_.c:fusefs.h \ |
| 1746 | glob_.c:glob.h \ |
| 1747 | graph_.c:graph.h \ |
| 1748 | gzip_.c:gzip.h \ |
| 1749 | hname_.c:hname.h \ |
| 1750 | http_.c:http.h \ |
| 1751 | http_socket_.c:http_socket.h \ |
| 1752 | http_ssl_.c:http_ssl.h \ |
| 1753 | http_transport_.c:http_transport.h \ |
| 1754 | import_.c:import.h \ |
| @@ -1767,10 +1795,12 @@ | |
| 1795 | rss_.c:rss.h \ |
| 1796 | schema_.c:schema.h \ |
| 1797 | search_.c:search.h \ |
| 1798 | setup_.c:setup.h \ |
| 1799 | sha1_.c:sha1.h \ |
| 1800 | sha1hard_.c:sha1hard.h \ |
| 1801 | sha3_.c:sha3.h \ |
| 1802 | shun_.c:shun.h \ |
| 1803 | sitemap_.c:sitemap.h \ |
| 1804 | skins_.c:skins.h \ |
| 1805 | sqlcmd_.c:sqlcmd.h \ |
| 1806 | stash_.c:stash.h \ |
| 1807 |
+30
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -386,10 +386,11 @@ | ||
| 386 | 386 | fshell_.c \ |
| 387 | 387 | fusefs_.c \ |
| 388 | 388 | glob_.c \ |
| 389 | 389 | graph_.c \ |
| 390 | 390 | gzip_.c \ |
| 391 | + hname_.c \ | |
| 391 | 392 | http_.c \ |
| 392 | 393 | http_socket_.c \ |
| 393 | 394 | http_ssl_.c \ |
| 394 | 395 | http_transport_.c \ |
| 395 | 396 | import_.c \ |
| @@ -436,10 +437,12 @@ | ||
| 436 | 437 | rss_.c \ |
| 437 | 438 | schema_.c \ |
| 438 | 439 | search_.c \ |
| 439 | 440 | setup_.c \ |
| 440 | 441 | sha1_.c \ |
| 442 | + sha1hard_.c \ | |
| 443 | + sha3_.c \ | |
| 441 | 444 | shun_.c \ |
| 442 | 445 | sitemap_.c \ |
| 443 | 446 | skins_.c \ |
| 444 | 447 | sqlcmd_.c \ |
| 445 | 448 | stash_.c \ |
| @@ -560,10 +563,11 @@ | ||
| 560 | 563 | $(OX)\fshell$O \ |
| 561 | 564 | $(OX)\fusefs$O \ |
| 562 | 565 | $(OX)\glob$O \ |
| 563 | 566 | $(OX)\graph$O \ |
| 564 | 567 | $(OX)\gzip$O \ |
| 568 | + $(OX)\hname$O \ | |
| 565 | 569 | $(OX)\http$O \ |
| 566 | 570 | $(OX)\http_socket$O \ |
| 567 | 571 | $(OX)\http_ssl$O \ |
| 568 | 572 | $(OX)\http_transport$O \ |
| 569 | 573 | $(OX)\import$O \ |
| @@ -610,10 +614,12 @@ | ||
| 610 | 614 | $(OX)\rss$O \ |
| 611 | 615 | $(OX)\schema$O \ |
| 612 | 616 | $(OX)\search$O \ |
| 613 | 617 | $(OX)\setup$O \ |
| 614 | 618 | $(OX)\sha1$O \ |
| 619 | + $(OX)\sha1hard$O \ | |
| 620 | + $(OX)\sha3$O \ | |
| 615 | 621 | $(OX)\shell$O \ |
| 616 | 622 | $(OX)\shun$O \ |
| 617 | 623 | $(OX)\sitemap$O \ |
| 618 | 624 | $(OX)\skins$O \ |
| 619 | 625 | $(OX)\sqlcmd$O \ |
| @@ -743,10 +749,11 @@ | ||
| 743 | 749 | echo $(OX)\fshell.obj >> $@ |
| 744 | 750 | echo $(OX)\fusefs.obj >> $@ |
| 745 | 751 | echo $(OX)\glob.obj >> $@ |
| 746 | 752 | echo $(OX)\graph.obj >> $@ |
| 747 | 753 | echo $(OX)\gzip.obj >> $@ |
| 754 | + echo $(OX)\hname.obj >> $@ | |
| 748 | 755 | echo $(OX)\http.obj >> $@ |
| 749 | 756 | echo $(OX)\http_socket.obj >> $@ |
| 750 | 757 | echo $(OX)\http_ssl.obj >> $@ |
| 751 | 758 | echo $(OX)\http_transport.obj >> $@ |
| 752 | 759 | echo $(OX)\import.obj >> $@ |
| @@ -793,10 +800,12 @@ | ||
| 793 | 800 | echo $(OX)\rss.obj >> $@ |
| 794 | 801 | echo $(OX)\schema.obj >> $@ |
| 795 | 802 | echo $(OX)\search.obj >> $@ |
| 796 | 803 | echo $(OX)\setup.obj >> $@ |
| 797 | 804 | echo $(OX)\sha1.obj >> $@ |
| 805 | + echo $(OX)\sha1hard.obj >> $@ | |
| 806 | + echo $(OX)\sha3.obj >> $@ | |
| 798 | 807 | echo $(OX)\shell.obj >> $@ |
| 799 | 808 | echo $(OX)\shun.obj >> $@ |
| 800 | 809 | echo $(OX)\sitemap.obj >> $@ |
| 801 | 810 | echo $(OX)\skins.obj >> $@ |
| 802 | 811 | echo $(OX)\sqlcmd.obj >> $@ |
| @@ -1175,10 +1184,16 @@ | ||
| 1175 | 1184 | $(OX)\gzip$O : gzip_.c gzip.h |
| 1176 | 1185 | $(TCC) /Fo$@ -c gzip_.c |
| 1177 | 1186 | |
| 1178 | 1187 | gzip_.c : $(SRCDIR)\gzip.c |
| 1179 | 1188 | translate$E $** > $@ |
| 1189 | + | |
| 1190 | +$(OX)\hname$O : hname_.c hname.h | |
| 1191 | + $(TCC) /Fo$@ -c hname_.c | |
| 1192 | + | |
| 1193 | +hname_.c : $(SRCDIR)\hname.c | |
| 1194 | + translate$E $** > $@ | |
| 1180 | 1195 | |
| 1181 | 1196 | $(OX)\http$O : http_.c http.h |
| 1182 | 1197 | $(TCC) /Fo$@ -c http_.c |
| 1183 | 1198 | |
| 1184 | 1199 | http_.c : $(SRCDIR)\http.c |
| @@ -1475,10 +1490,22 @@ | ||
| 1475 | 1490 | $(OX)\sha1$O : sha1_.c sha1.h |
| 1476 | 1491 | $(TCC) /Fo$@ -c sha1_.c |
| 1477 | 1492 | |
| 1478 | 1493 | sha1_.c : $(SRCDIR)\sha1.c |
| 1479 | 1494 | translate$E $** > $@ |
| 1495 | + | |
| 1496 | +$(OX)\sha1hard$O : sha1hard_.c sha1hard.h | |
| 1497 | + $(TCC) /Fo$@ -c sha1hard_.c | |
| 1498 | + | |
| 1499 | +sha1hard_.c : $(SRCDIR)\sha1hard.c | |
| 1500 | + translate$E $** > $@ | |
| 1501 | + | |
| 1502 | +$(OX)\sha3$O : sha3_.c sha3.h | |
| 1503 | + $(TCC) /Fo$@ -c sha3_.c | |
| 1504 | + | |
| 1505 | +sha3_.c : $(SRCDIR)\sha3.c | |
| 1506 | + translate$E $** > $@ | |
| 1480 | 1507 | |
| 1481 | 1508 | $(OX)\shun$O : shun_.c shun.h |
| 1482 | 1509 | $(TCC) /Fo$@ -c shun_.c |
| 1483 | 1510 | |
| 1484 | 1511 | shun_.c : $(SRCDIR)\shun.c |
| @@ -1717,10 +1744,11 @@ | ||
| 1717 | 1744 | fshell_.c:fshell.h \ |
| 1718 | 1745 | fusefs_.c:fusefs.h \ |
| 1719 | 1746 | glob_.c:glob.h \ |
| 1720 | 1747 | graph_.c:graph.h \ |
| 1721 | 1748 | gzip_.c:gzip.h \ |
| 1749 | + hname_.c:hname.h \ | |
| 1722 | 1750 | http_.c:http.h \ |
| 1723 | 1751 | http_socket_.c:http_socket.h \ |
| 1724 | 1752 | http_ssl_.c:http_ssl.h \ |
| 1725 | 1753 | http_transport_.c:http_transport.h \ |
| 1726 | 1754 | import_.c:import.h \ |
| @@ -1767,10 +1795,12 @@ | ||
| 1767 | 1795 | rss_.c:rss.h \ |
| 1768 | 1796 | schema_.c:schema.h \ |
| 1769 | 1797 | search_.c:search.h \ |
| 1770 | 1798 | setup_.c:setup.h \ |
| 1771 | 1799 | sha1_.c:sha1.h \ |
| 1800 | + sha1hard_.c:sha1hard.h \ | |
| 1801 | + sha3_.c:sha3.h \ | |
| 1772 | 1802 | shun_.c:shun.h \ |
| 1773 | 1803 | sitemap_.c:sitemap.h \ |
| 1774 | 1804 | skins_.c:skins.h \ |
| 1775 | 1805 | sqlcmd_.c:sqlcmd.h \ |
| 1776 | 1806 | stash_.c:stash.h \ |
| 1777 | 1807 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -386,10 +386,11 @@ | |
| 386 | fshell_.c \ |
| 387 | fusefs_.c \ |
| 388 | glob_.c \ |
| 389 | graph_.c \ |
| 390 | gzip_.c \ |
| 391 | http_.c \ |
| 392 | http_socket_.c \ |
| 393 | http_ssl_.c \ |
| 394 | http_transport_.c \ |
| 395 | import_.c \ |
| @@ -436,10 +437,12 @@ | |
| 436 | rss_.c \ |
| 437 | schema_.c \ |
| 438 | search_.c \ |
| 439 | setup_.c \ |
| 440 | sha1_.c \ |
| 441 | shun_.c \ |
| 442 | sitemap_.c \ |
| 443 | skins_.c \ |
| 444 | sqlcmd_.c \ |
| 445 | stash_.c \ |
| @@ -560,10 +563,11 @@ | |
| 560 | $(OX)\fshell$O \ |
| 561 | $(OX)\fusefs$O \ |
| 562 | $(OX)\glob$O \ |
| 563 | $(OX)\graph$O \ |
| 564 | $(OX)\gzip$O \ |
| 565 | $(OX)\http$O \ |
| 566 | $(OX)\http_socket$O \ |
| 567 | $(OX)\http_ssl$O \ |
| 568 | $(OX)\http_transport$O \ |
| 569 | $(OX)\import$O \ |
| @@ -610,10 +614,12 @@ | |
| 610 | $(OX)\rss$O \ |
| 611 | $(OX)\schema$O \ |
| 612 | $(OX)\search$O \ |
| 613 | $(OX)\setup$O \ |
| 614 | $(OX)\sha1$O \ |
| 615 | $(OX)\shell$O \ |
| 616 | $(OX)\shun$O \ |
| 617 | $(OX)\sitemap$O \ |
| 618 | $(OX)\skins$O \ |
| 619 | $(OX)\sqlcmd$O \ |
| @@ -743,10 +749,11 @@ | |
| 743 | echo $(OX)\fshell.obj >> $@ |
| 744 | echo $(OX)\fusefs.obj >> $@ |
| 745 | echo $(OX)\glob.obj >> $@ |
| 746 | echo $(OX)\graph.obj >> $@ |
| 747 | echo $(OX)\gzip.obj >> $@ |
| 748 | echo $(OX)\http.obj >> $@ |
| 749 | echo $(OX)\http_socket.obj >> $@ |
| 750 | echo $(OX)\http_ssl.obj >> $@ |
| 751 | echo $(OX)\http_transport.obj >> $@ |
| 752 | echo $(OX)\import.obj >> $@ |
| @@ -793,10 +800,12 @@ | |
| 793 | echo $(OX)\rss.obj >> $@ |
| 794 | echo $(OX)\schema.obj >> $@ |
| 795 | echo $(OX)\search.obj >> $@ |
| 796 | echo $(OX)\setup.obj >> $@ |
| 797 | echo $(OX)\sha1.obj >> $@ |
| 798 | echo $(OX)\shell.obj >> $@ |
| 799 | echo $(OX)\shun.obj >> $@ |
| 800 | echo $(OX)\sitemap.obj >> $@ |
| 801 | echo $(OX)\skins.obj >> $@ |
| 802 | echo $(OX)\sqlcmd.obj >> $@ |
| @@ -1175,10 +1184,16 @@ | |
| 1175 | $(OX)\gzip$O : gzip_.c gzip.h |
| 1176 | $(TCC) /Fo$@ -c gzip_.c |
| 1177 | |
| 1178 | gzip_.c : $(SRCDIR)\gzip.c |
| 1179 | translate$E $** > $@ |
| 1180 | |
| 1181 | $(OX)\http$O : http_.c http.h |
| 1182 | $(TCC) /Fo$@ -c http_.c |
| 1183 | |
| 1184 | http_.c : $(SRCDIR)\http.c |
| @@ -1475,10 +1490,22 @@ | |
| 1475 | $(OX)\sha1$O : sha1_.c sha1.h |
| 1476 | $(TCC) /Fo$@ -c sha1_.c |
| 1477 | |
| 1478 | sha1_.c : $(SRCDIR)\sha1.c |
| 1479 | translate$E $** > $@ |
| 1480 | |
| 1481 | $(OX)\shun$O : shun_.c shun.h |
| 1482 | $(TCC) /Fo$@ -c shun_.c |
| 1483 | |
| 1484 | shun_.c : $(SRCDIR)\shun.c |
| @@ -1717,10 +1744,11 @@ | |
| 1717 | fshell_.c:fshell.h \ |
| 1718 | fusefs_.c:fusefs.h \ |
| 1719 | glob_.c:glob.h \ |
| 1720 | graph_.c:graph.h \ |
| 1721 | gzip_.c:gzip.h \ |
| 1722 | http_.c:http.h \ |
| 1723 | http_socket_.c:http_socket.h \ |
| 1724 | http_ssl_.c:http_ssl.h \ |
| 1725 | http_transport_.c:http_transport.h \ |
| 1726 | import_.c:import.h \ |
| @@ -1767,10 +1795,12 @@ | |
| 1767 | rss_.c:rss.h \ |
| 1768 | schema_.c:schema.h \ |
| 1769 | search_.c:search.h \ |
| 1770 | setup_.c:setup.h \ |
| 1771 | sha1_.c:sha1.h \ |
| 1772 | shun_.c:shun.h \ |
| 1773 | sitemap_.c:sitemap.h \ |
| 1774 | skins_.c:skins.h \ |
| 1775 | sqlcmd_.c:sqlcmd.h \ |
| 1776 | stash_.c:stash.h \ |
| 1777 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -386,10 +386,11 @@ | |
| 386 | fshell_.c \ |
| 387 | fusefs_.c \ |
| 388 | glob_.c \ |
| 389 | graph_.c \ |
| 390 | gzip_.c \ |
| 391 | hname_.c \ |
| 392 | http_.c \ |
| 393 | http_socket_.c \ |
| 394 | http_ssl_.c \ |
| 395 | http_transport_.c \ |
| 396 | import_.c \ |
| @@ -436,10 +437,12 @@ | |
| 437 | rss_.c \ |
| 438 | schema_.c \ |
| 439 | search_.c \ |
| 440 | setup_.c \ |
| 441 | sha1_.c \ |
| 442 | sha1hard_.c \ |
| 443 | sha3_.c \ |
| 444 | shun_.c \ |
| 445 | sitemap_.c \ |
| 446 | skins_.c \ |
| 447 | sqlcmd_.c \ |
| 448 | stash_.c \ |
| @@ -560,10 +563,11 @@ | |
| 563 | $(OX)\fshell$O \ |
| 564 | $(OX)\fusefs$O \ |
| 565 | $(OX)\glob$O \ |
| 566 | $(OX)\graph$O \ |
| 567 | $(OX)\gzip$O \ |
| 568 | $(OX)\hname$O \ |
| 569 | $(OX)\http$O \ |
| 570 | $(OX)\http_socket$O \ |
| 571 | $(OX)\http_ssl$O \ |
| 572 | $(OX)\http_transport$O \ |
| 573 | $(OX)\import$O \ |
| @@ -610,10 +614,12 @@ | |
| 614 | $(OX)\rss$O \ |
| 615 | $(OX)\schema$O \ |
| 616 | $(OX)\search$O \ |
| 617 | $(OX)\setup$O \ |
| 618 | $(OX)\sha1$O \ |
| 619 | $(OX)\sha1hard$O \ |
| 620 | $(OX)\sha3$O \ |
| 621 | $(OX)\shell$O \ |
| 622 | $(OX)\shun$O \ |
| 623 | $(OX)\sitemap$O \ |
| 624 | $(OX)\skins$O \ |
| 625 | $(OX)\sqlcmd$O \ |
| @@ -743,10 +749,11 @@ | |
| 749 | echo $(OX)\fshell.obj >> $@ |
| 750 | echo $(OX)\fusefs.obj >> $@ |
| 751 | echo $(OX)\glob.obj >> $@ |
| 752 | echo $(OX)\graph.obj >> $@ |
| 753 | echo $(OX)\gzip.obj >> $@ |
| 754 | echo $(OX)\hname.obj >> $@ |
| 755 | echo $(OX)\http.obj >> $@ |
| 756 | echo $(OX)\http_socket.obj >> $@ |
| 757 | echo $(OX)\http_ssl.obj >> $@ |
| 758 | echo $(OX)\http_transport.obj >> $@ |
| 759 | echo $(OX)\import.obj >> $@ |
| @@ -793,10 +800,12 @@ | |
| 800 | echo $(OX)\rss.obj >> $@ |
| 801 | echo $(OX)\schema.obj >> $@ |
| 802 | echo $(OX)\search.obj >> $@ |
| 803 | echo $(OX)\setup.obj >> $@ |
| 804 | echo $(OX)\sha1.obj >> $@ |
| 805 | echo $(OX)\sha1hard.obj >> $@ |
| 806 | echo $(OX)\sha3.obj >> $@ |
| 807 | echo $(OX)\shell.obj >> $@ |
| 808 | echo $(OX)\shun.obj >> $@ |
| 809 | echo $(OX)\sitemap.obj >> $@ |
| 810 | echo $(OX)\skins.obj >> $@ |
| 811 | echo $(OX)\sqlcmd.obj >> $@ |
| @@ -1175,10 +1184,16 @@ | |
| 1184 | $(OX)\gzip$O : gzip_.c gzip.h |
| 1185 | $(TCC) /Fo$@ -c gzip_.c |
| 1186 | |
| 1187 | gzip_.c : $(SRCDIR)\gzip.c |
| 1188 | translate$E $** > $@ |
| 1189 | |
| 1190 | $(OX)\hname$O : hname_.c hname.h |
| 1191 | $(TCC) /Fo$@ -c hname_.c |
| 1192 | |
| 1193 | hname_.c : $(SRCDIR)\hname.c |
| 1194 | translate$E $** > $@ |
| 1195 | |
| 1196 | $(OX)\http$O : http_.c http.h |
| 1197 | $(TCC) /Fo$@ -c http_.c |
| 1198 | |
| 1199 | http_.c : $(SRCDIR)\http.c |
| @@ -1475,10 +1490,22 @@ | |
| 1490 | $(OX)\sha1$O : sha1_.c sha1.h |
| 1491 | $(TCC) /Fo$@ -c sha1_.c |
| 1492 | |
| 1493 | sha1_.c : $(SRCDIR)\sha1.c |
| 1494 | translate$E $** > $@ |
| 1495 | |
| 1496 | $(OX)\sha1hard$O : sha1hard_.c sha1hard.h |
| 1497 | $(TCC) /Fo$@ -c sha1hard_.c |
| 1498 | |
| 1499 | sha1hard_.c : $(SRCDIR)\sha1hard.c |
| 1500 | translate$E $** > $@ |
| 1501 | |
| 1502 | $(OX)\sha3$O : sha3_.c sha3.h |
| 1503 | $(TCC) /Fo$@ -c sha3_.c |
| 1504 | |
| 1505 | sha3_.c : $(SRCDIR)\sha3.c |
| 1506 | translate$E $** > $@ |
| 1507 | |
| 1508 | $(OX)\shun$O : shun_.c shun.h |
| 1509 | $(TCC) /Fo$@ -c shun_.c |
| 1510 | |
| 1511 | shun_.c : $(SRCDIR)\shun.c |
| @@ -1717,10 +1744,11 @@ | |
| 1744 | fshell_.c:fshell.h \ |
| 1745 | fusefs_.c:fusefs.h \ |
| 1746 | glob_.c:glob.h \ |
| 1747 | graph_.c:graph.h \ |
| 1748 | gzip_.c:gzip.h \ |
| 1749 | hname_.c:hname.h \ |
| 1750 | http_.c:http.h \ |
| 1751 | http_socket_.c:http_socket.h \ |
| 1752 | http_ssl_.c:http_ssl.h \ |
| 1753 | http_transport_.c:http_transport.h \ |
| 1754 | import_.c:import.h \ |
| @@ -1767,10 +1795,12 @@ | |
| 1795 | rss_.c:rss.h \ |
| 1796 | schema_.c:schema.h \ |
| 1797 | search_.c:search.h \ |
| 1798 | setup_.c:setup.h \ |
| 1799 | sha1_.c:sha1.h \ |
| 1800 | sha1hard_.c:sha1hard.h \ |
| 1801 | sha3_.c:sha3.h \ |
| 1802 | shun_.c:shun.h \ |
| 1803 | sitemap_.c:sitemap.h \ |
| 1804 | skins_.c:skins.h \ |
| 1805 | sqlcmd_.c:sqlcmd.h \ |
| 1806 | stash_.c:stash.h \ |
| 1807 |
+3
-3
| --- www/branching.wiki | ||
| +++ www/branching.wiki | ||
| @@ -10,14 +10,14 @@ | ||
| 10 | 10 | Figure 1 |
| 11 | 11 | </td></tr></table> |
| 12 | 12 | |
| 13 | 13 | Each circle represents a check-in. For the sake of clarity, the check-ins |
| 14 | 14 | are given small consecutive numbers. In a real system, of course, the |
| 15 | -check-in numbers would be 40-character SHA1 hashes since it is not possible | |
| 15 | +check-in numbers would be long hexadecimal hashes since it is not possible | |
| 16 | 16 | to allocate collision-free sequential numbers in a distributed system. |
| 17 | 17 | But as sequential numbers are easier to read, we will substitute them for |
| 18 | -the 40-character SHA1 hashes in this document. | |
| 18 | +the long hashes in this document. | |
| 19 | 19 | |
| 20 | 20 | The arrows in figure 1 show the evolution of a project. The initial |
| 21 | 21 | check-in is 1. Check-in 2 is derived from 1. In other words, check-in 2 |
| 22 | 22 | was created by making edits to check-in 1 and then committing those edits. |
| 23 | 23 | We say that 2 is a <i>child</i> of 1 |
| @@ -193,11 +193,11 @@ | ||
| 193 | 193 | figure 5, that initial check-in is check-in 1. The <b>branch</b> tag |
| 194 | 194 | tells (by its value) what branch the check-in is a member of. |
| 195 | 195 | The default branch is called "trunk." All tags that begin with "<b>sym-</b>" |
| 196 | 196 | are symbolic name tags. When a symbolic name tag is attached to a |
| 197 | 197 | check-in, that allows you to refer to that check-in by its symbolic |
| 198 | -name rather than by its 40-character SHA1 hash name. When a symbolic name | |
| 198 | +name rather than by its hexadecimal hash name. When a symbolic name | |
| 199 | 199 | tag propagates (as does the <b>sym-trunk</b> tag) then referring to that |
| 200 | 200 | name is the same as referring to the most recent check-in with that name. |
| 201 | 201 | Thus the two tags on check-in 1 cause all descendants to be in the |
| 202 | 202 | "trunk" branch and to have the symbolic name "trunk." |
| 203 | 203 | |
| 204 | 204 |
| --- www/branching.wiki | |
| +++ www/branching.wiki | |
| @@ -10,14 +10,14 @@ | |
| 10 | Figure 1 |
| 11 | </td></tr></table> |
| 12 | |
| 13 | Each circle represents a check-in. For the sake of clarity, the check-ins |
| 14 | are given small consecutive numbers. In a real system, of course, the |
| 15 | check-in numbers would be 40-character SHA1 hashes since it is not possible |
| 16 | to allocate collision-free sequential numbers in a distributed system. |
| 17 | But as sequential numbers are easier to read, we will substitute them for |
| 18 | the 40-character SHA1 hashes in this document. |
| 19 | |
| 20 | The arrows in figure 1 show the evolution of a project. The initial |
| 21 | check-in is 1. Check-in 2 is derived from 1. In other words, check-in 2 |
| 22 | was created by making edits to check-in 1 and then committing those edits. |
| 23 | We say that 2 is a <i>child</i> of 1 |
| @@ -193,11 +193,11 @@ | |
| 193 | figure 5, that initial check-in is check-in 1. The <b>branch</b> tag |
| 194 | tells (by its value) what branch the check-in is a member of. |
| 195 | The default branch is called "trunk." All tags that begin with "<b>sym-</b>" |
| 196 | are symbolic name tags. When a symbolic name tag is attached to a |
| 197 | check-in, that allows you to refer to that check-in by its symbolic |
| 198 | name rather than by its 40-character SHA1 hash name. When a symbolic name |
| 199 | tag propagates (as does the <b>sym-trunk</b> tag) then referring to that |
| 200 | name is the same as referring to the most recent check-in with that name. |
| 201 | Thus the two tags on check-in 1 cause all descendants to be in the |
| 202 | "trunk" branch and to have the symbolic name "trunk." |
| 203 | |
| 204 |
| --- www/branching.wiki | |
| +++ www/branching.wiki | |
| @@ -10,14 +10,14 @@ | |
| 10 | Figure 1 |
| 11 | </td></tr></table> |
| 12 | |
| 13 | Each circle represents a check-in. For the sake of clarity, the check-ins |
| 14 | are given small consecutive numbers. In a real system, of course, the |
| 15 | check-in numbers would be long hexadecimal hashes since it is not possible |
| 16 | to allocate collision-free sequential numbers in a distributed system. |
| 17 | But as sequential numbers are easier to read, we will substitute them for |
| 18 | the long hashes in this document. |
| 19 | |
| 20 | The arrows in figure 1 show the evolution of a project. The initial |
| 21 | check-in is 1. Check-in 2 is derived from 1. In other words, check-in 2 |
| 22 | was created by making edits to check-in 1 and then committing those edits. |
| 23 | We say that 2 is a <i>child</i> of 1 |
| @@ -193,11 +193,11 @@ | |
| 193 | figure 5, that initial check-in is check-in 1. The <b>branch</b> tag |
| 194 | tells (by its value) what branch the check-in is a member of. |
| 195 | The default branch is called "trunk." All tags that begin with "<b>sym-</b>" |
| 196 | are symbolic name tags. When a symbolic name tag is attached to a |
| 197 | check-in, that allows you to refer to that check-in by its symbolic |
| 198 | name rather than by its hexadecimal hash name. When a symbolic name |
| 199 | tag propagates (as does the <b>sym-trunk</b> tag) then referring to that |
| 200 | name is the same as referring to the most recent check-in with that name. |
| 201 | Thus the two tags on check-in 1 cause all descendants to be in the |
| 202 | "trunk" branch and to have the symbolic name "trunk." |
| 203 | |
| 204 |
+7
-12
| --- www/build.wiki | ||
| +++ www/build.wiki | ||
| @@ -1,16 +1,14 @@ | ||
| 1 | 1 | <title>Compiling and Installing Fossil</title> |
| 2 | 2 | |
| 3 | 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | 4 | |
| 5 | -<p>Released versions of fossil come with | |
| 6 | -<a href="/uv/download.html">pre-compiled binaries and | |
| 7 | -a source archive</a> for that release. You can thus skip the following if you | |
| 8 | -want to run or build a release version of fossil. Just download | |
| 9 | -the appropriate package from the <a href="/uv/download.html">downloads page</a> | |
| 5 | +<p>[/uv/download.html|Pre-compiled binaries] are available for recent | |
| 6 | +releases. Just download | |
| 7 | +the appropriate executable for your platform | |
| 10 | 8 | and put it on your $PATH. |
| 11 | -To uninstall, simply delete the binary. | |
| 9 | +To uninstall, simply delete the executable. | |
| 12 | 10 | To upgrade from an older release, just overwrite the older binary with |
| 13 | 11 | the newer one.</p> |
| 14 | 12 | |
| 15 | 13 | <h2>0.1 Executive Summary</h2> |
| 16 | 14 | |
| @@ -29,20 +27,17 @@ | ||
| 29 | 27 | |
| 30 | 28 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | 29 | containing a snapshot of the <em>latest</em> version directly from |
| 32 | 30 | Fossil's own fossil repository. Additionally, source archives of |
| 33 | 31 | <em>released</em> versions of |
| 34 | -fossil are available from the <a href="/uv/download.html">downloads page</a>. | |
| 32 | +fossil are available from the [/uv/download.html|downloads page]. | |
| 35 | 33 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | 34 | |
| 37 | 35 | <ol> |
| 38 | -<li><p>Point your web browser to | |
| 39 | -<a href="http://www.fossil-scm.org/"> | |
| 40 | -http://www.fossil-scm.org/</a>.</p></li> | |
| 36 | +<li><p>Point your web browser to [https://www.fossil-scm.org/]</li> | |
| 41 | 37 | |
| 42 | -<li><p>Click on the | |
| 43 | -<a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> | |
| 38 | +<li><p>Click on the [/timeline|Timeline] | |
| 44 | 39 | link at the top of the page.</p></li> |
| 45 | 40 | |
| 46 | 41 | <li><p>Select a version of of Fossil you want to download. The latest |
| 47 | 42 | version on the trunk branch is usually a good choice. Click on its |
| 48 | 43 | link.</p></li> |
| 49 | 44 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -1,16 +1,14 @@ | |
| 1 | <title>Compiling and Installing Fossil</title> |
| 2 | |
| 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | |
| 5 | <p>Released versions of fossil come with |
| 6 | <a href="/uv/download.html">pre-compiled binaries and |
| 7 | a source archive</a> for that release. You can thus skip the following if you |
| 8 | want to run or build a release version of fossil. Just download |
| 9 | the appropriate package from the <a href="/uv/download.html">downloads page</a> |
| 10 | and put it on your $PATH. |
| 11 | To uninstall, simply delete the binary. |
| 12 | To upgrade from an older release, just overwrite the older binary with |
| 13 | the newer one.</p> |
| 14 | |
| 15 | <h2>0.1 Executive Summary</h2> |
| 16 | |
| @@ -29,20 +27,17 @@ | |
| 29 | |
| 30 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | containing a snapshot of the <em>latest</em> version directly from |
| 32 | Fossil's own fossil repository. Additionally, source archives of |
| 33 | <em>released</em> versions of |
| 34 | fossil are available from the <a href="/uv/download.html">downloads page</a>. |
| 35 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | |
| 37 | <ol> |
| 38 | <li><p>Point your web browser to |
| 39 | <a href="http://www.fossil-scm.org/"> |
| 40 | http://www.fossil-scm.org/</a>.</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. The latest |
| 47 | version on the trunk branch is usually a good choice. Click on its |
| 48 | link.</p></li> |
| 49 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -1,16 +1,14 @@ | |
| 1 | <title>Compiling and Installing Fossil</title> |
| 2 | |
| 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | |
| 5 | <p>[/uv/download.html|Pre-compiled binaries] are available for recent |
| 6 | releases. Just download |
| 7 | the appropriate executable for your platform |
| 8 | and put it on your $PATH. |
| 9 | To uninstall, simply delete the executable. |
| 10 | To upgrade from an older release, just overwrite the older binary with |
| 11 | the newer one.</p> |
| 12 | |
| 13 | <h2>0.1 Executive Summary</h2> |
| 14 | |
| @@ -29,20 +27,17 @@ | |
| 27 | |
| 28 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 29 | containing a snapshot of the <em>latest</em> version directly from |
| 30 | Fossil's own fossil repository. Additionally, source archives of |
| 31 | <em>released</em> versions of |
| 32 | fossil are available from the [/uv/download.html|downloads page]. |
| 33 | To obtain a development version of fossil, follow these steps:</p> |
| 34 | |
| 35 | <ol> |
| 36 | <li><p>Point your web browser to [https://www.fossil-scm.org/]</li> |
| 37 | |
| 38 | <li><p>Click on the [/timeline|Timeline] |
| 39 | link at the top of the page.</p></li> |
| 40 | |
| 41 | <li><p>Select a version of of Fossil you want to download. The latest |
| 42 | version on the trunk branch is usually a good choice. Click on its |
| 43 | link.</p></li> |
| 44 |
+7
-12
| --- www/build.wiki | ||
| +++ www/build.wiki | ||
| @@ -1,16 +1,14 @@ | ||
| 1 | 1 | <title>Compiling and Installing Fossil</title> |
| 2 | 2 | |
| 3 | 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | 4 | |
| 5 | -<p>Released versions of fossil come with | |
| 6 | -<a href="/uv/download.html">pre-compiled binaries and | |
| 7 | -a source archive</a> for that release. You can thus skip the following if you | |
| 8 | -want to run or build a release version of fossil. Just download | |
| 9 | -the appropriate package from the <a href="/uv/download.html">downloads page</a> | |
| 5 | +<p>[/uv/download.html|Pre-compiled binaries] are available for recent | |
| 6 | +releases. Just download | |
| 7 | +the appropriate executable for your platform | |
| 10 | 8 | and put it on your $PATH. |
| 11 | -To uninstall, simply delete the binary. | |
| 9 | +To uninstall, simply delete the executable. | |
| 12 | 10 | To upgrade from an older release, just overwrite the older binary with |
| 13 | 11 | the newer one.</p> |
| 14 | 12 | |
| 15 | 13 | <h2>0.1 Executive Summary</h2> |
| 16 | 14 | |
| @@ -29,20 +27,17 @@ | ||
| 29 | 27 | |
| 30 | 28 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | 29 | containing a snapshot of the <em>latest</em> version directly from |
| 32 | 30 | Fossil's own fossil repository. Additionally, source archives of |
| 33 | 31 | <em>released</em> versions of |
| 34 | -fossil are available from the <a href="/uv/download.html">downloads page</a>. | |
| 32 | +fossil are available from the [/uv/download.html|downloads page]. | |
| 35 | 33 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | 34 | |
| 37 | 35 | <ol> |
| 38 | -<li><p>Point your web browser to | |
| 39 | -<a href="http://www.fossil-scm.org/"> | |
| 40 | -http://www.fossil-scm.org/</a>.</p></li> | |
| 36 | +<li><p>Point your web browser to [https://www.fossil-scm.org/]</li> | |
| 41 | 37 | |
| 42 | -<li><p>Click on the | |
| 43 | -<a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> | |
| 38 | +<li><p>Click on the [/timeline|Timeline] | |
| 44 | 39 | link at the top of the page.</p></li> |
| 45 | 40 | |
| 46 | 41 | <li><p>Select a version of of Fossil you want to download. The latest |
| 47 | 42 | version on the trunk branch is usually a good choice. Click on its |
| 48 | 43 | link.</p></li> |
| 49 | 44 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -1,16 +1,14 @@ | |
| 1 | <title>Compiling and Installing Fossil</title> |
| 2 | |
| 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | |
| 5 | <p>Released versions of fossil come with |
| 6 | <a href="/uv/download.html">pre-compiled binaries and |
| 7 | a source archive</a> for that release. You can thus skip the following if you |
| 8 | want to run or build a release version of fossil. Just download |
| 9 | the appropriate package from the <a href="/uv/download.html">downloads page</a> |
| 10 | and put it on your $PATH. |
| 11 | To uninstall, simply delete the binary. |
| 12 | To upgrade from an older release, just overwrite the older binary with |
| 13 | the newer one.</p> |
| 14 | |
| 15 | <h2>0.1 Executive Summary</h2> |
| 16 | |
| @@ -29,20 +27,17 @@ | |
| 29 | |
| 30 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | containing a snapshot of the <em>latest</em> version directly from |
| 32 | Fossil's own fossil repository. Additionally, source archives of |
| 33 | <em>released</em> versions of |
| 34 | fossil are available from the <a href="/uv/download.html">downloads page</a>. |
| 35 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | |
| 37 | <ol> |
| 38 | <li><p>Point your web browser to |
| 39 | <a href="http://www.fossil-scm.org/"> |
| 40 | http://www.fossil-scm.org/</a>.</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. The latest |
| 47 | version on the trunk branch is usually a good choice. Click on its |
| 48 | link.</p></li> |
| 49 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -1,16 +1,14 @@ | |
| 1 | <title>Compiling and Installing Fossil</title> |
| 2 | |
| 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | |
| 5 | <p>[/uv/download.html|Pre-compiled binaries] are available for recent |
| 6 | releases. Just download |
| 7 | the appropriate executable for your platform |
| 8 | and put it on your $PATH. |
| 9 | To uninstall, simply delete the executable. |
| 10 | To upgrade from an older release, just overwrite the older binary with |
| 11 | the newer one.</p> |
| 12 | |
| 13 | <h2>0.1 Executive Summary</h2> |
| 14 | |
| @@ -29,20 +27,17 @@ | |
| 27 | |
| 28 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 29 | containing a snapshot of the <em>latest</em> version directly from |
| 30 | Fossil's own fossil repository. Additionally, source archives of |
| 31 | <em>released</em> versions of |
| 32 | fossil are available from the [/uv/download.html|downloads page]. |
| 33 | To obtain a development version of fossil, follow these steps:</p> |
| 34 | |
| 35 | <ol> |
| 36 | <li><p>Point your web browser to [https://www.fossil-scm.org/]</li> |
| 37 | |
| 38 | <li><p>Click on the [/timeline|Timeline] |
| 39 | link at the top of the page.</p></li> |
| 40 | |
| 41 | <li><p>Select a version of of Fossil you want to download. The latest |
| 42 | version on the trunk branch is usually a good choice. Click on its |
| 43 | link.</p></li> |
| 44 |
+20
-2
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,10 +1,28 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | -<a name='v1_38'></a> | |
| 4 | -<h2>Changes for Version 1.38 (2017-??-??)</h2> | |
| 3 | +<a name='v2_1'></a> | |
| 4 | +<h2>Changes for Version 2.1 (2017-03-10)</h2> | |
| 5 | + | |
| 6 | + * Add support for [./hashpolicy.wiki|hash policies] that control which | |
| 7 | + of the Hardened-SHA1 or SHA3-256 algorithms is used to name new | |
| 8 | + artifacts. | |
| 9 | + * Add the "gshow" and "gcat" subcommands to [/help?cmd=stash|fossil stash]. | |
| 10 | + * Add the [/help?cmd=/juvlist|/juvlist] web page and use it to construct | |
| 11 | + the [/uv/download.html|Download Page] of the Fossil self-hosting website | |
| 12 | + using Ajax. | |
| 13 | + | |
| 14 | +<a name='v2_0'></a> | |
| 15 | +<h2>Changes for Version 2.0 (2017-03-03)</h2> | |
| 5 | 16 | |
| 17 | + * Use the | |
| 18 | + [https://github.com/cr-marcstevens/sha1collisiondetection|hardened SHA1] | |
| 19 | + implemenation by Marc Stevens and Dan Shumow. | |
| 20 | + * Add the ability to read and understand | |
| 21 | + [./fileformat.wiki#names|artifact names] that are based on SHA3-256 | |
| 22 | + rather than SHA1, but do not actually generate any such names. | |
| 23 | + * Added the [/help?cmd=sha3sum|sha3sum] command. | |
| 6 | 24 | * Update the built-in SQLite to version 3.17.0. |
| 7 | 25 | |
| 8 | 26 | <a name='v1_37'></a> |
| 9 | 27 | <h2>Changes for Version 1.37 (2017-01-16)</h2> |
| 10 | 28 | |
| 11 | 29 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,10 +1,28 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v1_38'></a> |
| 4 | <h2>Changes for Version 1.38 (2017-??-??)</h2> |
| 5 | |
| 6 | * Update the built-in SQLite to version 3.17.0. |
| 7 | |
| 8 | <a name='v1_37'></a> |
| 9 | <h2>Changes for Version 1.37 (2017-01-16)</h2> |
| 10 | |
| 11 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,10 +1,28 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v2_1'></a> |
| 4 | <h2>Changes for Version 2.1 (2017-03-10)</h2> |
| 5 | |
| 6 | * Add support for [./hashpolicy.wiki|hash policies] that control which |
| 7 | of the Hardened-SHA1 or SHA3-256 algorithms is used to name new |
| 8 | artifacts. |
| 9 | * Add the "gshow" and "gcat" subcommands to [/help?cmd=stash|fossil stash]. |
| 10 | * Add the [/help?cmd=/juvlist|/juvlist] web page and use it to construct |
| 11 | the [/uv/download.html|Download Page] of the Fossil self-hosting website |
| 12 | using Ajax. |
| 13 | |
| 14 | <a name='v2_0'></a> |
| 15 | <h2>Changes for Version 2.0 (2017-03-03)</h2> |
| 16 | |
| 17 | * Use the |
| 18 | [https://github.com/cr-marcstevens/sha1collisiondetection|hardened SHA1] |
| 19 | implemenation by Marc Stevens and Dan Shumow. |
| 20 | * Add the ability to read and understand |
| 21 | [./fileformat.wiki#names|artifact names] that are based on SHA3-256 |
| 22 | rather than SHA1, but do not actually generate any such names. |
| 23 | * Added the [/help?cmd=sha3sum|sha3sum] command. |
| 24 | * Update the built-in SQLite to version 3.17.0. |
| 25 | |
| 26 | <a name='v1_37'></a> |
| 27 | <h2>Changes for Version 1.37 (2017-01-16)</h2> |
| 28 | |
| 29 |
+4
-4
| --- www/checkin_names.wiki | ||
| +++ www/checkin_names.wiki | ||
| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | <tr><td> |
| 5 | 5 | <h3>Executive Summary</h3> |
| 6 | 6 | <p>A check-in can be identified using any of the following |
| 7 | 7 | names: |
| 8 | 8 | <ul> |
| 9 | -<li> SHA1 hash prefix | |
| 9 | +<li> Cryptographic hash prefix | |
| 10 | 10 | <li> Tag or branchname |
| 11 | 11 | <li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i> |
| 12 | 12 | <li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i> |
| 13 | 13 | <li> <b>root :</b> <i>branchname</i> |
| 14 | 14 | <li> Special names: |
| @@ -44,19 +44,19 @@ | ||
| 44 | 44 | Fossil provides a variety of ways to specify a check-in. This |
| 45 | 45 | document describes the various methods. |
| 46 | 46 | |
| 47 | 47 | <h2>Canonical Check-in Name</h2> |
| 48 | 48 | |
| 49 | -The canonical name of a check-in is the SHA1 hash of its | |
| 50 | -[./fileformat.wiki#manifest | manifest] expressed as a 40-character | |
| 49 | +The canonical name of a check-in is the hash of its | |
| 50 | +[./fileformat.wiki#manifest | manifest] expressed as a 40-or-more character | |
| 51 | 51 | lowercase hexadecimal number. For example: |
| 52 | 52 | |
| 53 | 53 | <blockquote><pre> |
| 54 | 54 | fossil info e5a734a19a9826973e1d073b49dc2a16aa2308f9 |
| 55 | 55 | </pre></blockquote> |
| 56 | 56 | |
| 57 | -The full 40-character SHA1 hash is unwieldy to remember and type, though, | |
| 57 | +The full 40+ character hash is unwieldy to remember and type, though, | |
| 58 | 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | 60 | characters long. Hence the following commands all |
| 61 | 61 | accomplish the same thing as the above: |
| 62 | 62 | |
| 63 | 63 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -4,11 +4,11 @@ | |
| 4 | <tr><td> |
| 5 | <h3>Executive Summary</h3> |
| 6 | <p>A check-in can be identified using any of the following |
| 7 | names: |
| 8 | <ul> |
| 9 | <li> SHA1 hash prefix |
| 10 | <li> Tag or branchname |
| 11 | <li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i> |
| 12 | <li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i> |
| 13 | <li> <b>root :</b> <i>branchname</i> |
| 14 | <li> Special names: |
| @@ -44,19 +44,19 @@ | |
| 44 | Fossil provides a variety of ways to specify a check-in. This |
| 45 | document describes the various methods. |
| 46 | |
| 47 | <h2>Canonical Check-in Name</h2> |
| 48 | |
| 49 | The canonical name of a check-in is the SHA1 hash of its |
| 50 | [./fileformat.wiki#manifest | manifest] expressed as a 40-character |
| 51 | lowercase hexadecimal number. For example: |
| 52 | |
| 53 | <blockquote><pre> |
| 54 | fossil info e5a734a19a9826973e1d073b49dc2a16aa2308f9 |
| 55 | </pre></blockquote> |
| 56 | |
| 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | characters long. Hence the following commands all |
| 61 | accomplish the same thing as the above: |
| 62 | |
| 63 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -4,11 +4,11 @@ | |
| 4 | <tr><td> |
| 5 | <h3>Executive Summary</h3> |
| 6 | <p>A check-in can be identified using any of the following |
| 7 | names: |
| 8 | <ul> |
| 9 | <li> Cryptographic hash prefix |
| 10 | <li> Tag or branchname |
| 11 | <li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i> |
| 12 | <li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i> |
| 13 | <li> <b>root :</b> <i>branchname</i> |
| 14 | <li> Special names: |
| @@ -44,19 +44,19 @@ | |
| 44 | Fossil provides a variety of ways to specify a check-in. This |
| 45 | document describes the various methods. |
| 46 | |
| 47 | <h2>Canonical Check-in Name</h2> |
| 48 | |
| 49 | The canonical name of a check-in is the hash of its |
| 50 | [./fileformat.wiki#manifest | manifest] expressed as a 40-or-more character |
| 51 | lowercase hexadecimal number. For example: |
| 52 | |
| 53 | <blockquote><pre> |
| 54 | fossil info e5a734a19a9826973e1d073b49dc2a16aa2308f9 |
| 55 | </pre></blockquote> |
| 56 | |
| 57 | The full 40+ character hash is unwieldy to remember and type, though, |
| 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | characters long. Hence the following commands all |
| 61 | accomplish the same thing as the above: |
| 62 | |
| 63 |
+1
-1
| --- www/customskin.md | ||
| +++ www/customskin.md | ||
| @@ -177,11 +177,11 @@ | ||
| 177 | 177 | |
| 178 | 178 | * **csrf_token** - A token used to prevent cross-site request forgery. |
| 179 | 179 | |
| 180 | 180 | * **release_version** - The release version of Fossil. Ex: "1.31" |
| 181 | 181 | |
| 182 | - * **manifest_version** - A prefix on the SHA1 check-in hash of the | |
| 182 | + * **manifest_version** - A prefix on the check-in hash of the | |
| 183 | 183 | specific version of fossil that is running. Ex: "\[47bb6432a1\]" |
| 184 | 184 | |
| 185 | 185 | * **manifest_date** - The date of the source-code check-in for the |
| 186 | 186 | version of fossil that is running. |
| 187 | 187 | |
| 188 | 188 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -177,11 +177,11 @@ | |
| 177 | |
| 178 | * **csrf_token** - A token used to prevent cross-site request forgery. |
| 179 | |
| 180 | * **release_version** - The release version of Fossil. Ex: "1.31" |
| 181 | |
| 182 | * **manifest_version** - A prefix on the SHA1 check-in hash of the |
| 183 | specific version of fossil that is running. Ex: "\[47bb6432a1\]" |
| 184 | |
| 185 | * **manifest_date** - The date of the source-code check-in for the |
| 186 | version of fossil that is running. |
| 187 | |
| 188 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -177,11 +177,11 @@ | |
| 177 | |
| 178 | * **csrf_token** - A token used to prevent cross-site request forgery. |
| 179 | |
| 180 | * **release_version** - The release version of Fossil. Ex: "1.31" |
| 181 | |
| 182 | * **manifest_version** - A prefix on the check-in hash of the |
| 183 | specific version of fossil that is running. Ex: "\[47bb6432a1\]" |
| 184 | |
| 185 | * **manifest_date** - The date of the source-code check-in for the |
| 186 | version of fossil that is running. |
| 187 | |
| 188 |
+79
-84
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -9,14 +9,19 @@ | ||
| 9 | 9 | searchable, and extensible by people not yet born. |
| 10 | 10 | |
| 11 | 11 | The global state of a fossil repository is an unordered |
| 12 | 12 | set of <i>artifacts</i>. |
| 13 | 13 | An artifact might be a source code file, the text of a wiki page, |
| 14 | -part of a trouble ticket, or one of several special control artifacts | |
| 15 | -used to show the relationships between other artifacts within the | |
| 16 | -project. Each artifact is normally represented on disk as a separate | |
| 17 | -file. Artifacts can be text or binary. | |
| 14 | +part of a trouble ticket, a description of a check-in including all | |
| 15 | +the files in that check-in with the check-in comment and so forth. | |
| 16 | +Artifacts are broadly grouped into two types: content artifacts and | |
| 17 | +structural artifacts. Content artifacts are the raw project source-code | |
| 18 | +files that are checked into the repository. Structural artifacts have | |
| 19 | +special formatting rules and are used to show the relationships between | |
| 20 | +other artifacts in the repository. It is possible for an artifact to | |
| 21 | +be both a structure artifact and a content artifact, though this is | |
| 22 | +rare. Artifacts can be text or binary. | |
| 18 | 23 | |
| 19 | 24 | In addition to the global state, |
| 20 | 25 | each fossil repository also contains local state. |
| 21 | 26 | The local state consists of web-page formatting |
| 22 | 27 | preferences, authorized users, ticket display and reporting formats, |
| @@ -27,18 +32,40 @@ | ||
| 27 | 32 | with the global state. |
| 28 | 33 | The local state is not composed of artifacts and is not intended to be enduring. |
| 29 | 34 | This document is concerned with global state only. Local state is only |
| 30 | 35 | mentioned here in order to distinguish it from global state. |
| 31 | 36 | |
| 32 | -Each artifact in the repository is named by its SHA1 hash. | |
| 33 | -No prefixes or meta information is added to an artifact before | |
| 34 | -its hash is computed. The name of an artifact in the repository | |
| 35 | -is exactly the same SHA1 hash that is computed by sha1sum | |
| 36 | -on the file as it exists in your source tree.</p> | |
| 37 | - | |
| 38 | -Some artifacts have a particular format which gives them special | |
| 39 | -meaning to fossil. Fossil recognizes: | |
| 37 | +<a name="names"></a> | |
| 38 | +<h2>1.0 Artifact Names</h2> | |
| 39 | + | |
| 40 | +Each artifact in the repository is named by a hash of its content. | |
| 41 | +No prefixes, suffixes, or other information is added to an artifact before | |
| 42 | +the hash is computed. The artifact name is just the (lower-case | |
| 43 | +hexadecimal) hash of the raw artifact. | |
| 44 | + | |
| 45 | +Fossil currently computes artifact names using either SHA1 or SHA3-256. It | |
| 46 | +is relatively easy to add new algorithms in the future, but there are no | |
| 47 | +plans to do so at this time. | |
| 48 | + | |
| 49 | +When referring to artifacts in using tty commands or webpage URLs, it is | |
| 50 | +sufficient to specify a unique prefix for the artifact name. If the input | |
| 51 | +prefix is not unique, Fossil will show an error. Within a structural | |
| 52 | +artifact, however, all references to other artifacts must be the complete | |
| 53 | +hash. | |
| 54 | + | |
| 55 | +Prior to Fossil version 2.0, all names were formed from the SHA1 hash of | |
| 56 | +the artifact. The key innovation in Fossil 2.0 was adding support for | |
| 57 | +alternative hash algorithms. | |
| 58 | + | |
| 59 | +<a name="structural"></a> | |
| 60 | +<h2>2.0 Structural Artifacts</h2> | |
| 61 | + | |
| 62 | +A structural artifact is an artifact with a particular format | |
| 63 | +that is used to define the relationships between other artifacts in the | |
| 64 | +repository. | |
| 65 | +Fossil recognizes the following kinds of structural | |
| 66 | +artifacts: | |
| 40 | 67 | |
| 41 | 68 | <ul> |
| 42 | 69 | <li> [#manifest | Manifests] </li> |
| 43 | 70 | <li> [#cluster | Clusters] </li> |
| 44 | 71 | <li> [#ctrl | Control Artifacts] </li> |
| @@ -46,66 +73,55 @@ | ||
| 46 | 73 | <li> [#tktchng | Ticket Changes] </li> |
| 47 | 74 | <li> [#attachment | Attachments] </li> |
| 48 | 75 | <li> [#event | TechNotes] </li> |
| 49 | 76 | </ul> |
| 50 | 77 | |
| 51 | -These seven artifact types are described in the following sections. | |
| 78 | +These seven structural artifact types are described in subsections below. | |
| 52 | 79 | |
| 53 | -In the current implementation (as of 2009-01-25) the artifacts that | |
| 80 | +Structural artifacts are ASCII text. The artifact may be PGP clearsigned. | |
| 81 | +After removal of the PGP clearsign header and suffix (if any) a structural | |
| 82 | +artifact consists of one or more "cards" separated by a single newline | |
| 83 | +(ASCII: 0x0a) character. Each card begins with a single | |
| 84 | +character "card type". Zero or more arguments may follow | |
| 85 | +the card type. All arguments are separated from each other | |
| 86 | +and from the card-type character by a single space | |
| 87 | +character. There is no surplus white space between arguments | |
| 88 | +and no leading or trailing whitespace except for the newline | |
| 89 | +character that acts as the card separator. All cards must be in strict | |
| 90 | +lexicographical order. There may not be any duplicate cards. | |
| 91 | + | |
| 92 | +In the current implementation (as of 2017-02-27) the artifacts that | |
| 54 | 93 | make up a fossil repository are stored as delta- and zlib-compressed |
| 55 | 94 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | 95 | is an implementation detail and might change in a future release. For |
| 57 | 96 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | 97 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | 98 | is intended to be enduring. The specifics of how artifacts are stored on |
| 60 | 99 | disk, though stable, is not intended to live as long as the |
| 61 | 100 | artifact format. |
| 62 | 101 | |
| 63 | -All of the artifacts can be extracted from a Fossil repository using | |
| 64 | -the "fossil deconstruct" command. | |
| 65 | - | |
| 66 | 102 | <a name="manifest"></a> |
| 67 | -<h2>1.0 The Manifest</h2> | |
| 103 | +<h3>2.1 The Manifest</h3> | |
| 68 | 104 | |
| 69 | -A manifest defines a check-in or version of the project | |
| 70 | -source tree. The manifest contains a list of artifacts for | |
| 105 | +A manifest defines a check-in. | |
| 106 | +A manifest contains a list of artifacts for | |
| 71 | 107 | each file in the project and the corresponding filenames, as |
| 72 | -well as information such as parent check-ins, the name of the | |
| 108 | +well as information such as parent check-ins, the username of the | |
| 73 | 109 | programmer who created the check-in, the date and time when |
| 74 | 110 | the check-in was created, and any check-in comments associated |
| 75 | 111 | with the check-in. |
| 76 | 112 | |
| 77 | -Any artifact in the repository that follows the syntactic rules | |
| 78 | -of a manifest is a manifest. Note that a manifest can | |
| 79 | -be both a real manifest and also a content file, though this | |
| 80 | -is rare. | |
| 81 | - | |
| 82 | -A manifest is a text file. Newline characters | |
| 83 | -(ASCII 0x0a) separate the file into "cards". | |
| 84 | -Each card begins with a single | |
| 85 | -character "card type". Zero or more arguments may follow | |
| 86 | -the card type. All arguments are separated from each other | |
| 87 | -and from the card-type character by a single space | |
| 88 | -character. There is no surplus white space between arguments | |
| 89 | -and no leading or trailing whitespace except for the newline | |
| 90 | -character that acts as the card separator. | |
| 91 | - | |
| 92 | -All cards of the manifest occur in strict sorted lexicographical order. | |
| 93 | -No card may be duplicated. | |
| 94 | -The entire manifest may be PGP clear-signed, but otherwise it | |
| 95 | -may contain no additional text or data beyond what is described here. | |
| 96 | - | |
| 97 | 113 | Allowed cards in the manifest are as follows: |
| 98 | 114 | |
| 99 | 115 | <blockquote> |
| 100 | 116 | <b>B</b> <i>baseline-manifest</i><br> |
| 101 | 117 | <b>C</b> <i>checkin-comment</i><br> |
| 102 | 118 | <b>D</b> <i>time-and-date-stamp</i><br> |
| 103 | -<b>F</b> <i>filename</i> ?<i>SHA1-hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br> | |
| 119 | +<b>F</b> <i>filename</i> ?<i>hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br> | |
| 104 | 120 | <b>N</b> <i>mimetype</i><br> |
| 105 | -<b>P</b> <i>SHA1-hash</i>+<br> | |
| 106 | -<b>Q</b> (<b>+</b>|<b>-</b>)<i>SHA1-hash</i> ?<i>SHA1-hash</i>?<br> | |
| 121 | +<b>P</b> <i>artifact-hash</i>+<br> | |
| 122 | +<b>Q</b> (<b>+</b>|<b>-</b>)<i>artifact-hash</i> ?<i>artifact-hash</i>?<br> | |
| 107 | 123 | <b>R</b> <i>repository-checksum</i><br> |
| 108 | 124 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br> |
| 109 | 125 | <b>U</b> <i>user-login</i><br> |
| 110 | 126 | <b>Z</b> <i>manifest-checksum</i> |
| 111 | 127 | </blockquote> |
| @@ -145,11 +161,11 @@ | ||
| 145 | 161 | check-in relative to the root of the project file hierarchy. No ".." |
| 146 | 162 | or "." directories are allowed within the filename. Space characters |
| 147 | 163 | are escaped as in C-card comment text. Backslash characters and |
| 148 | 164 | newlines are not allowed within filenames. The directory separator |
| 149 | 165 | character is a forward slash (ASCII 0x2F). The second argument to the |
| 150 | -F-card is the full 40-character lower-case hexadecimal SHA1 hash of | |
| 166 | +F-card is the lower-case hexadecimal artifact hash of | |
| 151 | 167 | the content artifact. The second argument is required for baseline |
| 152 | 168 | manifests but is optional for delta manifests. When the second |
| 153 | 169 | argument to the F-card is omitted, it means that the file has been |
| 154 | 170 | deleted relative to the baseline (files removed in baseline manifests |
| 155 | 171 | versions are <em>not</em> added as F-cards). The optional 3rd argument |
| @@ -167,14 +183,14 @@ | ||
| 167 | 183 | is used. |
| 168 | 184 | |
| 169 | 185 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | 186 | The P-card has a varying number of arguments that |
| 171 | 187 | define other manifests from which the current manifest |
| 172 | -is derived. Each argument is a 40-character lowercase | |
| 173 | -hexadecimal SHA1 of a predecessor manifest. All arguments | |
| 188 | +is derived. Each argument is a lowercase | |
| 189 | +hexadecimal artifact hash of a predecessor manifest. All arguments | |
| 174 | 190 | to the P-card must be unique within that card. |
| 175 | -The first argument is the SHA1 of the direct ancestor of the manifest. | |
| 191 | +The first argument is the artifact hash of the direct ancestor of the manifest. | |
| 176 | 192 | Other arguments define manifests with which the first was |
| 177 | 193 | merged to yield the current manifest. Most manifests have |
| 178 | 194 | a P-card with a single argument. The first manifest in the |
| 179 | 195 | project has no ancestors and thus has no P-card or (depending |
| 180 | 196 | on the Fossil version) an empty P-card (no arguments). |
| @@ -229,41 +245,27 @@ | ||
| 229 | 245 | check-in comment argument to the C-card. |
| 230 | 246 | |
| 231 | 247 | A manifest must have a single Z-card as its last line. The argument |
| 232 | 248 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | 249 | of all prior lines of the manifest up to and including the newline |
| 234 | -character that immediately precedes the "Z". The Z-card is | |
| 250 | +character that immediately precedes the "Z", excluding any PGP | |
| 251 | +clear-signing prefix. The Z-card is | |
| 235 | 252 | a sanity check to prove that the manifest is well-formed and |
| 236 | 253 | consistent. |
| 237 | 254 | |
| 238 | 255 | A sample manifest from Fossil itself can be seen |
| 239 | 256 | [/artifact/28987096ac | here]. |
| 240 | 257 | |
| 241 | 258 | <a name="cluster"></a> |
| 242 | -<h2>2.0 Clusters</h2> | |
| 259 | +<h3>2.2 Clusters</h3> | |
| 243 | 260 | |
| 244 | 261 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | 262 | Clusters are used during repository synchronization to help |
| 246 | 263 | reduce network traffic. As such, clusters are an optimization and |
| 247 | 264 | may be removed from a repository without loss or damage to the |
| 248 | 265 | underlying project code. |
| 249 | 266 | |
| 250 | -Clusters follow a syntax that is very similar to manifests. | |
| 251 | -A cluster is a line-oriented text file. Newline characters | |
| 252 | -(ASCII 0x0a) separate the artifact into cards. Each card begins with a single | |
| 253 | -character "card type". Zero or more arguments may follow | |
| 254 | -the card type. All arguments are separated from each other | |
| 255 | -and from the card-type character by a single space | |
| 256 | -character. There is no surplus white space between arguments | |
| 257 | -and no leading or trailing whitespace except for the newline | |
| 258 | -character that acts as the card separator. | |
| 259 | -All cards of a cluster occur in strict sorted lexicographical order. | |
| 260 | -No card may be duplicated. | |
| 261 | -The cluster may not contain additional text or data beyond | |
| 262 | -what is described here. | |
| 263 | -Unlike manifests, clusters are never PGP signed. | |
| 264 | - | |
| 265 | 267 | Allowed cards in the cluster are as follows: |
| 266 | 268 | |
| 267 | 269 | <blockquote> |
| 268 | 270 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | 271 | <b>Z</b> <i>checksum</i> |
| @@ -278,20 +280,14 @@ | ||
| 278 | 280 | |
| 279 | 281 | An example cluster from Fossil can be seen |
| 280 | 282 | [/artifact/d03dbdd73a2a8 | here]. |
| 281 | 283 | |
| 282 | 284 | <a name="ctrl"></a> |
| 283 | -<h2>3.0 Control Artifacts</h2> | |
| 285 | +<h3>2.3 Control Artifacts</h3> | |
| 284 | 286 | |
| 285 | 287 | Control artifacts are used to assign properties to other artifacts |
| 286 | -within the repository. The basic format of a control artifact is | |
| 287 | -the same as a manifest or cluster. A control artifact is a text | |
| 288 | -file divided into cards by newline characters. Each card has a | |
| 289 | -single-character card type followed by arguments. Spaces separate | |
| 290 | -the card type and the arguments. No surplus whitespace is allowed. | |
| 291 | -All cards must occur in strict lexicographical order. | |
| 292 | - | |
| 288 | +within the repository. | |
| 293 | 289 | Allowed cards in a control artifact are as follows: |
| 294 | 290 | |
| 295 | 291 | <blockquote> |
| 296 | 292 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 297 | 293 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br /> |
| @@ -338,16 +334,15 @@ | ||
| 338 | 334 | |
| 339 | 335 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | 336 | |
| 341 | 337 | |
| 342 | 338 | <a name="wikichng"></a> |
| 343 | -<h2>4.0 Wiki Pages</h2> | |
| 339 | +<h3>2.4 Wiki Pages</h3> | |
| 344 | 340 | |
| 345 | -A wiki page is an artifact with a format similar to manifests, | |
| 346 | -clusters, and control artifacts. The artifact is divided into | |
| 347 | -cards by newline characters. The format of each card is as in | |
| 348 | -manifests, clusters, and control artifacts. Wiki artifacts accept | |
| 341 | +A wiki artifact defines a single version of a | |
| 342 | +single wiki page. | |
| 343 | +Wiki artifacts accept | |
| 349 | 344 | the following card types: |
| 350 | 345 | |
| 351 | 346 | <blockquote> |
| 352 | 347 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 353 | 348 | <b>L</b> <i>wiki-title</i><br /> |
| @@ -375,11 +370,11 @@ | ||
| 375 | 370 | |
| 376 | 371 | An example wiki artifact can be seen |
| 377 | 372 | [/artifact?name=7b2f5fd0e0&txt=1 | here]. |
| 378 | 373 | |
| 379 | 374 | <a name="tktchng"></a> |
| 380 | -<h2>5.0 Ticket Changes</h2> | |
| 375 | +<h3>2.5 Ticket Changes</h3> | |
| 381 | 376 | |
| 382 | 377 | A ticket-change artifact represents a change to a trouble ticket. |
| 383 | 378 | The following cards are allowed on a ticket change artifact: |
| 384 | 379 | |
| 385 | 380 | <blockquote> |
| @@ -421,11 +416,11 @@ | ||
| 421 | 416 | |
| 422 | 417 | An example ticket-change artifact can be seen |
| 423 | 418 | [/artifact/91f1ec6af053 | here]. |
| 424 | 419 | |
| 425 | 420 | <a name="attachment"></a> |
| 426 | -<h2>6.0 Attachments</h2> | |
| 421 | +<h3>2.6 Attachments</h3> | |
| 427 | 422 | |
| 428 | 423 | An attachment artifact associates some other artifact that is the |
| 429 | 424 | attachment (the source artifact) with a ticket or wiki page or |
| 430 | 425 | technical note to which |
| 431 | 426 | the attachment is connected (the target artifact). |
| @@ -463,11 +458,11 @@ | ||
| 463 | 458 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 464 | 459 | The Z card is required. |
| 465 | 460 | |
| 466 | 461 | |
| 467 | 462 | <a name="event"></a> |
| 468 | -<h2>7.0 Technical Notes</h2> | |
| 463 | +<h3>2.7 Technical Notes</h3> | |
| 469 | 464 | |
| 470 | 465 | A technical note or "technote" artifact (formerly known as an "event" artifact) |
| 471 | 466 | associates a timeline comment and a page of text |
| 472 | 467 | (similar to a wiki page) with a point in time. Technotes can be used |
| 473 | 468 | to record project milestones, release notes, blog entries, process |
| @@ -532,11 +527,11 @@ | ||
| 532 | 527 | |
| 533 | 528 | The Z card is the required checksum over the rest of the artifact. |
| 534 | 529 | |
| 535 | 530 | |
| 536 | 531 | <a name="summary"></a> |
| 537 | -<h2>8.0 Card Summary</h2> | |
| 532 | +<h2>3.0 Card Summary</h2> | |
| 538 | 533 | |
| 539 | 534 | The following table summarizes the various kinds of cards that appear |
| 540 | 535 | on Fossil artifacts. A blank entry means that combination of card and |
| 541 | 536 | artifact is not legal. A number or range of numbers indicates the number |
| 542 | 537 | of times a card may (or must) appear in the corresponding artifact type. |
| @@ -739,16 +734,16 @@ | ||
| 739 | 734 | </tr> |
| 740 | 735 | </table> |
| 741 | 736 | |
| 742 | 737 | |
| 743 | 738 | <a name="addenda"></a> |
| 744 | -<h2>9.0 Addenda</h2> | |
| 739 | +<h2>4.0 Addenda</h2> | |
| 745 | 740 | |
| 746 | 741 | This section contains additional information which may be useful when |
| 747 | 742 | implementing algorithms described above. |
| 748 | 743 | |
| 749 | -<h3>R Card Hash Calculation</h3> | |
| 744 | +<h3>4.1 R-Card Hash Calculation</h3> | |
| 750 | 745 | |
| 751 | 746 | Given a manifest file named <tt>MF</tt>, the following Bash shell code |
| 752 | 747 | demonstrates how to compute the value of the R card in that manifest. |
| 753 | 748 | This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are |
| 754 | 749 | shell input and other lines are output. This demonstration assumes that the |
| 755 | 750 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -9,14 +9,19 @@ | |
| 9 | searchable, and extensible by people not yet born. |
| 10 | |
| 11 | The global state of a fossil repository is an unordered |
| 12 | set of <i>artifacts</i>. |
| 13 | An artifact might be a source code file, the text of a wiki page, |
| 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | used to show the relationships between other artifacts within the |
| 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | file. Artifacts can be text or binary. |
| 18 | |
| 19 | In addition to the global state, |
| 20 | each fossil repository also contains local state. |
| 21 | The local state consists of web-page formatting |
| 22 | preferences, authorized users, ticket display and reporting formats, |
| @@ -27,18 +32,40 @@ | |
| 27 | with the global state. |
| 28 | The local state is not composed of artifacts and is not intended to be enduring. |
| 29 | This document is concerned with global state only. Local state is only |
| 30 | mentioned here in order to distinguish it from global state. |
| 31 | |
| 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | No prefixes or meta information is added to an artifact before |
| 34 | its hash is computed. The name of an artifact in the repository |
| 35 | is exactly the same SHA1 hash that is computed by sha1sum |
| 36 | on the file as it exists in your source tree.</p> |
| 37 | |
| 38 | Some artifacts have a particular format which gives them special |
| 39 | meaning to fossil. Fossil recognizes: |
| 40 | |
| 41 | <ul> |
| 42 | <li> [#manifest | Manifests] </li> |
| 43 | <li> [#cluster | Clusters] </li> |
| 44 | <li> [#ctrl | Control Artifacts] </li> |
| @@ -46,66 +73,55 @@ | |
| 46 | <li> [#tktchng | Ticket Changes] </li> |
| 47 | <li> [#attachment | Attachments] </li> |
| 48 | <li> [#event | TechNotes] </li> |
| 49 | </ul> |
| 50 | |
| 51 | These seven artifact types are described in the following sections. |
| 52 | |
| 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | make up a fossil repository are stored as delta- and zlib-compressed |
| 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | is an implementation detail and might change in a future release. For |
| 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| 60 | disk, though stable, is not intended to live as long as the |
| 61 | artifact format. |
| 62 | |
| 63 | All of the artifacts can be extracted from a Fossil repository using |
| 64 | the "fossil deconstruct" command. |
| 65 | |
| 66 | <a name="manifest"></a> |
| 67 | <h2>1.0 The Manifest</h2> |
| 68 | |
| 69 | A manifest defines a check-in or version of the project |
| 70 | source tree. The manifest contains a list of artifacts for |
| 71 | each file in the project and the corresponding filenames, as |
| 72 | well as information such as parent check-ins, the name of the |
| 73 | programmer who created the check-in, the date and time when |
| 74 | the check-in was created, and any check-in comments associated |
| 75 | with the check-in. |
| 76 | |
| 77 | Any artifact in the repository that follows the syntactic rules |
| 78 | of a manifest is a manifest. Note that a manifest can |
| 79 | be both a real manifest and also a content file, though this |
| 80 | is rare. |
| 81 | |
| 82 | A manifest is a text file. Newline characters |
| 83 | (ASCII 0x0a) separate the file into "cards". |
| 84 | Each card begins with a single |
| 85 | character "card type". Zero or more arguments may follow |
| 86 | the card type. All arguments are separated from each other |
| 87 | and from the card-type character by a single space |
| 88 | character. There is no surplus white space between arguments |
| 89 | and no leading or trailing whitespace except for the newline |
| 90 | character that acts as the card separator. |
| 91 | |
| 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | No card may be duplicated. |
| 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| 95 | may contain no additional text or data beyond what is described here. |
| 96 | |
| 97 | Allowed cards in the manifest are as follows: |
| 98 | |
| 99 | <blockquote> |
| 100 | <b>B</b> <i>baseline-manifest</i><br> |
| 101 | <b>C</b> <i>checkin-comment</i><br> |
| 102 | <b>D</b> <i>time-and-date-stamp</i><br> |
| 103 | <b>F</b> <i>filename</i> ?<i>SHA1-hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br> |
| 104 | <b>N</b> <i>mimetype</i><br> |
| 105 | <b>P</b> <i>SHA1-hash</i>+<br> |
| 106 | <b>Q</b> (<b>+</b>|<b>-</b>)<i>SHA1-hash</i> ?<i>SHA1-hash</i>?<br> |
| 107 | <b>R</b> <i>repository-checksum</i><br> |
| 108 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br> |
| 109 | <b>U</b> <i>user-login</i><br> |
| 110 | <b>Z</b> <i>manifest-checksum</i> |
| 111 | </blockquote> |
| @@ -145,11 +161,11 @@ | |
| 145 | check-in relative to the root of the project file hierarchy. No ".." |
| 146 | or "." directories are allowed within the filename. Space characters |
| 147 | are escaped as in C-card comment text. Backslash characters and |
| 148 | newlines are not allowed within filenames. The directory separator |
| 149 | character is a forward slash (ASCII 0x2F). The second argument to the |
| 150 | F-card is the full 40-character lower-case hexadecimal SHA1 hash of |
| 151 | the content artifact. The second argument is required for baseline |
| 152 | manifests but is optional for delta manifests. When the second |
| 153 | argument to the F-card is omitted, it means that the file has been |
| 154 | deleted relative to the baseline (files removed in baseline manifests |
| 155 | versions are <em>not</em> added as F-cards). The optional 3rd argument |
| @@ -167,14 +183,14 @@ | |
| 167 | is used. |
| 168 | |
| 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | The P-card has a varying number of arguments that |
| 171 | define other manifests from which the current manifest |
| 172 | is derived. Each argument is a 40-character lowercase |
| 173 | hexadecimal SHA1 of a predecessor manifest. All arguments |
| 174 | to the P-card must be unique within that card. |
| 175 | The first argument is the SHA1 of the direct ancestor of the manifest. |
| 176 | Other arguments define manifests with which the first was |
| 177 | merged to yield the current manifest. Most manifests have |
| 178 | a P-card with a single argument. The first manifest in the |
| 179 | project has no ancestors and thus has no P-card or (depending |
| 180 | on the Fossil version) an empty P-card (no arguments). |
| @@ -229,41 +245,27 @@ | |
| 229 | check-in comment argument to the C-card. |
| 230 | |
| 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | of all prior lines of the manifest up to and including the newline |
| 234 | character that immediately precedes the "Z". The Z-card is |
| 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | consistent. |
| 237 | |
| 238 | A sample manifest from Fossil itself can be seen |
| 239 | [/artifact/28987096ac | here]. |
| 240 | |
| 241 | <a name="cluster"></a> |
| 242 | <h2>2.0 Clusters</h2> |
| 243 | |
| 244 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | Clusters are used during repository synchronization to help |
| 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | may be removed from a repository without loss or damage to the |
| 248 | underlying project code. |
| 249 | |
| 250 | Clusters follow a syntax that is very similar to manifests. |
| 251 | A cluster is a line-oriented text file. Newline characters |
| 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | character "card type". Zero or more arguments may follow |
| 254 | the card type. All arguments are separated from each other |
| 255 | and from the card-type character by a single space |
| 256 | character. There is no surplus white space between arguments |
| 257 | and no leading or trailing whitespace except for the newline |
| 258 | character that acts as the card separator. |
| 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | No card may be duplicated. |
| 261 | The cluster may not contain additional text or data beyond |
| 262 | what is described here. |
| 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | |
| 265 | Allowed cards in the cluster are as follows: |
| 266 | |
| 267 | <blockquote> |
| 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | <b>Z</b> <i>checksum</i> |
| @@ -278,20 +280,14 @@ | |
| 278 | |
| 279 | An example cluster from Fossil can be seen |
| 280 | [/artifact/d03dbdd73a2a8 | here]. |
| 281 | |
| 282 | <a name="ctrl"></a> |
| 283 | <h2>3.0 Control Artifacts</h2> |
| 284 | |
| 285 | Control artifacts are used to assign properties to other artifacts |
| 286 | within the repository. The basic format of a control artifact is |
| 287 | the same as a manifest or cluster. A control artifact is a text |
| 288 | file divided into cards by newline characters. Each card has a |
| 289 | single-character card type followed by arguments. Spaces separate |
| 290 | the card type and the arguments. No surplus whitespace is allowed. |
| 291 | All cards must occur in strict lexicographical order. |
| 292 | |
| 293 | Allowed cards in a control artifact are as follows: |
| 294 | |
| 295 | <blockquote> |
| 296 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 297 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br /> |
| @@ -338,16 +334,15 @@ | |
| 338 | |
| 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | |
| 341 | |
| 342 | <a name="wikichng"></a> |
| 343 | <h2>4.0 Wiki Pages</h2> |
| 344 | |
| 345 | A wiki page is an artifact with a format similar to manifests, |
| 346 | clusters, and control artifacts. The artifact is divided into |
| 347 | cards by newline characters. The format of each card is as in |
| 348 | manifests, clusters, and control artifacts. Wiki artifacts accept |
| 349 | the following card types: |
| 350 | |
| 351 | <blockquote> |
| 352 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 353 | <b>L</b> <i>wiki-title</i><br /> |
| @@ -375,11 +370,11 @@ | |
| 375 | |
| 376 | An example wiki artifact can be seen |
| 377 | [/artifact?name=7b2f5fd0e0&txt=1 | here]. |
| 378 | |
| 379 | <a name="tktchng"></a> |
| 380 | <h2>5.0 Ticket Changes</h2> |
| 381 | |
| 382 | A ticket-change artifact represents a change to a trouble ticket. |
| 383 | The following cards are allowed on a ticket change artifact: |
| 384 | |
| 385 | <blockquote> |
| @@ -421,11 +416,11 @@ | |
| 421 | |
| 422 | An example ticket-change artifact can be seen |
| 423 | [/artifact/91f1ec6af053 | here]. |
| 424 | |
| 425 | <a name="attachment"></a> |
| 426 | <h2>6.0 Attachments</h2> |
| 427 | |
| 428 | An attachment artifact associates some other artifact that is the |
| 429 | attachment (the source artifact) with a ticket or wiki page or |
| 430 | technical note to which |
| 431 | the attachment is connected (the target artifact). |
| @@ -463,11 +458,11 @@ | |
| 463 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 464 | The Z card is required. |
| 465 | |
| 466 | |
| 467 | <a name="event"></a> |
| 468 | <h2>7.0 Technical Notes</h2> |
| 469 | |
| 470 | A technical note or "technote" artifact (formerly known as an "event" artifact) |
| 471 | associates a timeline comment and a page of text |
| 472 | (similar to a wiki page) with a point in time. Technotes can be used |
| 473 | to record project milestones, release notes, blog entries, process |
| @@ -532,11 +527,11 @@ | |
| 532 | |
| 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | |
| 535 | |
| 536 | <a name="summary"></a> |
| 537 | <h2>8.0 Card Summary</h2> |
| 538 | |
| 539 | The following table summarizes the various kinds of cards that appear |
| 540 | on Fossil artifacts. A blank entry means that combination of card and |
| 541 | artifact is not legal. A number or range of numbers indicates the number |
| 542 | of times a card may (or must) appear in the corresponding artifact type. |
| @@ -739,16 +734,16 @@ | |
| 739 | </tr> |
| 740 | </table> |
| 741 | |
| 742 | |
| 743 | <a name="addenda"></a> |
| 744 | <h2>9.0 Addenda</h2> |
| 745 | |
| 746 | This section contains additional information which may be useful when |
| 747 | implementing algorithms described above. |
| 748 | |
| 749 | <h3>R Card Hash Calculation</h3> |
| 750 | |
| 751 | Given a manifest file named <tt>MF</tt>, the following Bash shell code |
| 752 | demonstrates how to compute the value of the R card in that manifest. |
| 753 | This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are |
| 754 | shell input and other lines are output. This demonstration assumes that the |
| 755 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -9,14 +9,19 @@ | |
| 9 | searchable, and extensible by people not yet born. |
| 10 | |
| 11 | The global state of a fossil repository is an unordered |
| 12 | set of <i>artifacts</i>. |
| 13 | An artifact might be a source code file, the text of a wiki page, |
| 14 | part of a trouble ticket, a description of a check-in including all |
| 15 | the files in that check-in with the check-in comment and so forth. |
| 16 | Artifacts are broadly grouped into two types: content artifacts and |
| 17 | structural artifacts. Content artifacts are the raw project source-code |
| 18 | files that are checked into the repository. Structural artifacts have |
| 19 | special formatting rules and are used to show the relationships between |
| 20 | other artifacts in the repository. It is possible for an artifact to |
| 21 | be both a structure artifact and a content artifact, though this is |
| 22 | rare. Artifacts can be text or binary. |
| 23 | |
| 24 | In addition to the global state, |
| 25 | each fossil repository also contains local state. |
| 26 | The local state consists of web-page formatting |
| 27 | preferences, authorized users, ticket display and reporting formats, |
| @@ -27,18 +32,40 @@ | |
| 32 | with the global state. |
| 33 | The local state is not composed of artifacts and is not intended to be enduring. |
| 34 | This document is concerned with global state only. Local state is only |
| 35 | mentioned here in order to distinguish it from global state. |
| 36 | |
| 37 | <a name="names"></a> |
| 38 | <h2>1.0 Artifact Names</h2> |
| 39 | |
| 40 | Each artifact in the repository is named by a hash of its content. |
| 41 | No prefixes, suffixes, or other information is added to an artifact before |
| 42 | the hash is computed. The artifact name is just the (lower-case |
| 43 | hexadecimal) hash of the raw artifact. |
| 44 | |
| 45 | Fossil currently computes artifact names using either SHA1 or SHA3-256. It |
| 46 | is relatively easy to add new algorithms in the future, but there are no |
| 47 | plans to do so at this time. |
| 48 | |
| 49 | When referring to artifacts in using tty commands or webpage URLs, it is |
| 50 | sufficient to specify a unique prefix for the artifact name. If the input |
| 51 | prefix is not unique, Fossil will show an error. Within a structural |
| 52 | artifact, however, all references to other artifacts must be the complete |
| 53 | hash. |
| 54 | |
| 55 | Prior to Fossil version 2.0, all names were formed from the SHA1 hash of |
| 56 | the artifact. The key innovation in Fossil 2.0 was adding support for |
| 57 | alternative hash algorithms. |
| 58 | |
| 59 | <a name="structural"></a> |
| 60 | <h2>2.0 Structural Artifacts</h2> |
| 61 | |
| 62 | A structural artifact is an artifact with a particular format |
| 63 | that is used to define the relationships between other artifacts in the |
| 64 | repository. |
| 65 | Fossil recognizes the following kinds of structural |
| 66 | artifacts: |
| 67 | |
| 68 | <ul> |
| 69 | <li> [#manifest | Manifests] </li> |
| 70 | <li> [#cluster | Clusters] </li> |
| 71 | <li> [#ctrl | Control Artifacts] </li> |
| @@ -46,66 +73,55 @@ | |
| 73 | <li> [#tktchng | Ticket Changes] </li> |
| 74 | <li> [#attachment | Attachments] </li> |
| 75 | <li> [#event | TechNotes] </li> |
| 76 | </ul> |
| 77 | |
| 78 | These seven structural artifact types are described in subsections below. |
| 79 | |
| 80 | Structural artifacts are ASCII text. The artifact may be PGP clearsigned. |
| 81 | After removal of the PGP clearsign header and suffix (if any) a structural |
| 82 | artifact consists of one or more "cards" separated by a single newline |
| 83 | (ASCII: 0x0a) character. Each card begins with a single |
| 84 | character "card type". Zero or more arguments may follow |
| 85 | the card type. All arguments are separated from each other |
| 86 | and from the card-type character by a single space |
| 87 | character. There is no surplus white space between arguments |
| 88 | and no leading or trailing whitespace except for the newline |
| 89 | character that acts as the card separator. All cards must be in strict |
| 90 | lexicographical order. There may not be any duplicate cards. |
| 91 | |
| 92 | In the current implementation (as of 2017-02-27) the artifacts that |
| 93 | make up a fossil repository are stored as delta- and zlib-compressed |
| 94 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 95 | is an implementation detail and might change in a future release. For |
| 96 | the purpose of this article "file format" means the format of the artifacts, |
| 97 | not how the artifacts are stored on disk. It is the artifact format that |
| 98 | is intended to be enduring. The specifics of how artifacts are stored on |
| 99 | disk, though stable, is not intended to live as long as the |
| 100 | artifact format. |
| 101 | |
| 102 | <a name="manifest"></a> |
| 103 | <h3>2.1 The Manifest</h3> |
| 104 | |
| 105 | A manifest defines a check-in. |
| 106 | A manifest contains a list of artifacts for |
| 107 | each file in the project and the corresponding filenames, as |
| 108 | well as information such as parent check-ins, the username of the |
| 109 | programmer who created the check-in, the date and time when |
| 110 | the check-in was created, and any check-in comments associated |
| 111 | with the check-in. |
| 112 | |
| 113 | Allowed cards in the manifest are as follows: |
| 114 | |
| 115 | <blockquote> |
| 116 | <b>B</b> <i>baseline-manifest</i><br> |
| 117 | <b>C</b> <i>checkin-comment</i><br> |
| 118 | <b>D</b> <i>time-and-date-stamp</i><br> |
| 119 | <b>F</b> <i>filename</i> ?<i>hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br> |
| 120 | <b>N</b> <i>mimetype</i><br> |
| 121 | <b>P</b> <i>artifact-hash</i>+<br> |
| 122 | <b>Q</b> (<b>+</b>|<b>-</b>)<i>artifact-hash</i> ?<i>artifact-hash</i>?<br> |
| 123 | <b>R</b> <i>repository-checksum</i><br> |
| 124 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br> |
| 125 | <b>U</b> <i>user-login</i><br> |
| 126 | <b>Z</b> <i>manifest-checksum</i> |
| 127 | </blockquote> |
| @@ -145,11 +161,11 @@ | |
| 161 | check-in relative to the root of the project file hierarchy. No ".." |
| 162 | or "." directories are allowed within the filename. Space characters |
| 163 | are escaped as in C-card comment text. Backslash characters and |
| 164 | newlines are not allowed within filenames. The directory separator |
| 165 | character is a forward slash (ASCII 0x2F). The second argument to the |
| 166 | F-card is the lower-case hexadecimal artifact hash of |
| 167 | the content artifact. The second argument is required for baseline |
| 168 | manifests but is optional for delta manifests. When the second |
| 169 | argument to the F-card is omitted, it means that the file has been |
| 170 | deleted relative to the baseline (files removed in baseline manifests |
| 171 | versions are <em>not</em> added as F-cards). The optional 3rd argument |
| @@ -167,14 +183,14 @@ | |
| 183 | is used. |
| 184 | |
| 185 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 186 | The P-card has a varying number of arguments that |
| 187 | define other manifests from which the current manifest |
| 188 | is derived. Each argument is a lowercase |
| 189 | hexadecimal artifact hash of a predecessor manifest. All arguments |
| 190 | to the P-card must be unique within that card. |
| 191 | The first argument is the artifact hash of the direct ancestor of the manifest. |
| 192 | Other arguments define manifests with which the first was |
| 193 | merged to yield the current manifest. Most manifests have |
| 194 | a P-card with a single argument. The first manifest in the |
| 195 | project has no ancestors and thus has no P-card or (depending |
| 196 | on the Fossil version) an empty P-card (no arguments). |
| @@ -229,41 +245,27 @@ | |
| 245 | check-in comment argument to the C-card. |
| 246 | |
| 247 | A manifest must have a single Z-card as its last line. The argument |
| 248 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 249 | of all prior lines of the manifest up to and including the newline |
| 250 | character that immediately precedes the "Z", excluding any PGP |
| 251 | clear-signing prefix. The Z-card is |
| 252 | a sanity check to prove that the manifest is well-formed and |
| 253 | consistent. |
| 254 | |
| 255 | A sample manifest from Fossil itself can be seen |
| 256 | [/artifact/28987096ac | here]. |
| 257 | |
| 258 | <a name="cluster"></a> |
| 259 | <h3>2.2 Clusters</h3> |
| 260 | |
| 261 | A cluster is an artifact that declares the existence of other artifacts. |
| 262 | Clusters are used during repository synchronization to help |
| 263 | reduce network traffic. As such, clusters are an optimization and |
| 264 | may be removed from a repository without loss or damage to the |
| 265 | underlying project code. |
| 266 | |
| 267 | Allowed cards in the cluster are as follows: |
| 268 | |
| 269 | <blockquote> |
| 270 | <b>M</b> <i>artifact-id</i><br /> |
| 271 | <b>Z</b> <i>checksum</i> |
| @@ -278,20 +280,14 @@ | |
| 280 | |
| 281 | An example cluster from Fossil can be seen |
| 282 | [/artifact/d03dbdd73a2a8 | here]. |
| 283 | |
| 284 | <a name="ctrl"></a> |
| 285 | <h3>2.3 Control Artifacts</h3> |
| 286 | |
| 287 | Control artifacts are used to assign properties to other artifacts |
| 288 | within the repository. |
| 289 | Allowed cards in a control artifact are as follows: |
| 290 | |
| 291 | <blockquote> |
| 292 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 293 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br /> |
| @@ -338,16 +334,15 @@ | |
| 334 | |
| 335 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 336 | |
| 337 | |
| 338 | <a name="wikichng"></a> |
| 339 | <h3>2.4 Wiki Pages</h3> |
| 340 | |
| 341 | A wiki artifact defines a single version of a |
| 342 | single wiki page. |
| 343 | Wiki artifacts accept |
| 344 | the following card types: |
| 345 | |
| 346 | <blockquote> |
| 347 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 348 | <b>L</b> <i>wiki-title</i><br /> |
| @@ -375,11 +370,11 @@ | |
| 370 | |
| 371 | An example wiki artifact can be seen |
| 372 | [/artifact?name=7b2f5fd0e0&txt=1 | here]. |
| 373 | |
| 374 | <a name="tktchng"></a> |
| 375 | <h3>2.5 Ticket Changes</h3> |
| 376 | |
| 377 | A ticket-change artifact represents a change to a trouble ticket. |
| 378 | The following cards are allowed on a ticket change artifact: |
| 379 | |
| 380 | <blockquote> |
| @@ -421,11 +416,11 @@ | |
| 416 | |
| 417 | An example ticket-change artifact can be seen |
| 418 | [/artifact/91f1ec6af053 | here]. |
| 419 | |
| 420 | <a name="attachment"></a> |
| 421 | <h3>2.6 Attachments</h3> |
| 422 | |
| 423 | An attachment artifact associates some other artifact that is the |
| 424 | attachment (the source artifact) with a ticket or wiki page or |
| 425 | technical note to which |
| 426 | the attachment is connected (the target artifact). |
| @@ -463,11 +458,11 @@ | |
| 458 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 459 | The Z card is required. |
| 460 | |
| 461 | |
| 462 | <a name="event"></a> |
| 463 | <h3>2.7 Technical Notes</h3> |
| 464 | |
| 465 | A technical note or "technote" artifact (formerly known as an "event" artifact) |
| 466 | associates a timeline comment and a page of text |
| 467 | (similar to a wiki page) with a point in time. Technotes can be used |
| 468 | to record project milestones, release notes, blog entries, process |
| @@ -532,11 +527,11 @@ | |
| 527 | |
| 528 | The Z card is the required checksum over the rest of the artifact. |
| 529 | |
| 530 | |
| 531 | <a name="summary"></a> |
| 532 | <h2>3.0 Card Summary</h2> |
| 533 | |
| 534 | The following table summarizes the various kinds of cards that appear |
| 535 | on Fossil artifacts. A blank entry means that combination of card and |
| 536 | artifact is not legal. A number or range of numbers indicates the number |
| 537 | of times a card may (or must) appear in the corresponding artifact type. |
| @@ -739,16 +734,16 @@ | |
| 734 | </tr> |
| 735 | </table> |
| 736 | |
| 737 | |
| 738 | <a name="addenda"></a> |
| 739 | <h2>4.0 Addenda</h2> |
| 740 | |
| 741 | This section contains additional information which may be useful when |
| 742 | implementing algorithms described above. |
| 743 | |
| 744 | <h3>4.1 R-Card Hash Calculation</h3> |
| 745 | |
| 746 | Given a manifest file named <tt>MF</tt>, the following Bash shell code |
| 747 | demonstrates how to compute the value of the R card in that manifest. |
| 748 | This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are |
| 749 | shell input and other lines are output. This demonstration assumes that the |
| 750 |
+4
-3
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -67,11 +67,12 @@ | ||
| 67 | 67 | |
| 68 | 68 | <h3>3.2 Database</h3> |
| 69 | 69 | |
| 70 | 70 | The baseline data structures for Fossil and Git are the same (modulo |
| 71 | 71 | formatting details). Both systems store check-ins as immutable |
| 72 | -objects referencing their immediate ancestors and named by their SHA1 hash. | |
| 72 | +objects referencing their immediate ancestors and named by a | |
| 73 | +cryptographic hash of the check-in content. | |
| 73 | 74 | |
| 74 | 75 | The difference is that Git stores its objects as individual files |
| 75 | 76 | in the ".git" folder or compressed into |
| 76 | 77 | bespoke "pack-files", whereas Fossil stores its objects in a |
| 77 | 78 | relational ([https://www.sqlite.org/|SQLite]) database file. To put it |
| @@ -117,11 +118,11 @@ | ||
| 117 | 118 | closely supervised by an highly engaged architect and implemented by |
| 118 | 119 | a clique of developers. |
| 119 | 120 | |
| 120 | 121 | Nota Bene: This is not to say that Git cannot be used for cathedral-style |
| 121 | 122 | development or that Fossil cannot be used for bazaar-style development. |
| 122 | -They can be. But those modes are not their design intent nor the their | |
| 123 | +They can be. But those modes are not their design intent nor their | |
| 123 | 124 | low-friction path. |
| 124 | 125 | |
| 125 | 126 | Git encourages a style in which individual developers work in relative |
| 126 | 127 | isolation, maintaining their |
| 127 | 128 | own branches and occasionally rebasing and pushing selected changes up |
| @@ -144,11 +145,11 @@ | ||
| 144 | 145 | Fossil was specifically designed to support the development of SQLite. |
| 145 | 146 | |
| 146 | 147 | Both SQLite and Linux are important pieces of software. |
| 147 | 148 | SQLite is found on far more systems than Linux. (Almost every Linux |
| 148 | 149 | system uses SQLite, but there are many non-Linux systems such as |
| 149 | -iPhones, PlayStations, and Windows PC that use SQLite.) On the other | |
| 150 | +iPhones, PlayStations, and Windows PCs that use SQLite.) On the other | |
| 150 | 151 | hand, for those systems that do use Linux, Linux is a far more important |
| 151 | 152 | component. |
| 152 | 153 | |
| 153 | 154 | Linux uses a bazaar-style development model. There are thousands and |
| 154 | 155 | thousands of contributors, most of whom do not know each others names. |
| 155 | 156 | |
| 156 | 157 | ADDED www/hashpolicy.wiki |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -67,11 +67,12 @@ | |
| 67 | |
| 68 | <h3>3.2 Database</h3> |
| 69 | |
| 70 | The baseline data structures for Fossil and Git are the same (modulo |
| 71 | formatting details). Both systems store check-ins as immutable |
| 72 | objects referencing their immediate ancestors and named by their SHA1 hash. |
| 73 | |
| 74 | The difference is that Git stores its objects as individual files |
| 75 | in the ".git" folder or compressed into |
| 76 | bespoke "pack-files", whereas Fossil stores its objects in a |
| 77 | relational ([https://www.sqlite.org/|SQLite]) database file. To put it |
| @@ -117,11 +118,11 @@ | |
| 117 | closely supervised by an highly engaged architect and implemented by |
| 118 | a clique of developers. |
| 119 | |
| 120 | Nota Bene: This is not to say that Git cannot be used for cathedral-style |
| 121 | development or that Fossil cannot be used for bazaar-style development. |
| 122 | They can be. But those modes are not their design intent nor the their |
| 123 | low-friction path. |
| 124 | |
| 125 | Git encourages a style in which individual developers work in relative |
| 126 | isolation, maintaining their |
| 127 | own branches and occasionally rebasing and pushing selected changes up |
| @@ -144,11 +145,11 @@ | |
| 144 | Fossil was specifically designed to support the development of SQLite. |
| 145 | |
| 146 | Both SQLite and Linux are important pieces of software. |
| 147 | SQLite is found on far more systems than Linux. (Almost every Linux |
| 148 | system uses SQLite, but there are many non-Linux systems such as |
| 149 | iPhones, PlayStations, and Windows PC that use SQLite.) On the other |
| 150 | hand, for those systems that do use Linux, Linux is a far more important |
| 151 | component. |
| 152 | |
| 153 | Linux uses a bazaar-style development model. There are thousands and |
| 154 | thousands of contributors, most of whom do not know each others names. |
| 155 | |
| 156 | DDED www/hashpolicy.wiki |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -67,11 +67,12 @@ | |
| 67 | |
| 68 | <h3>3.2 Database</h3> |
| 69 | |
| 70 | The baseline data structures for Fossil and Git are the same (modulo |
| 71 | formatting details). Both systems store check-ins as immutable |
| 72 | objects referencing their immediate ancestors and named by a |
| 73 | cryptographic hash of the check-in content. |
| 74 | |
| 75 | The difference is that Git stores its objects as individual files |
| 76 | in the ".git" folder or compressed into |
| 77 | bespoke "pack-files", whereas Fossil stores its objects in a |
| 78 | relational ([https://www.sqlite.org/|SQLite]) database file. To put it |
| @@ -117,11 +118,11 @@ | |
| 118 | closely supervised by an highly engaged architect and implemented by |
| 119 | a clique of developers. |
| 120 | |
| 121 | Nota Bene: This is not to say that Git cannot be used for cathedral-style |
| 122 | development or that Fossil cannot be used for bazaar-style development. |
| 123 | They can be. But those modes are not their design intent nor their |
| 124 | low-friction path. |
| 125 | |
| 126 | Git encourages a style in which individual developers work in relative |
| 127 | isolation, maintaining their |
| 128 | own branches and occasionally rebasing and pushing selected changes up |
| @@ -144,11 +145,11 @@ | |
| 145 | Fossil was specifically designed to support the development of SQLite. |
| 146 | |
| 147 | Both SQLite and Linux are important pieces of software. |
| 148 | SQLite is found on far more systems than Linux. (Almost every Linux |
| 149 | system uses SQLite, but there are many non-Linux systems such as |
| 150 | iPhones, PlayStations, and Windows PCs that use SQLite.) On the other |
| 151 | hand, for those systems that do use Linux, Linux is a far more important |
| 152 | component. |
| 153 | |
| 154 | Linux uses a bazaar-style development model. There are thousands and |
| 155 | thousands of contributors, most of whom do not know each others names. |
| 156 | |
| 157 | DDED www/hashpolicy.wiki |
+20
| --- a/www/hashpolicy.wiki | ||
| +++ b/www/hashpolicy.wiki | ||
| @@ -0,0 +1,20 @@ | ||
| 1 | +<title>Hash Policy</title> | |
| 2 | + | |
| 3 | +<h2> Executive Summary, Orcutive Summary</h2> | |
| 4 | + | |
| 5 | +<b>Or: How To </h2> | |
| 6 | + | |
| 7 | +There i This Article</b> | |
| 8 | + | |
| 9 | +Thham now | |
| 10 | +upgraded to | |
| 11 | +change texpected to be | |
| 12 | +replaced ot expected to be | |
| 13 | +replaced until Ma | |
| 14 | +out o | |
| 15 | +Debian 9 is implement0 or later | |
| 16 | + | |
| 17 | +work and | |
| 18 | +Hash Policy</title> | |
| 19 | + | |
| 20 | +<h2>< Introduction ha", not generic SHA1sequel |
| --- a/www/hashpolicy.wiki | |
| +++ b/www/hashpolicy.wiki | |
| @@ -0,0 +1,20 @@ | |
| --- a/www/hashpolicy.wiki | |
| +++ b/www/hashpolicy.wiki | |
| @@ -0,0 +1,20 @@ | |
| 1 | <title>Hash Policy</title> |
| 2 | |
| 3 | <h2> Executive Summary, Orcutive Summary</h2> |
| 4 | |
| 5 | <b>Or: How To </h2> |
| 6 | |
| 7 | There i This Article</b> |
| 8 | |
| 9 | Thham now |
| 10 | upgraded to |
| 11 | change texpected to be |
| 12 | replaced ot expected to be |
| 13 | replaced until Ma |
| 14 | out o |
| 15 | Debian 9 is implement0 or later |
| 16 | |
| 17 | work and |
| 18 | Hash Policy</title> |
| 19 | |
| 20 | <h2>< Introduction ha", not generic SHA1sequel |
+2
-2
| --- www/mkdownload.tcl | ||
| +++ www/mkdownload.tcl | ||
| @@ -37,12 +37,12 @@ | ||
| 37 | 37 | set avers($version) 1 |
| 38 | 38 | } |
| 39 | 39 | } |
| 40 | 40 | close $in |
| 41 | 41 | |
| 42 | +set vdate(2.0) 2017-03-03 | |
| 42 | 43 | set vdate(1.37) 2017-01-15 |
| 43 | -set vdate(1.36) 2016-10-24 | |
| 44 | 44 | |
| 45 | 45 | # Do all versions from newest to oldest |
| 46 | 46 | # |
| 47 | 47 | foreach vers [lsort -decr -real [array names avers]] { |
| 48 | 48 | # set hr "../timeline?c=version-$vers;y=ci" |
| @@ -57,11 +57,11 @@ | ||
| 57 | 57 | puts $out "</b></center>" |
| 58 | 58 | puts $out "</td></tr>" |
| 59 | 59 | puts $out "<tr>" |
| 60 | 60 | |
| 61 | 61 | foreach {prefix img desc} { |
| 62 | - fossil-linux-x86 linux.gif {Linux 3.x x86} | |
| 62 | + fossil-linux linux.gif {Linux 3.x x64} | |
| 63 | 63 | fossil-macosx mac.gif {Mac 10.x x86} |
| 64 | 64 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 65 | 65 | fossil-w32 win32.gif {Windows} |
| 66 | 66 | fossil-src src.gif {Source Tarball} |
| 67 | 67 | } { |
| 68 | 68 |
| --- www/mkdownload.tcl | |
| +++ www/mkdownload.tcl | |
| @@ -37,12 +37,12 @@ | |
| 37 | set avers($version) 1 |
| 38 | } |
| 39 | } |
| 40 | close $in |
| 41 | |
| 42 | set vdate(1.37) 2017-01-15 |
| 43 | set vdate(1.36) 2016-10-24 |
| 44 | |
| 45 | # Do all versions from newest to oldest |
| 46 | # |
| 47 | foreach vers [lsort -decr -real [array names avers]] { |
| 48 | # set hr "../timeline?c=version-$vers;y=ci" |
| @@ -57,11 +57,11 @@ | |
| 57 | puts $out "</b></center>" |
| 58 | puts $out "</td></tr>" |
| 59 | puts $out "<tr>" |
| 60 | |
| 61 | foreach {prefix img desc} { |
| 62 | fossil-linux-x86 linux.gif {Linux 3.x x86} |
| 63 | fossil-macosx mac.gif {Mac 10.x x86} |
| 64 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 65 | fossil-w32 win32.gif {Windows} |
| 66 | fossil-src src.gif {Source Tarball} |
| 67 | } { |
| 68 |
| --- www/mkdownload.tcl | |
| +++ www/mkdownload.tcl | |
| @@ -37,12 +37,12 @@ | |
| 37 | set avers($version) 1 |
| 38 | } |
| 39 | } |
| 40 | close $in |
| 41 | |
| 42 | set vdate(2.0) 2017-03-03 |
| 43 | set vdate(1.37) 2017-01-15 |
| 44 | |
| 45 | # Do all versions from newest to oldest |
| 46 | # |
| 47 | foreach vers [lsort -decr -real [array names avers]] { |
| 48 | # set hr "../timeline?c=version-$vers;y=ci" |
| @@ -57,11 +57,11 @@ | |
| 57 | puts $out "</b></center>" |
| 58 | puts $out "</td></tr>" |
| 59 | puts $out "<tr>" |
| 60 | |
| 61 | foreach {prefix img desc} { |
| 62 | fossil-linux linux.gif {Linux 3.x x64} |
| 63 | fossil-macosx mac.gif {Mac 10.x x86} |
| 64 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 65 | fossil-w32 win32.gif {Windows} |
| 66 | fossil-src src.gif {Source Tarball} |
| 67 | } { |
| 68 |
+1
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -36,10 +36,11 @@ | ||
| 36 | 36 | fiveminutes.wiki {Update and Running in 5 Minutes as a Single User} |
| 37 | 37 | foss-cklist.wiki {Checklist For Successful Open-Source Projects} |
| 38 | 38 | fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} |
| 39 | 39 | fossil-v-git.wiki {Fossil Versus Git} |
| 40 | 40 | hacker-howto.wiki {Hacker How-To} |
| 41 | + hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256} | |
| 41 | 42 | /help {Lists of Commands and Webpages} |
| 42 | 43 | hints.wiki {Fossil Tips And Usage Hints} |
| 43 | 44 | index.wiki {Home Page} |
| 44 | 45 | inout.wiki {Import And Export To And From Git} |
| 45 | 46 | makefile.wiki {The Fossil Build Process} |
| 46 | 47 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -36,10 +36,11 @@ | |
| 36 | fiveminutes.wiki {Update and Running in 5 Minutes as a Single User} |
| 37 | foss-cklist.wiki {Checklist For Successful Open-Source Projects} |
| 38 | fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} |
| 39 | fossil-v-git.wiki {Fossil Versus Git} |
| 40 | hacker-howto.wiki {Hacker How-To} |
| 41 | /help {Lists of Commands and Webpages} |
| 42 | hints.wiki {Fossil Tips And Usage Hints} |
| 43 | index.wiki {Home Page} |
| 44 | inout.wiki {Import And Export To And From Git} |
| 45 | makefile.wiki {The Fossil Build Process} |
| 46 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -36,10 +36,11 @@ | |
| 36 | fiveminutes.wiki {Update and Running in 5 Minutes as a Single User} |
| 37 | foss-cklist.wiki {Checklist For Successful Open-Source Projects} |
| 38 | fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} |
| 39 | fossil-v-git.wiki {Fossil Versus Git} |
| 40 | hacker-howto.wiki {Hacker How-To} |
| 41 | hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256} |
| 42 | /help {Lists of Commands and Webpages} |
| 43 | hints.wiki {Fossil Tips And Usage Hints} |
| 44 | index.wiki {Home Page} |
| 45 | inout.wiki {Import And Export To And From Git} |
| 46 | makefile.wiki {The Fossil Build Process} |
| 47 |
| --- www/permutedindex.html | ||
| +++ www/permutedindex.html | ||
| @@ -29,10 +29,11 @@ | ||
| 29 | 29 | <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil — The</a></li> |
| 30 | 30 | <li><a href="customskin.md">Appearance of Web Pages — Theming: Customizing The</a></li> |
| 31 | 31 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| 32 | 32 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 33 | 33 | <li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li> |
| 34 | +<li><a href="hashpolicy.wiki">Between SHA1 and SHA3-256 — Hash Policy: Choosing</a></li> | |
| 34 | 35 | <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> |
| 35 | 36 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 36 | 37 | <li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li> |
| 37 | 38 | <li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li> |
| 38 | 39 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| @@ -43,10 +44,11 @@ | ||
| 43 | 44 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 44 | 45 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 45 | 46 | <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> |
| 46 | 47 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 47 | 48 | <li><a href="childprojects.wiki"><b>Child Projects</b></a></li> |
| 49 | +<li><a href="hashpolicy.wiki">Choosing Between SHA1 and SHA3-256 — Hash Policy:</a></li> | |
| 48 | 50 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 49 | 51 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 50 | 52 | <li><a href="../../../help">Commands and Webpages — Lists of</a></li> |
| 51 | 53 | <li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li> |
| 52 | 54 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| @@ -111,10 +113,11 @@ | ||
| 111 | 113 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 112 | 114 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 113 | 115 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 114 | 116 | <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> |
| 115 | 117 | <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> |
| 118 | +<li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li> | |
| 116 | 119 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 117 | 120 | <li><a href="index.wiki"><b>Home Page</b></a></li> |
| 118 | 121 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 119 | 122 | <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> |
| 120 | 123 | <li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li> |
| @@ -147,10 +150,11 @@ | ||
| 147 | 150 | <li><a href="index.wiki">Page — Home</a></li> |
| 148 | 151 | <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> |
| 149 | 152 | <li><a href="password.wiki"><b>Password Management And Authentication</b></a></li> |
| 150 | 153 | <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> |
| 151 | 154 | <li><a href="stats.wiki"><b>Performance Statistics</b></a></li> |
| 155 | +<li><a href="hashpolicy.wiki">Policy: Choosing Between SHA1 and SHA3-256 — Hash</a></li> | |
| 152 | 156 | <li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li> |
| 153 | 157 | <li><a href="pop.wiki"><b>Principles Of Operation</b></a></li> |
| 154 | 158 | <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> |
| 155 | 159 | <li><a href="makefile.wiki">Process — The Fossil Build</a></li> |
| 156 | 160 | <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> |
| @@ -174,10 +178,12 @@ | ||
| 174 | 178 | <li><a href="th1.md">Scripting Language — The TH1</a></li> |
| 175 | 179 | <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> |
| 176 | 180 | <li><a href="selfhost.wiki">Self Hosting Repositories — Fossil</a></li> |
| 177 | 181 | <li><a href="server.wiki">Server — How To Configure A Fossil</a></li> |
| 178 | 182 | <li><a href="settings.wiki">Settings — Fossil</a></li> |
| 183 | +<li><a href="hashpolicy.wiki">SHA1 and SHA3-256 — Hash Policy: Choosing Between</a></li> | |
| 184 | +<li><a href="hashpolicy.wiki">SHA3-256 — Hash Policy: Choosing Between SHA1 and</a></li> | |
| 179 | 185 | <li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li> |
| 180 | 186 | <li><a href="fiveminutes.wiki">Single User — Update and Running in 5 Minutes as a</a></li> |
| 181 | 187 | <li><a href="../../../sitemap"><b>Site Map</b></a></li> |
| 182 | 188 | <li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li> |
| 183 | 189 | <li><a href="antibot.wiki">Spiders and Bots — Defense against</a></li> |
| 184 | 190 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -29,10 +29,11 @@ | |
| 29 | <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil — The</a></li> |
| 30 | <li><a href="customskin.md">Appearance of Web Pages — Theming: Customizing The</a></li> |
| 31 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| 32 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 33 | <li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li> |
| 34 | <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> |
| 35 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 36 | <li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li> |
| 37 | <li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li> |
| 38 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| @@ -43,10 +44,11 @@ | |
| 43 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 44 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 45 | <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> |
| 46 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 47 | <li><a href="childprojects.wiki"><b>Child Projects</b></a></li> |
| 48 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 49 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 50 | <li><a href="../../../help">Commands and Webpages — Lists of</a></li> |
| 51 | <li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li> |
| 52 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| @@ -111,10 +113,11 @@ | |
| 111 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 112 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 113 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 114 | <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> |
| 115 | <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> |
| 116 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 117 | <li><a href="index.wiki"><b>Home Page</b></a></li> |
| 118 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 119 | <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> |
| 120 | <li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li> |
| @@ -147,10 +150,11 @@ | |
| 147 | <li><a href="index.wiki">Page — Home</a></li> |
| 148 | <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> |
| 149 | <li><a href="password.wiki"><b>Password Management And Authentication</b></a></li> |
| 150 | <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> |
| 151 | <li><a href="stats.wiki"><b>Performance Statistics</b></a></li> |
| 152 | <li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li> |
| 153 | <li><a href="pop.wiki"><b>Principles Of Operation</b></a></li> |
| 154 | <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> |
| 155 | <li><a href="makefile.wiki">Process — The Fossil Build</a></li> |
| 156 | <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> |
| @@ -174,10 +178,12 @@ | |
| 174 | <li><a href="th1.md">Scripting Language — The TH1</a></li> |
| 175 | <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> |
| 176 | <li><a href="selfhost.wiki">Self Hosting Repositories — Fossil</a></li> |
| 177 | <li><a href="server.wiki">Server — How To Configure A Fossil</a></li> |
| 178 | <li><a href="settings.wiki">Settings — Fossil</a></li> |
| 179 | <li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li> |
| 180 | <li><a href="fiveminutes.wiki">Single User — Update and Running in 5 Minutes as a</a></li> |
| 181 | <li><a href="../../../sitemap"><b>Site Map</b></a></li> |
| 182 | <li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li> |
| 183 | <li><a href="antibot.wiki">Spiders and Bots — Defense against</a></li> |
| 184 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -29,10 +29,11 @@ | |
| 29 | <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil — The</a></li> |
| 30 | <li><a href="customskin.md">Appearance of Web Pages — Theming: Customizing The</a></li> |
| 31 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| 32 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 33 | <li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li> |
| 34 | <li><a href="hashpolicy.wiki">Between SHA1 and SHA3-256 — Hash Policy: Choosing</a></li> |
| 35 | <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> |
| 36 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 37 | <li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li> |
| 38 | <li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li> |
| 39 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| @@ -43,10 +44,11 @@ | |
| 44 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 45 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 46 | <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> |
| 47 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 48 | <li><a href="childprojects.wiki"><b>Child Projects</b></a></li> |
| 49 | <li><a href="hashpolicy.wiki">Choosing Between SHA1 and SHA3-256 — Hash Policy:</a></li> |
| 50 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 51 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 52 | <li><a href="../../../help">Commands and Webpages — Lists of</a></li> |
| 53 | <li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li> |
| 54 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| @@ -111,10 +113,11 @@ | |
| 113 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 114 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 115 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 116 | <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> |
| 117 | <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> |
| 118 | <li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li> |
| 119 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 120 | <li><a href="index.wiki"><b>Home Page</b></a></li> |
| 121 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 122 | <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> |
| 123 | <li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li> |
| @@ -147,10 +150,11 @@ | |
| 150 | <li><a href="index.wiki">Page — Home</a></li> |
| 151 | <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> |
| 152 | <li><a href="password.wiki"><b>Password Management And Authentication</b></a></li> |
| 153 | <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> |
| 154 | <li><a href="stats.wiki"><b>Performance Statistics</b></a></li> |
| 155 | <li><a href="hashpolicy.wiki">Policy: Choosing Between SHA1 and SHA3-256 — Hash</a></li> |
| 156 | <li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li> |
| 157 | <li><a href="pop.wiki"><b>Principles Of Operation</b></a></li> |
| 158 | <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> |
| 159 | <li><a href="makefile.wiki">Process — The Fossil Build</a></li> |
| 160 | <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> |
| @@ -174,10 +178,12 @@ | |
| 178 | <li><a href="th1.md">Scripting Language — The TH1</a></li> |
| 179 | <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> |
| 180 | <li><a href="selfhost.wiki">Self Hosting Repositories — Fossil</a></li> |
| 181 | <li><a href="server.wiki">Server — How To Configure A Fossil</a></li> |
| 182 | <li><a href="settings.wiki">Settings — Fossil</a></li> |
| 183 | <li><a href="hashpolicy.wiki">SHA1 and SHA3-256 — Hash Policy: Choosing Between</a></li> |
| 184 | <li><a href="hashpolicy.wiki">SHA3-256 — Hash Policy: Choosing Between SHA1 and</a></li> |
| 185 | <li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li> |
| 186 | <li><a href="fiveminutes.wiki">Single User — Update and Running in 5 Minutes as a</a></li> |
| 187 | <li><a href="../../../sitemap"><b>Site Map</b></a></li> |
| 188 | <li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li> |
| 189 | <li><a href="antibot.wiki">Spiders and Bots — Defense against</a></li> |
| 190 |
+7
-6
| --- www/pop.wiki | ||
| +++ www/pop.wiki | ||
| @@ -25,17 +25,18 @@ | ||
| 25 | 25 | The global state represents the content of the project. |
| 26 | 26 | The local state identifies the authorized users and |
| 27 | 27 | access policies for a particular repository.</p></li> |
| 28 | 28 | |
| 29 | 29 | <li><p>The global state of a repository is an unordered |
| 30 | -collection of artifacts. Each artifact is named by | |
| 31 | -its SHA1 hash encoded in lowercase hexadecimal. | |
| 30 | +collection of artifacts. Each artifact is named by a | |
| 31 | +cryptographic hash (SHA1 or SHA3-256) encoded in | |
| 32 | +lowercase hexadecimal. | |
| 32 | 33 | In many contexts, the name can be |
| 33 | 34 | abbreviated to a unique prefix. A five- or six-character |
| 34 | 35 | prefix usually suffices to uniquely identify a file.</p></li> |
| 35 | 36 | |
| 36 | -<li><p>Because artifacts are named by their SHA1 hash, all artifacts | |
| 37 | +<li><p>Because artifacts are named by a cryptographic hash, all artifacts | |
| 37 | 38 | are immutable. Any change to the content of an artifact also |
| 38 | 39 | changes the hash that forms the artifacts name, thus |
| 39 | 40 | creating a new artifact. Both the old original version of the |
| 40 | 41 | artifact and the new change are preserved under different names.</p></li> |
| 41 | 42 | |
| @@ -42,16 +43,16 @@ | ||
| 42 | 43 | <li><p>It is theoretically possible for two artifacts with different |
| 43 | 44 | content to share the same hash. But finding two such |
| 44 | 45 | artifacts is so incredibly difficult and unlikely that we |
| 45 | 46 | consider it to be an impossibility.</p></li> |
| 46 | 47 | |
| 47 | -<li><p>The signature of an artifact is the SHA1 hash of the | |
| 48 | +<li><p>The signature of an artifact is the cryptographic hash of the | |
| 48 | 49 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 49 | 50 | or meta-information about the artifact is added before computing |
| 50 | 51 | the hash. So you can |
| 51 | -always find the SHA1 signature of a file by using the | |
| 52 | -"sha1sum" command-line utility.</p></li> | |
| 52 | +always find the signature of a file by using the | |
| 53 | +"sha1sum" or "sha3sum" or similar command-line utilities.</p></li> | |
| 53 | 54 | |
| 54 | 55 | <li><p>The artifacts that comprise the global state of a repository |
| 55 | 56 | are the complete global state of that repository. The SQLite |
| 56 | 57 | database that holds the repository contains additional information |
| 57 | 58 | about linkages between artifacts, but all of that added information |
| 58 | 59 |
| --- www/pop.wiki | |
| +++ www/pop.wiki | |
| @@ -25,17 +25,18 @@ | |
| 25 | The global state represents the content of the project. |
| 26 | The local state identifies the authorized users and |
| 27 | access policies for a particular repository.</p></li> |
| 28 | |
| 29 | <li><p>The global state of a repository is an unordered |
| 30 | collection of artifacts. Each artifact is named by |
| 31 | its SHA1 hash encoded in lowercase hexadecimal. |
| 32 | In many contexts, the name can be |
| 33 | abbreviated to a unique prefix. A five- or six-character |
| 34 | prefix usually suffices to uniquely identify a file.</p></li> |
| 35 | |
| 36 | <li><p>Because artifacts are named by their SHA1 hash, all artifacts |
| 37 | are immutable. Any change to the content of an artifact also |
| 38 | changes the hash that forms the artifacts name, thus |
| 39 | creating a new artifact. Both the old original version of the |
| 40 | artifact and the new change are preserved under different names.</p></li> |
| 41 | |
| @@ -42,16 +43,16 @@ | |
| 42 | <li><p>It is theoretically possible for two artifacts with different |
| 43 | content to share the same hash. But finding two such |
| 44 | artifacts is so incredibly difficult and unlikely that we |
| 45 | consider it to be an impossibility.</p></li> |
| 46 | |
| 47 | <li><p>The signature of an artifact is the SHA1 hash of the |
| 48 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 49 | or meta-information about the artifact is added before computing |
| 50 | the hash. So you can |
| 51 | always find the SHA1 signature of a file by using the |
| 52 | "sha1sum" command-line utility.</p></li> |
| 53 | |
| 54 | <li><p>The artifacts that comprise the global state of a repository |
| 55 | are the complete global state of that repository. The SQLite |
| 56 | database that holds the repository contains additional information |
| 57 | about linkages between artifacts, but all of that added information |
| 58 |
| --- www/pop.wiki | |
| +++ www/pop.wiki | |
| @@ -25,17 +25,18 @@ | |
| 25 | The global state represents the content of the project. |
| 26 | The local state identifies the authorized users and |
| 27 | access policies for a particular repository.</p></li> |
| 28 | |
| 29 | <li><p>The global state of a repository is an unordered |
| 30 | collection of artifacts. Each artifact is named by a |
| 31 | cryptographic hash (SHA1 or SHA3-256) encoded in |
| 32 | lowercase hexadecimal. |
| 33 | In many contexts, the name can be |
| 34 | abbreviated to a unique prefix. A five- or six-character |
| 35 | prefix usually suffices to uniquely identify a file.</p></li> |
| 36 | |
| 37 | <li><p>Because artifacts are named by a cryptographic hash, all artifacts |
| 38 | are immutable. Any change to the content of an artifact also |
| 39 | changes the hash that forms the artifacts name, thus |
| 40 | creating a new artifact. Both the old original version of the |
| 41 | artifact and the new change are preserved under different names.</p></li> |
| 42 | |
| @@ -42,16 +43,16 @@ | |
| 43 | <li><p>It is theoretically possible for two artifacts with different |
| 44 | content to share the same hash. But finding two such |
| 45 | artifacts is so incredibly difficult and unlikely that we |
| 46 | consider it to be an impossibility.</p></li> |
| 47 | |
| 48 | <li><p>The signature of an artifact is the cryptographic hash of the |
| 49 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 50 | or meta-information about the artifact is added before computing |
| 51 | the hash. So you can |
| 52 | always find the signature of a file by using the |
| 53 | "sha1sum" or "sha3sum" or similar command-line utilities.</p></li> |
| 54 | |
| 55 | <li><p>The artifacts that comprise the global state of a repository |
| 56 | are the complete global state of that repository. The SQLite |
| 57 | database that holds the repository contains additional information |
| 58 | about linkages between artifacts, but all of that added information |
| 59 |
+10
-9
| --- www/selfcheck.wiki | ||
| +++ www/selfcheck.wiki | ||
| @@ -51,14 +51,14 @@ | ||
| 51 | 51 | commit. So during the course of check-in (or other repository |
| 52 | 52 | operation) many different files |
| 53 | 53 | in the repository might be modified. Some files are simply |
| 54 | 54 | compressed. Other files are delta encoded and then compressed. |
| 55 | 55 | While all this is going on, fossil makes a record of every file |
| 56 | -that is encoded and the SHA1 hash of the original content of that | |
| 56 | +and the SHA1 or SHA3-256 hash of the original content of that | |
| 57 | 57 | file. Then just before transaction commit, fossil re-extracts |
| 58 | -the original content of all files that were written, computes | |
| 59 | -the SHA1 checksum again, and verifies that the checksums match. | |
| 58 | +the original content of all files that were written, recomputes | |
| 59 | +the hash, and verifies that the recomputed hash still matches. | |
| 60 | 60 | If anything does not match up, an error |
| 61 | 61 | message is printed and the transaction rolls back. |
| 62 | 62 | |
| 63 | 63 | So, in other words, fossil always checks to make sure it can |
| 64 | 64 | re-extract a file before it commits a change to that file. |
| @@ -73,20 +73,20 @@ | ||
| 73 | 73 | and of all other files in the manifest. Prior to any check-in |
| 74 | 74 | commit, these checksums are verified to ensure that the check-in |
| 75 | 75 | agrees exactly with what is on disk. Similarly, |
| 76 | 76 | the repository checksum is verified after a checkout to make |
| 77 | 77 | sure that the entire repository was checked out correctly. |
| 78 | -Note that these added checks use a different hash (MD5 instead | |
| 79 | -of SHA1) in order to avoid common-mode failures in the hash | |
| 78 | +Note that these added checks use a different hash algorithm (MD5) | |
| 79 | +in order to avoid common-mode failures in the hash | |
| 80 | 80 | algorithm implementation. |
| 81 | 81 | |
| 82 | 82 | |
| 83 | -<h2>Checksums On Control Artifacts And Deltas</h2> | |
| 83 | +<h2>Checksums On Structural Artifacts And Deltas</h2> | |
| 84 | 84 | |
| 85 | -Every [./fileformat.wiki | control artifact] in a fossil repository | |
| 85 | +Every [./fileformat.wiki | structural artifact] in a fossil repository | |
| 86 | 86 | contains a "Z-card" bearing an MD5 checksum over the rest of the |
| 87 | -artifact. Any mismatch causes the control artifact to be ignored. | |
| 87 | +artifact. Any mismatch causes the structural artifact to be ignored. | |
| 88 | 88 | |
| 89 | 89 | The [./delta_format.wiki | file delta format] includes a 32-bit |
| 90 | 90 | checksum of the target file. Whenever a file is reconstructed from |
| 91 | 91 | a delta, that checksum is verified to make sure the reconstruction |
| 92 | 92 | was done correctly. |
| @@ -103,6 +103,7 @@ | ||
| 103 | 103 | reliability is more important than raw speed. The developers of |
| 104 | 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | 105 | |
| 106 | 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | 107 | Fossil runs quickly enough to stay out of the developers way. |
| 108 | -Most operations complete in under a second. | |
| 108 | +Most operations complete in milliseconds, faster that you can press | |
| 109 | +the "Enter" key. | |
| 109 | 110 |
| --- www/selfcheck.wiki | |
| +++ www/selfcheck.wiki | |
| @@ -51,14 +51,14 @@ | |
| 51 | commit. So during the course of check-in (or other repository |
| 52 | operation) many different files |
| 53 | in the repository might be modified. Some files are simply |
| 54 | compressed. Other files are delta encoded and then compressed. |
| 55 | While all this is going on, fossil makes a record of every file |
| 56 | that is encoded and the SHA1 hash of the original content of that |
| 57 | file. Then just before transaction commit, fossil re-extracts |
| 58 | the original content of all files that were written, computes |
| 59 | the SHA1 checksum again, and verifies that the checksums match. |
| 60 | If anything does not match up, an error |
| 61 | message is printed and the transaction rolls back. |
| 62 | |
| 63 | So, in other words, fossil always checks to make sure it can |
| 64 | re-extract a file before it commits a change to that file. |
| @@ -73,20 +73,20 @@ | |
| 73 | and of all other files in the manifest. Prior to any check-in |
| 74 | commit, these checksums are verified to ensure that the check-in |
| 75 | agrees exactly with what is on disk. Similarly, |
| 76 | the repository checksum is verified after a checkout to make |
| 77 | sure that the entire repository was checked out correctly. |
| 78 | Note that these added checks use a different hash (MD5 instead |
| 79 | of SHA1) in order to avoid common-mode failures in the hash |
| 80 | algorithm implementation. |
| 81 | |
| 82 | |
| 83 | <h2>Checksums On Control Artifacts And Deltas</h2> |
| 84 | |
| 85 | Every [./fileformat.wiki | control artifact] in a fossil repository |
| 86 | contains a "Z-card" bearing an MD5 checksum over the rest of the |
| 87 | artifact. Any mismatch causes the control artifact to be ignored. |
| 88 | |
| 89 | The [./delta_format.wiki | file delta format] includes a 32-bit |
| 90 | checksum of the target file. Whenever a file is reconstructed from |
| 91 | a delta, that checksum is verified to make sure the reconstruction |
| 92 | was done correctly. |
| @@ -103,6 +103,7 @@ | |
| 103 | reliability is more important than raw speed. The developers of |
| 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | |
| 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | Fossil runs quickly enough to stay out of the developers way. |
| 108 | Most operations complete in under a second. |
| 109 |
| --- www/selfcheck.wiki | |
| +++ www/selfcheck.wiki | |
| @@ -51,14 +51,14 @@ | |
| 51 | commit. So during the course of check-in (or other repository |
| 52 | operation) many different files |
| 53 | in the repository might be modified. Some files are simply |
| 54 | compressed. Other files are delta encoded and then compressed. |
| 55 | While all this is going on, fossil makes a record of every file |
| 56 | and the SHA1 or SHA3-256 hash of the original content of that |
| 57 | file. Then just before transaction commit, fossil re-extracts |
| 58 | the original content of all files that were written, recomputes |
| 59 | the hash, and verifies that the recomputed hash still matches. |
| 60 | If anything does not match up, an error |
| 61 | message is printed and the transaction rolls back. |
| 62 | |
| 63 | So, in other words, fossil always checks to make sure it can |
| 64 | re-extract a file before it commits a change to that file. |
| @@ -73,20 +73,20 @@ | |
| 73 | and of all other files in the manifest. Prior to any check-in |
| 74 | commit, these checksums are verified to ensure that the check-in |
| 75 | agrees exactly with what is on disk. Similarly, |
| 76 | the repository checksum is verified after a checkout to make |
| 77 | sure that the entire repository was checked out correctly. |
| 78 | Note that these added checks use a different hash algorithm (MD5) |
| 79 | in order to avoid common-mode failures in the hash |
| 80 | algorithm implementation. |
| 81 | |
| 82 | |
| 83 | <h2>Checksums On Structural Artifacts And Deltas</h2> |
| 84 | |
| 85 | Every [./fileformat.wiki | structural artifact] in a fossil repository |
| 86 | contains a "Z-card" bearing an MD5 checksum over the rest of the |
| 87 | artifact. Any mismatch causes the structural artifact to be ignored. |
| 88 | |
| 89 | The [./delta_format.wiki | file delta format] includes a 32-bit |
| 90 | checksum of the target file. Whenever a file is reconstructed from |
| 91 | a delta, that checksum is verified to make sure the reconstruction |
| 92 | was done correctly. |
| @@ -103,6 +103,7 @@ | |
| 103 | reliability is more important than raw speed. The developers of |
| 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | |
| 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | Fossil runs quickly enough to stay out of the developers way. |
| 108 | Most operations complete in milliseconds, faster that you can press |
| 109 | the "Enter" key. |
| 110 |
+1
-1
| --- www/shunning.wiki | ||
| +++ www/shunning.wiki | ||
| @@ -23,11 +23,11 @@ | ||
| 23 | 23 | <h2>Shunning</h2> |
| 24 | 24 | |
| 25 | 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | 26 | a repository. |
| 27 | 27 | |
| 28 | -Every Fossil repository maintains a list of the SHA1 hash names of | |
| 28 | +Every Fossil repository maintains a list of the hash names of | |
| 29 | 29 | "shunned" artifacts. |
| 30 | 30 | Fossil will refuse to push or pull any shunned artifact. |
| 31 | 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | 32 | itself) are removed from the |
| 33 | 33 | repository whenever the repository is reconstructed using the |
| 34 | 34 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -23,11 +23,11 @@ | |
| 23 | <h2>Shunning</h2> |
| 24 | |
| 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | a repository. |
| 27 | |
| 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | "shunned" artifacts. |
| 30 | Fossil will refuse to push or pull any shunned artifact. |
| 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | itself) are removed from the |
| 33 | repository whenever the repository is reconstructed using the |
| 34 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -23,11 +23,11 @@ | |
| 23 | <h2>Shunning</h2> |
| 24 | |
| 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | a repository. |
| 27 | |
| 28 | Every Fossil repository maintains a list of the hash names of |
| 29 | "shunned" artifacts. |
| 30 | Fossil will refuse to push or pull any shunned artifact. |
| 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | itself) are removed from the |
| 33 | repository whenever the repository is reconstructed using the |
| 34 |
+14
-14
| --- www/sync.wiki | ||
| +++ www/sync.wiki | ||
| @@ -4,23 +4,23 @@ | ||
| 4 | 4 | content between two Fossil repositories.</p> |
| 5 | 5 | |
| 6 | 6 | <h2>1.0 Overview</h2> |
| 7 | 7 | |
| 8 | 8 | <p>The global state of a fossil repository consists of an unordered |
| 9 | -collection of artifacts. Each artifact is identified by its SHA1 hash | |
| 10 | -expressed as a 40-character lower-case hexadecimal string. | |
| 9 | +collection of artifacts. Each artifact is identified by a cryptographic | |
| 10 | +hash of its content, expressed as a lower-case hexadecimal string. | |
| 11 | 11 | Synchronization is the process of sharing artifacts between |
| 12 | 12 | servers so that all servers have copies of all artifacts. Because |
| 13 | 13 | artifacts are unordered, the order in which artifacts are received |
| 14 | -at a server is inconsequential. It is assumed that the SHA1 hashes | |
| 15 | -of artifacts are unique - that every artifact has a different SHA1 hash. | |
| 14 | +at a server is inconsequential. It is assumed that the hash names | |
| 15 | +of artifacts are unique - that every artifact has a different hash. | |
| 16 | 16 | To a first approximation, synchronization proceeds by sharing lists |
| 17 | -SHA1 hashes of available artifacts, then sharing those artifacts that | |
| 18 | -are not found on one side or the other of the connection. In practice, | |
| 19 | -a repository might contain millions of artifacts. The list of | |
| 20 | -SHA1 hashes for this many artifacts can be large. So optimizations are | |
| 21 | -employed that usually reduce the number of SHA1 hashes that need to be | |
| 17 | +hash values for available artifacts, then sharing the content of artifacts | |
| 18 | +whose names are missing from one side or the other of the connection. | |
| 19 | +In practice, a repository might contain millions of artifacts. The list of | |
| 20 | +hash names for this many artifacts can be large. So optimizations are | |
| 21 | +employed that usually reduce the number of hashes that need to be | |
| 22 | 22 | shared to a few hundred.</p> |
| 23 | 23 | |
| 24 | 24 | <p>Each repository also has local state. The local state determines |
| 25 | 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | 26 | and similar information that varies from one repository to another. |
| @@ -198,11 +198,11 @@ | ||
| 198 | 198 | terminates the file card. |
| 199 | 199 | </p> |
| 200 | 200 | |
| 201 | 201 | <p>The first argument of a file card is the ID of the artifact that |
| 202 | 202 | is being transferred. The artifact ID is the lower-case hexadecimal |
| 203 | -representation of the SHA1 hash of the artifact. | |
| 203 | +representation of the name hash for the artifact. | |
| 204 | 204 | The last argument of the file card is the number of bytes of |
| 205 | 205 | payload that immediately follow the file card. If the file |
| 206 | 206 | card has only two arguments, that means the payload is the |
| 207 | 207 | complete content of the artifact. If the file card has three |
| 208 | 208 | arguments, then the payload is a delta and second argument is |
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | <b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br> |
| 232 | 232 | </blockquote> |
| 233 | 233 | |
| 234 | 234 | <p>The first argument of the cfile card is the ID of the artifact that |
| 235 | 235 | is being transferred. The artifact ID is the lower-case hexadecimal |
| 236 | -representation of the SHA1 hash of the artifact. The second argument of | |
| 236 | +representation of the name hash for the artifact. The second argument of | |
| 237 | 237 | the cfile card is the original size in bytes of the artifact. The last |
| 238 | 238 | argument of the cfile card is the number of compressed bytes of payload |
| 239 | 239 | that immediately follow the cfile card. If the cfile card has only |
| 240 | 240 | three arguments, that means the payload is the complete content of the |
| 241 | 241 | artifact. If the cfile card has four arguments, then the payload is a |
| @@ -271,11 +271,11 @@ | ||
| 271 | 271 | <b>uvfile</b> <i>name mtime hash size flags</i> <b>\n</b> <i>content</i> |
| 272 | 272 | </blockquote> |
| 273 | 273 | |
| 274 | 274 | <p>The <i>name</i> field is the name of the unversioned file. The |
| 275 | 275 | <i>mtime</i> is the last modification time of the file in seconds |
| 276 | -since 1970. The <i>hash</i> field is the SHA1 hash of the content | |
| 276 | +since 1970. The <i>hash</i> field is the hash of the content | |
| 277 | 277 | for the unversioned file, or "<b>-</b>" for deleted content. |
| 278 | 278 | The <i>size</i> field is the (uncompressed) size of the content |
| 279 | 279 | in bytes. The <i>flags</i> field is an integer which is interpreted |
| 280 | 280 | as an array of bits. The 0x0004 bit of <i>flags</i> indicates that |
| 281 | 281 | the <i>content</i> is to be omitted. The content might be omitted if |
| @@ -409,12 +409,12 @@ | ||
| 409 | 409 | </blockquote> |
| 410 | 410 | |
| 411 | 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | 413 | in seconds since 1970. |
| 414 | -The <i>hash</i> is the SHA1 hash of the unversioned file content, or | |
| 415 | -"<b>-</b>" if the file has been deleted. | |
| 414 | +The <i>hash</i> is the SHA1 or SHA3-256 hash of the unversioned file | |
| 415 | +content, or "<b>-</b>" if the file has been deleted. | |
| 416 | 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | 417 | |
| 418 | 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 | 419 | does not match, it sends uvigot cards for every unversioned file that it |
| 420 | 420 | holds. The client will use this information to figure out which |
| 421 | 421 |
| --- www/sync.wiki | |
| +++ www/sync.wiki | |
| @@ -4,23 +4,23 @@ | |
| 4 | content between two Fossil repositories.</p> |
| 5 | |
| 6 | <h2>1.0 Overview</h2> |
| 7 | |
| 8 | <p>The global state of a fossil repository consists of an unordered |
| 9 | collection of artifacts. Each artifact is identified by its SHA1 hash |
| 10 | expressed as a 40-character lower-case hexadecimal string. |
| 11 | Synchronization is the process of sharing artifacts between |
| 12 | servers so that all servers have copies of all artifacts. Because |
| 13 | artifacts are unordered, the order in which artifacts are received |
| 14 | at a server is inconsequential. It is assumed that the SHA1 hashes |
| 15 | of artifacts are unique - that every artifact has a different SHA1 hash. |
| 16 | To a first approximation, synchronization proceeds by sharing lists |
| 17 | SHA1 hashes of available artifacts, then sharing those artifacts that |
| 18 | are not found on one side or the other of the connection. In practice, |
| 19 | a repository might contain millions of artifacts. The list of |
| 20 | SHA1 hashes for this many artifacts can be large. So optimizations are |
| 21 | employed that usually reduce the number of SHA1 hashes that need to be |
| 22 | shared to a few hundred.</p> |
| 23 | |
| 24 | <p>Each repository also has local state. The local state determines |
| 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | and similar information that varies from one repository to another. |
| @@ -198,11 +198,11 @@ | |
| 198 | terminates the file card. |
| 199 | </p> |
| 200 | |
| 201 | <p>The first argument of a file card is the ID of the artifact that |
| 202 | is being transferred. The artifact ID is the lower-case hexadecimal |
| 203 | representation of the SHA1 hash of the artifact. |
| 204 | The last argument of the file card is the number of bytes of |
| 205 | payload that immediately follow the file card. If the file |
| 206 | card has only two arguments, that means the payload is the |
| 207 | complete content of the artifact. If the file card has three |
| 208 | arguments, then the payload is a delta and second argument is |
| @@ -231,11 +231,11 @@ | |
| 231 | <b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br> |
| 232 | </blockquote> |
| 233 | |
| 234 | <p>The first argument of the cfile card is the ID of the artifact that |
| 235 | is being transferred. The artifact ID is the lower-case hexadecimal |
| 236 | representation of the SHA1 hash of the artifact. The second argument of |
| 237 | the cfile card is the original size in bytes of the artifact. The last |
| 238 | argument of the cfile card is the number of compressed bytes of payload |
| 239 | that immediately follow the cfile card. If the cfile card has only |
| 240 | three arguments, that means the payload is the complete content of the |
| 241 | artifact. If the cfile card has four arguments, then the payload is a |
| @@ -271,11 +271,11 @@ | |
| 271 | <b>uvfile</b> <i>name mtime hash size flags</i> <b>\n</b> <i>content</i> |
| 272 | </blockquote> |
| 273 | |
| 274 | <p>The <i>name</i> field is the name of the unversioned file. The |
| 275 | <i>mtime</i> is the last modification time of the file in seconds |
| 276 | since 1970. The <i>hash</i> field is the SHA1 hash of the content |
| 277 | for the unversioned file, or "<b>-</b>" for deleted content. |
| 278 | The <i>size</i> field is the (uncompressed) size of the content |
| 279 | in bytes. The <i>flags</i> field is an integer which is interpreted |
| 280 | as an array of bits. The 0x0004 bit of <i>flags</i> indicates that |
| 281 | the <i>content</i> is to be omitted. The content might be omitted if |
| @@ -409,12 +409,12 @@ | |
| 409 | </blockquote> |
| 410 | |
| 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | in seconds since 1970. |
| 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | "<b>-</b>" if the file has been deleted. |
| 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | |
| 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 | does not match, it sends uvigot cards for every unversioned file that it |
| 420 | holds. The client will use this information to figure out which |
| 421 |
| --- www/sync.wiki | |
| +++ www/sync.wiki | |
| @@ -4,23 +4,23 @@ | |
| 4 | content between two Fossil repositories.</p> |
| 5 | |
| 6 | <h2>1.0 Overview</h2> |
| 7 | |
| 8 | <p>The global state of a fossil repository consists of an unordered |
| 9 | collection of artifacts. Each artifact is identified by a cryptographic |
| 10 | hash of its content, expressed as a lower-case hexadecimal string. |
| 11 | Synchronization is the process of sharing artifacts between |
| 12 | servers so that all servers have copies of all artifacts. Because |
| 13 | artifacts are unordered, the order in which artifacts are received |
| 14 | at a server is inconsequential. It is assumed that the hash names |
| 15 | of artifacts are unique - that every artifact has a different hash. |
| 16 | To a first approximation, synchronization proceeds by sharing lists |
| 17 | hash values for available artifacts, then sharing the content of artifacts |
| 18 | whose names are missing from one side or the other of the connection. |
| 19 | In practice, a repository might contain millions of artifacts. The list of |
| 20 | hash names for this many artifacts can be large. So optimizations are |
| 21 | employed that usually reduce the number of hashes that need to be |
| 22 | shared to a few hundred.</p> |
| 23 | |
| 24 | <p>Each repository also has local state. The local state determines |
| 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | and similar information that varies from one repository to another. |
| @@ -198,11 +198,11 @@ | |
| 198 | terminates the file card. |
| 199 | </p> |
| 200 | |
| 201 | <p>The first argument of a file card is the ID of the artifact that |
| 202 | is being transferred. The artifact ID is the lower-case hexadecimal |
| 203 | representation of the name hash for the artifact. |
| 204 | The last argument of the file card is the number of bytes of |
| 205 | payload that immediately follow the file card. If the file |
| 206 | card has only two arguments, that means the payload is the |
| 207 | complete content of the artifact. If the file card has three |
| 208 | arguments, then the payload is a delta and second argument is |
| @@ -231,11 +231,11 @@ | |
| 231 | <b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br> |
| 232 | </blockquote> |
| 233 | |
| 234 | <p>The first argument of the cfile card is the ID of the artifact that |
| 235 | is being transferred. The artifact ID is the lower-case hexadecimal |
| 236 | representation of the name hash for the artifact. The second argument of |
| 237 | the cfile card is the original size in bytes of the artifact. The last |
| 238 | argument of the cfile card is the number of compressed bytes of payload |
| 239 | that immediately follow the cfile card. If the cfile card has only |
| 240 | three arguments, that means the payload is the complete content of the |
| 241 | artifact. If the cfile card has four arguments, then the payload is a |
| @@ -271,11 +271,11 @@ | |
| 271 | <b>uvfile</b> <i>name mtime hash size flags</i> <b>\n</b> <i>content</i> |
| 272 | </blockquote> |
| 273 | |
| 274 | <p>The <i>name</i> field is the name of the unversioned file. The |
| 275 | <i>mtime</i> is the last modification time of the file in seconds |
| 276 | since 1970. The <i>hash</i> field is the hash of the content |
| 277 | for the unversioned file, or "<b>-</b>" for deleted content. |
| 278 | The <i>size</i> field is the (uncompressed) size of the content |
| 279 | in bytes. The <i>flags</i> field is an integer which is interpreted |
| 280 | as an array of bits. The 0x0004 bit of <i>flags</i> indicates that |
| 281 | the <i>content</i> is to be omitted. The content might be omitted if |
| @@ -409,12 +409,12 @@ | |
| 409 | </blockquote> |
| 410 | |
| 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | in seconds since 1970. |
| 414 | The <i>hash</i> is the SHA1 or SHA3-256 hash of the unversioned file |
| 415 | content, or "<b>-</b>" if the file has been deleted. |
| 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | |
| 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 | does not match, it sends uvigot cards for every unversioned file that it |
| 420 | holds. The client will use this information to figure out which |
| 421 |
+5
-4
| --- www/tech_overview.wiki | ||
| +++ www/tech_overview.wiki | ||
| @@ -6,12 +6,12 @@ | ||
| 6 | 6 | <h2>1.0 Introduction</h2> |
| 7 | 7 | |
| 8 | 8 | At its lowest level, a Fossil repository consists of an unordered set |
| 9 | 9 | of immutable "artifacts". You might think of these artifacts as "files", |
| 10 | 10 | since in many cases the artifacts are exactly that. |
| 11 | -But other "control artifacts" | |
| 12 | -are also included in the mix. These control artifacts define the relationships | |
| 11 | +But other "structural artifacts" are also included in the mix. | |
| 12 | +These structural artifacts define the relationships | |
| 13 | 13 | between artifacts - which files go together to form a particular |
| 14 | 14 | version of the project, who checked in that version and when, what was |
| 15 | 15 | the check-in comment, what wiki pages are included with the project, what |
| 16 | 16 | are the edit histories of each wiki page, what bug reports or tickets are |
| 17 | 17 | included, who contributed to the evolution of each ticket, and so forth. |
| @@ -173,11 +173,12 @@ | ||
| 173 | 173 | the [/help/deconstruct | fossil deconstruct] |
| 174 | 174 | command. Individual artifacts can be extracted using the |
| 175 | 175 | [/help/artifact | fossil artifact] command. |
| 176 | 176 | When accessing the repository database using raw SQL and the |
| 177 | 177 | [/help/sqlite3 | fossil sql] command, the extension function |
| 178 | -"<tt>content()</tt>" with a single argument which is the SHA1 hash | |
| 178 | +"<tt>content()</tt>" with a single argument which is the SHA1 or | |
| 179 | +SHA3-256 hash | |
| 179 | 180 | of an artifact will return the complete undeleted and uncompressed |
| 180 | 181 | content of that artifact. |
| 181 | 182 | |
| 182 | 183 | Going the other way, the [/help/reconstruct | fossil reconstruct] |
| 183 | 184 | command will scan a directory hierarchy and add all files found to |
| @@ -278,11 +279,11 @@ | ||
| 278 | 279 | project - is intended to be an append-only database. In other words, |
| 279 | 280 | new artifacts can be added but artifacts can never be removed. But |
| 280 | 281 | it sometimes happens that inappropriate content is mistakenly or |
| 281 | 282 | maliciously added to a repository. The only way to get rid of |
| 282 | 283 | the undesired content is to [./shunning.wiki | "shun"] it. |
| 283 | -The "shun" table in the repository database records the SHA1 hash of | |
| 284 | +The "shun" table in the repository database records the hash values for | |
| 284 | 285 | all shunned artifacts. |
| 285 | 286 | |
| 286 | 287 | The shun table can be pushed or pulled using |
| 287 | 288 | the [/help/config | fossil config] command with the "shun" AREA argument. |
| 288 | 289 | The shun table is also copied during a [/help/clone | clone]. |
| 289 | 290 |
| --- www/tech_overview.wiki | |
| +++ www/tech_overview.wiki | |
| @@ -6,12 +6,12 @@ | |
| 6 | <h2>1.0 Introduction</h2> |
| 7 | |
| 8 | At its lowest level, a Fossil repository consists of an unordered set |
| 9 | of immutable "artifacts". You might think of these artifacts as "files", |
| 10 | since in many cases the artifacts are exactly that. |
| 11 | But other "control artifacts" |
| 12 | are also included in the mix. These control artifacts define the relationships |
| 13 | between artifacts - which files go together to form a particular |
| 14 | version of the project, who checked in that version and when, what was |
| 15 | the check-in comment, what wiki pages are included with the project, what |
| 16 | are the edit histories of each wiki page, what bug reports or tickets are |
| 17 | included, who contributed to the evolution of each ticket, and so forth. |
| @@ -173,11 +173,12 @@ | |
| 173 | the [/help/deconstruct | fossil deconstruct] |
| 174 | command. Individual artifacts can be extracted using the |
| 175 | [/help/artifact | fossil artifact] command. |
| 176 | When accessing the repository database using raw SQL and the |
| 177 | [/help/sqlite3 | fossil sql] command, the extension function |
| 178 | "<tt>content()</tt>" with a single argument which is the SHA1 hash |
| 179 | of an artifact will return the complete undeleted and uncompressed |
| 180 | content of that artifact. |
| 181 | |
| 182 | Going the other way, the [/help/reconstruct | fossil reconstruct] |
| 183 | command will scan a directory hierarchy and add all files found to |
| @@ -278,11 +279,11 @@ | |
| 278 | project - is intended to be an append-only database. In other words, |
| 279 | new artifacts can be added but artifacts can never be removed. But |
| 280 | it sometimes happens that inappropriate content is mistakenly or |
| 281 | maliciously added to a repository. The only way to get rid of |
| 282 | the undesired content is to [./shunning.wiki | "shun"] it. |
| 283 | The "shun" table in the repository database records the SHA1 hash of |
| 284 | all shunned artifacts. |
| 285 | |
| 286 | The shun table can be pushed or pulled using |
| 287 | the [/help/config | fossil config] command with the "shun" AREA argument. |
| 288 | The shun table is also copied during a [/help/clone | clone]. |
| 289 |
| --- www/tech_overview.wiki | |
| +++ www/tech_overview.wiki | |
| @@ -6,12 +6,12 @@ | |
| 6 | <h2>1.0 Introduction</h2> |
| 7 | |
| 8 | At its lowest level, a Fossil repository consists of an unordered set |
| 9 | of immutable "artifacts". You might think of these artifacts as "files", |
| 10 | since in many cases the artifacts are exactly that. |
| 11 | But other "structural artifacts" are also included in the mix. |
| 12 | These structural artifacts define the relationships |
| 13 | between artifacts - which files go together to form a particular |
| 14 | version of the project, who checked in that version and when, what was |
| 15 | the check-in comment, what wiki pages are included with the project, what |
| 16 | are the edit histories of each wiki page, what bug reports or tickets are |
| 17 | included, who contributed to the evolution of each ticket, and so forth. |
| @@ -173,11 +173,12 @@ | |
| 173 | the [/help/deconstruct | fossil deconstruct] |
| 174 | command. Individual artifacts can be extracted using the |
| 175 | [/help/artifact | fossil artifact] command. |
| 176 | When accessing the repository database using raw SQL and the |
| 177 | [/help/sqlite3 | fossil sql] command, the extension function |
| 178 | "<tt>content()</tt>" with a single argument which is the SHA1 or |
| 179 | SHA3-256 hash |
| 180 | of an artifact will return the complete undeleted and uncompressed |
| 181 | content of that artifact. |
| 182 | |
| 183 | Going the other way, the [/help/reconstruct | fossil reconstruct] |
| 184 | command will scan a directory hierarchy and add all files found to |
| @@ -278,11 +279,11 @@ | |
| 279 | project - is intended to be an append-only database. In other words, |
| 280 | new artifacts can be added but artifacts can never be removed. But |
| 281 | it sometimes happens that inappropriate content is mistakenly or |
| 282 | maliciously added to a repository. The only way to get rid of |
| 283 | the undesired content is to [./shunning.wiki | "shun"] it. |
| 284 | The "shun" table in the repository database records the hash values for |
| 285 | all shunned artifacts. |
| 286 | |
| 287 | The shun table can be pushed or pulled using |
| 288 | the [/help/config | fossil config] command with the "shun" AREA argument. |
| 289 | The shun table is also copied during a [/help/clone | clone]. |
| 290 |
+2
-1
| --- www/theory1.wiki | ||
| +++ www/theory1.wiki | ||
| @@ -38,11 +38,12 @@ | ||
| 38 | 38 | been checked into the Fossil repository. Call these "content artifacts". |
| 39 | 39 | Other artifacts, known as |
| 40 | 40 | "control artifacts", contain ASCII text in a particular format that |
| 41 | 41 | defines relationships between other artifacts, such as which |
| 42 | 42 | content artifacts that go together to form a particular version of the |
| 43 | -project. Each artifact is named by its SHA1 hash and is thus immutable. | |
| 43 | +project. Each artifact is named by its SHA1 or SHA3-256 hash and is | |
| 44 | +thus immutable. | |
| 44 | 45 | Artifacts can be added to the database but not removed (if we ignore |
| 45 | 46 | the exceptional case of [./shunning.wiki | shunning].) Repositories |
| 46 | 47 | synchronize by computing the union of their artifact sets. SQL and |
| 47 | 48 | relation theory play no role in any of this. |
| 48 | 49 | |
| 49 | 50 |
| --- www/theory1.wiki | |
| +++ www/theory1.wiki | |
| @@ -38,11 +38,12 @@ | |
| 38 | been checked into the Fossil repository. Call these "content artifacts". |
| 39 | Other artifacts, known as |
| 40 | "control artifacts", contain ASCII text in a particular format that |
| 41 | defines relationships between other artifacts, such as which |
| 42 | content artifacts that go together to form a particular version of the |
| 43 | project. Each artifact is named by its SHA1 hash and is thus immutable. |
| 44 | Artifacts can be added to the database but not removed (if we ignore |
| 45 | the exceptional case of [./shunning.wiki | shunning].) Repositories |
| 46 | synchronize by computing the union of their artifact sets. SQL and |
| 47 | relation theory play no role in any of this. |
| 48 | |
| 49 |
| --- www/theory1.wiki | |
| +++ www/theory1.wiki | |
| @@ -38,11 +38,12 @@ | |
| 38 | been checked into the Fossil repository. Call these "content artifacts". |
| 39 | Other artifacts, known as |
| 40 | "control artifacts", contain ASCII text in a particular format that |
| 41 | defines relationships between other artifacts, such as which |
| 42 | content artifacts that go together to form a particular version of the |
| 43 | project. Each artifact is named by its SHA1 or SHA3-256 hash and is |
| 44 | thus immutable. |
| 45 | Artifacts can be added to the database but not removed (if we ignore |
| 46 | the exceptional case of [./shunning.wiki | shunning].) Repositories |
| 47 | synchronize by computing the union of their artifact sets. SQL and |
| 48 | relation theory play no role in any of this. |
| 49 | |
| 50 |
+1
-1
| --- www/webpage-ex.md | ||
| +++ www/webpage-ex.md | ||
| @@ -123,10 +123,10 @@ | ||
| 123 | 123 | href='$ROOT/bigbloblist'>Example</a> |
| 124 | 124 | The largest objects in the repository. |
| 125 | 125 | |
| 126 | 126 | * <a target='_blank' class='exbtn' |
| 127 | 127 | href='$ROOT/hash-collisions'>Example</a> |
| 128 | - SHA1 prefix collisions | |
| 128 | + Hash prefix collisions | |
| 129 | 129 | |
| 130 | 130 | * <a target='_blank' class='exbtn' |
| 131 | 131 | href='$ROOT/sitemap'>Example</a> |
| 132 | 132 | The "sitemap" containing links to many other pages |
| 133 | 133 |
| --- www/webpage-ex.md | |
| +++ www/webpage-ex.md | |
| @@ -123,10 +123,10 @@ | |
| 123 | href='$ROOT/bigbloblist'>Example</a> |
| 124 | The largest objects in the repository. |
| 125 | |
| 126 | * <a target='_blank' class='exbtn' |
| 127 | href='$ROOT/hash-collisions'>Example</a> |
| 128 | SHA1 prefix collisions |
| 129 | |
| 130 | * <a target='_blank' class='exbtn' |
| 131 | href='$ROOT/sitemap'>Example</a> |
| 132 | The "sitemap" containing links to many other pages |
| 133 |
| --- www/webpage-ex.md | |
| +++ www/webpage-ex.md | |
| @@ -123,10 +123,10 @@ | |
| 123 | href='$ROOT/bigbloblist'>Example</a> |
| 124 | The largest objects in the repository. |
| 125 | |
| 126 | * <a target='_blank' class='exbtn' |
| 127 | href='$ROOT/hash-collisions'>Example</a> |
| 128 | Hash prefix collisions |
| 129 | |
| 130 | * <a target='_blank' class='exbtn' |
| 131 | href='$ROOT/sitemap'>Example</a> |
| 132 | The "sitemap" containing links to many other pages |
| 133 |
+4
-3
| --- www/whyusefossil.wiki | ||
| +++ www/whyusefossil.wiki | ||
| @@ -232,18 +232,19 @@ | ||
| 232 | 232 | </ul> |
| 233 | 233 | </ul> |
| 234 | 234 | <li><p><b>Why version control is important (reprise)</b> |
| 235 | 235 | <ol type="A"> |
| 236 | 236 | <li><p>Every check-in and every individual file has a unique name - its |
| 237 | - SHA1 hash. Team members can unambiguously identify any specific | |
| 237 | + SHA1 or SHA3-256 hash. Team members can unambiguously identify | |
| 238 | + any specific | |
| 238 | 239 | version of the overall project or any specific version of an |
| 239 | 240 | individual file. |
| 240 | 241 | <li><p>Any historical version of the whole project or of any individual |
| 241 | 242 | file can be easily recreated at any time and by any team member. |
| 242 | 243 | <li><p>Accidental changes to files can be detected by recomputing their |
| 243 | - SHA1 hash. | |
| 244 | - <li><p>Files of unknown origin can be identified using their SHA1 hash. | |
| 244 | + cryptographic hash. | |
| 245 | + <li><p>Files of unknown origin can be identified using their hash. | |
| 245 | 246 | <li><p>Developers are able to work in parallel, review each others work, |
| 246 | 247 | and easily merge their changes together. External revisions to |
| 247 | 248 | the baseline can be easily incorporated into the latest changes. |
| 248 | 249 | <li><p>Developers can follow experimental lines of development, then |
| 249 | 250 | revert back to an earlier stable version if the experiment does |
| 250 | 251 |
| --- www/whyusefossil.wiki | |
| +++ www/whyusefossil.wiki | |
| @@ -232,18 +232,19 @@ | |
| 232 | </ul> |
| 233 | </ul> |
| 234 | <li><p><b>Why version control is important (reprise)</b> |
| 235 | <ol type="A"> |
| 236 | <li><p>Every check-in and every individual file has a unique name - its |
| 237 | SHA1 hash. Team members can unambiguously identify any specific |
| 238 | version of the overall project or any specific version of an |
| 239 | individual file. |
| 240 | <li><p>Any historical version of the whole project or of any individual |
| 241 | file can be easily recreated at any time and by any team member. |
| 242 | <li><p>Accidental changes to files can be detected by recomputing their |
| 243 | SHA1 hash. |
| 244 | <li><p>Files of unknown origin can be identified using their SHA1 hash. |
| 245 | <li><p>Developers are able to work in parallel, review each others work, |
| 246 | and easily merge their changes together. External revisions to |
| 247 | the baseline can be easily incorporated into the latest changes. |
| 248 | <li><p>Developers can follow experimental lines of development, then |
| 249 | revert back to an earlier stable version if the experiment does |
| 250 |
| --- www/whyusefossil.wiki | |
| +++ www/whyusefossil.wiki | |
| @@ -232,18 +232,19 @@ | |
| 232 | </ul> |
| 233 | </ul> |
| 234 | <li><p><b>Why version control is important (reprise)</b> |
| 235 | <ol type="A"> |
| 236 | <li><p>Every check-in and every individual file has a unique name - its |
| 237 | SHA1 or SHA3-256 hash. Team members can unambiguously identify |
| 238 | any specific |
| 239 | version of the overall project or any specific version of an |
| 240 | individual file. |
| 241 | <li><p>Any historical version of the whole project or of any individual |
| 242 | file can be easily recreated at any time and by any team member. |
| 243 | <li><p>Accidental changes to files can be detected by recomputing their |
| 244 | cryptographic hash. |
| 245 | <li><p>Files of unknown origin can be identified using their hash. |
| 246 | <li><p>Developers are able to work in parallel, review each others work, |
| 247 | and easily merge their changes together. External revisions to |
| 248 | the baseline can be easily incorporated into the latest changes. |
| 249 | <li><p>Developers can follow experimental lines of development, then |
| 250 | revert back to an earlier stable version if the experiment does |
| 251 |